Dumped on 2021-05-19

Index of database - cic-dev-db


Schema core


Table: core.ad_audits

Действия пользователя

core.ad_audits Structure
F-Key Name Type Description
id bigint PRIMARY KEY DEFAULT nextval('core.auto_id_ad_audits'::regclass)

Идентификатор
fn_user integer

Пользователь
d_date timestamp with time zone

Дата события
c_data text

Дополнительные параметры
c_type text

Тип события
c_app_name text

Имя приложение
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД

Index - Schema core


Table: core.ad_mobile_devices

Информация о мобильных устройствах

core.ad_mobile_devices Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_user integer

Пользователь
d_date timestamp with time zone

Дата возникновения событий
b_debug boolean NOT NULL DEFAULT false

Режим отладки
c_architecture text

Архитектура устройства
c_phone_model text

Модель телефона
c_sdk text

Версия sdk
c_os text

Версия ОС
c_imei text

IMEI
c_version text

Версия приложения
dx_created timestamp with time zone NOT NULL DEFAULT now()

Создан в БД
n_version bigint

Index - Schema core


Table: core.ad_mobile_indicators

Показатели мобильного устройства

core.ad_mobile_indicators Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_user integer NOT NULL

Пользователь
d_date timestamp with time zone NOT NULL DEFAULT now()

Дата события
c_network_type text

Тип сети
b_isonline boolean NOT NULL DEFAULT false

Состояние подключения к сети интернет
n_ram bigint

Размер ОЗУ
n_used_ram bigint

Размер используемого ОЗУ
n_phone_memory bigint

Размер внутренней памяти
n_used_phone_memory bigint

Размер используемой внутренней памяти
n_sd_card_memory bigint

Размер внешней памяти
n_used_sd_card_memory bigint

Размер используемой внешей памяти
n_battery_level integer

Уровень заряда батареи
n_time integer

Смещение времени
dx_created timestamp with time zone DEFAULT now()

Создан в БД

Index - Schema core


Table: core.ad_tracking

Перемещение исполнителя

core.ad_tracking Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_user integer NOT NULL

Исполнитель
d_date timestamp with time zone NOT NULL DEFAULT now()

Дата
n_longitude numeric(20,15) NOT NULL

Долгота
n_latitude numeric(20,15) NOT NULL

Широта
c_network_status text

Тип сети
dx_created timestamp with time zone DEFAULT now()

Создан в БД

Index - Schema core


Table: core.cd_action_log

Логирование действий пользователей с данными. Полная информация

core.cd_action_log Structure
F-Key Name Type Description
id uuid NOT NULL DEFAULT uuid_generate_v4()
c_table_name text

Имя таблицы в которой произошли изменения
c_operation text

Тип операции, INSERT, UPDATE, DELETE
jb_old_value jsonb

Предыдущие данные
jb_new_value jsonb

Новые данные
c_user text

Учетная запись
d_date timestamp with time zone

Дата события

Index - Schema core


Table: core.cd_action_log_user

Логирование запросов пользователя

core.cd_action_log_user Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()
integer_id bigint

Идентификатор
uuid_id uuid

Идентификатор
c_action text NOT NULL

Имя таблицы
c_method text

Метод
d_date timestamp with time zone NOT NULL DEFAULT now()
core.pd_users.id f_user integer NOT NULL DEFAULT '-1'::integer

Пользователь
jb_data jsonb NOT NULL

Index - Schema core


Table: core.cd_attachments

Файлы

core.cd_attachments Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_type integer NOT NULL

Тип изображения
fn_result uuid NOT NULL

Результат
fn_route uuid NOT NULL

Маршрут
n_longitude numeric(20,15) NOT NULL

Долгота
n_latitude numeric(20,15) NOT NULL

Широта
c_notice text

Примечание
d_date timestamp with time zone NOT NULL

Дата создания
fn_file uuid NOT NULL

Файл
ba_data bytea

Превью
n_size integer

Размер превью
jb_data jsonb

JSON данные
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД
fn_point uuid

Index - Schema core


Table: core.cd_files

Файлы

core.cd_files Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
c_name text NOT NULL

Имя файла
d_date timestamp with time zone NOT NULL

Дата создания
c_mime text NOT NULL

MIME-тип
c_extension text NOT NULL

Расширение
ba_data bytea NOT NULL

Байты
n_size integer NOT NULL

Размер файла
jb_data jsonb

JSON данные
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД

Index - Schema core


Table: core.cd_notifications

Уведомления

core.cd_notifications Structure
F-Key Name Type Description
fn_user_to integer NOT NULL

Адресат
c_title text

Заголовок
c_message text

Сообщение
d_date timestamp with time zone NOT NULL

Создан
d_changed timestamp with time zone

Изменен
fn_user_from integer NOT NULL

От кого
b_readed boolean NOT NULL DEFAULT false

Прочитан
b_sended boolean NOT NULL DEFAULT false

Доставлено
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()
c_group text
jb_data jsonb

Дополнительные данные в уведомлениях

Index - Schema core


Table: core.cd_points

Точки

core.cd_points Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
dbo.ed_registr_pts.id f_registr_pts uuid

Учетный показатель
core.cd_routes.id f_route uuid NOT NULL

Маршрут
core.cs_point_types.id f_type integer NOT NULL

Тип точки
c_notice text

Примечание
c_info text

Информация
jb_data jsonb

JSON данные
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД
n_order integer NOT NULL

Сортировка
b_anomaly boolean NOT NULL DEFAULT false
sn_delete boolean NOT NULL DEFAULT false

Index - Schema core


Table: core.cd_results

Результат выполнения

core.cd_results Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_user_point uuid NOT NULL

Пользовательская точка
fn_point uuid NOT NULL

Точка маршрута
fn_type integer NOT NULL

Тип результат
fn_user integer NOT NULL

Пользователь
fn_route uuid NOT NULL

Маршрут
d_date timestamp with time zone NOT NULL

Дата создания
c_notice text

Примечание
b_warning boolean NOT NULL DEFAULT false

Предупреждение Дост./Недост.
jb_data jsonb

JSON данные
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД
b_check boolean

Подтверждено
d_date_check timestamp with time zone

Дата подтверждения
n_manual_longitude numeric(20,15)

Долгота указанная вручную
n_manual_latitude numeric(20,15)

Широта указанная вручную

Index - Schema core


Table: core.cd_route_history

История изменения статусов заданий

core.cd_route_history Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_route uuid NOT NULL

Задание
fn_status integer NOT NULL

Статус
fn_user integer NOT NULL

Пользователь
d_date timestamp with time zone NOT NULL

Дата изменения
c_notice text

Примечание
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД

Index - Schema core


Table: core.cd_routes

Маршруты

core.cd_routes Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
core.cs_route_types.id f_type integer NOT NULL

Тип маршрута
c_number text NOT NULL

Номер маршрута
d_date timestamp with time zone NOT NULL DEFAULT now()

Дата создания
d_date_start date NOT NULL

Дата начала выполнения
d_date_end date NOT NULL

Дата завершения выполнения
c_notice text

Примечание
b_extended boolean NOT NULL

Продлен
d_extended date

Продлен до
jb_data jsonb

JSON данные
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД
n_order integer NOT NULL

Сортировка
b_draft boolean NOT NULL DEFAULT false

Является черновиком
core.cs_route_statuses.id f_status integer

Статус маршрута

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.cd_settings

Настройки

core.cd_settings Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cd_settings'::regclass)

Идентификатор
c_key text NOT NULL

Ключ
c_value text

Значение
core.cs_setting_types.id f_type integer NOT NULL

Тип
c_label text

Заголовок
c_summary text

Краткое описание
core.sd_divisions.id f_division integer

Регион
core.pd_users.id f_user integer

Пользователь
sn_delete boolean NOT NULL DEFAULT false

Удален
f_role integer

Index - Schema core


Table: core.cd_sys_log

Логирование job

core.cd_sys_log Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()
n_level_msg integer

0 - сообщение 1 - предупрежденние 2 - ошибка
d_timestamp timestamp with time zone
c_descr text

Index - Schema core


Table: core.cd_user_points

Точки

core.cd_user_points Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_point uuid

Точка
fn_user integer NOT NULL

Пользователь
fn_route uuid NOT NULL

Маршрут
fn_type integer NOT NULL

Тип
n_longitude numeric(20,15) NOT NULL

Долгота
n_latitude numeric(20,15) NOT NULL

Широта
c_notice text

Примечание
jb_data jsonb

JSON данные
b_check boolean
d_date_check timestamp with time zone

Дата подтверждения
dx_created timestamp with time zone DEFAULT now()

Дата записи в БД
d_date timestamp with time zone NOT NULL

Дата создания
c_telephone text

Новый номер телефона абонента
b_export boolean DEFAULT false

Index - Schema core


Table: core.cd_userinroutes

Исполнители задания

core.cd_userinroutes Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентифиактор
core.cd_routes.id f_route uuid NOT NULL

Маршрут
core.pd_users.id f_user integer NOT NULL

Пользователь
b_main boolean NOT NULL DEFAULT false

Является главным
dx_created timestamp with time zone DEFAULT now()

Дата создания в БД

Index - Schema core


Table: core.cs_attachment_types

Тип изображений

core.cs_attachment_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_attachment_types'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Index - Schema core


Table: core.cs_point_types

Тип точки

core.cs_point_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_point_types'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

Отключено
b_disabled boolean NOT NULL DEFAULT false

Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.cs_result_types

Тип результат

core.cs_result_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_result_types'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Отключено
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено
c_code_out text

Код из внешней системы

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.cs_route_statuses

Тип результат

core.cs_route_statuses Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_route_statuses'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Приоритет статуса (чем больше число тем выше статус)
b_disabled boolean NOT NULL DEFAULT false

Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.cs_route_types

Тип маршрута

core.cs_route_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_route_types'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.cs_setting_types

Тип настройки

core.cs_setting_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_cs_setting_types'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.pd_accesses

Права доступа

core.pd_accesses Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_pd_accesses'::regclass)

Идентификатор
core.pd_users.id f_user integer

Пользователь
core.pd_roles.id f_role integer

Роль
c_name text

Табл./Предст./Функц.
c_criteria text

Серверный фильтр
c_path text

Путь в файловой системе
c_function text

Функция RPC или её часть
c_columns text

Запрещенные колонки
b_deletable boolean NOT NULL DEFAULT false

Разрешено удалени
b_creatable boolean NOT NULL DEFAULT false

Разрешено создание
b_editable boolean NOT NULL DEFAULT false

Разрешено редактирование
b_full_control boolean NOT NULL DEFAULT false

Дополнительный доступ
sn_delete boolean NOT NULL DEFAULT false

Удален

Index - Schema core


Table: core.pd_roles

Роли

core.pd_roles Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_pd_roles'::regclass)

Идентификатор
c_name text UNIQUE NOT NULL

Наименование
c_description text

Описание роли
n_weight integer NOT NULL

Приоритет
sn_delete boolean NOT NULL DEFAULT false

Удален

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.pd_userindivisions

Привязка пользователей к отделению или участку

core.pd_userindivisions Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_pd_userindivisions'::regclass)

Идентификатор
core.pd_users.id f_user integer NOT NULL

Пользователь
core.sd_divisions.id f_division integer

Отделение
core.sd_subdivisions.id f_subdivision integer

Участок
sn_delete boolean NOT NULL DEFAULT false

Признак удаленной записи

Index - Schema core


Table: core.pd_userinroles

Пользователи в ролях

core.pd_userinroles Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_pd_userinroles'::regclass)

Идентификатор
core.pd_users.id f_user integer NOT NULL

Пользователь
core.pd_roles.id f_role integer NOT NULL

Роль
sn_delete boolean NOT NULL DEFAULT false

Удален

Index - Schema core


Table: core.pd_users

Пользователи

core.pd_users Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_pd_users'::regclass)

Идентификатор
core.pd_users.id f_parent integer

Родитель
c_login text UNIQUE NOT NULL

Логин
c_password text

Пароль
fn_file uuid

Иконка
s_salt text

Salt
s_hash text

Hash
c_first_name text

Имя
c_imei text

IMEI
c_description text

Описание
b_disabled boolean NOT NULL DEFAULT false

Отключен
sn_delete boolean NOT NULL DEFAULT false

Удален
c_version text

Версия мобильного приложения
n_version bigint

Версия мобильного приложения - Число
c_last_name text

Фамилия
c_middle_name text

Отчество
c_phone text

Телефон
c_email text

Эл. почта
c_post text

Должность
c_tab_number text UNIQUE

Табельный номер
b_pgcrypto boolean
c_post_code text

Код должности

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


View: core.pv_users

Открытый список пользователей

core.pv_users Structure
F-Key Name Type Description
id integer
f_parent integer
c_login text
c_claims text
fn_file uuid
c_description text
c_first_name text
c_last_name text
c_middle_name text
c_imei text
c_phone text
c_email text
c_version text
n_version bigint
b_disabled boolean
c_main_divisions text
c_divisions text
c_subdivisions text
SELECT t.id
,
    t.f_parent
,
    t.c_login
,
    t.c_claims
,
    t.fn_file
,
    t.c_description
,
    t.c_first_name
,
    t.c_last_name
,
    t.c_middle_name
,
    t.c_imei
,
    t.c_phone
,
    t.c_email
,
    t.c_version
,
    t.n_version
,
    t.b_disabled
,
        CASE
            WHEN 
(t.c_main_divisions = '..'::text) THEN ''::text
            ELSE t.c_main_divisions
        END AS c_main_divisions
,
        CASE
            WHEN 
(t.c_divisions = '..'::text) THEN ''::text
            ELSE t.c_divisions
        END AS c_divisions
,
        CASE
            WHEN 
(t.c_subdivisions = '..'::text) THEN ''::text
            ELSE t.c_subdivisions
        END AS c_subdivisions
   
FROM ( WITH items AS 
     (
                 
      SELECT uid.f_user
           ,
                    COALESCE
           (d.f_division
                 , uid.f_division
           ) AS f_main_division
           ,
                        CASE
                            WHEN 
           (d.f_division IS NOT NULL) THEN uid.f_division
                            ELSE NULL::integer
                        END AS f_division
           ,
                    uid.f_subdivision
                   
        FROM (core.pd_userindivisions uid
                     
              JOIN core.sd_divisions d 
                ON (
                       (uid.f_division = d.id)
                 )
           )
                  
    ORDER BY uid.f_user
                
     )
         
SELECT u.id
     ,
            u.f_parent
     ,
            u.c_login
     ,
            concat
     ('.'
           , (
            SELECT string_agg
                 (t_1.c_name
                       ,'.'::text
                 ) AS string_agg
                   
              FROM (
                  SELECT r.c_name
                           
                    FROM (core.pd_userinroles uir
                             
                          JOIN core.pd_roles r 
                            ON (
                                   (uir.f_role = r.id)
                             )
                       )
                          
                   WHERE (uir.f_user = u.id)
                          
                ORDER BY r.n_weight DESC
                 ) t_1
           )
           ,'.'
     ) AS c_claims
     ,
            u.fn_file
     ,
            u.c_description
     ,
            u.c_first_name
     ,
            u.c_last_name
     ,
            u.c_middle_name
     ,
            u.c_imei
     ,
            u.c_phone
     ,
            u.c_email
     ,
            u.c_version
     ,
            u.n_version
     ,
            u.b_disabled
     ,
            concat
     ('.'
           , (
            SELECT string_agg
                 (
                       (t_1.f_main_division)::text
                       ,'.'::text
                 ) AS string_agg
                   
              FROM (
                  SELECT DISTINCT i.f_main_division
                           
                    FROM items i
                          
                   WHERE (
                             (i.f_user = u.id)
                           AND (i.f_main_division IS NOT NULL)
                       )
                 ) t_1
           )
           ,'.'
     ) AS c_main_divisions
     ,
            concat
     ('.'
           , (
            SELECT string_agg
                 (
                       (t_1.f_division)::text
                       ,'.'::text
                 ) AS string_agg
                   
              FROM (
                  SELECT DISTINCT i.f_division
                           
                    FROM items i
                          
                   WHERE (
                             (i.f_user = u.id)
                           AND (i.f_division IS NOT NULL)
                       )
                 ) t_1
           )
           ,'.'
     ) AS c_divisions
     ,
            concat
     ('.'
           , (
            SELECT string_agg
                 (
                       (t_1.f_subdivision)::text
                       ,'.'::text
                 ) AS string_agg
                   
              FROM (
                  SELECT DISTINCT i.f_subdivision
                           
                    FROM items i
                          
                   WHERE (
                             (i.f_user = u.id)
                           AND (i.f_subdivision IS NOT NULL)
                       )
                 ) t_1
           )
           ,'.'
     ) AS c_subdivisions
           
  FROM core.pd_users u
          
 WHERE (u.sn_delete = false)
) t;

Index - Schema core


Table: core.sd_client_errors

Клиентские ошибки

core.sd_client_errors Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
c_message text

Текст ошибки
c_code text

Код ошибки
d_created timestamp with time zone

Дата возникновения ошибки
fn_user integer

Идентификатор пользователя
c_version text

Версия приложения
c_platform text

Тип платформы
jb_data jsonb

Прочии данные
dx_date timestamp with time zone DEFAULT now()

Дата записи на сервере

Index - Schema core


Table: core.sd_digests

Журнал версий

core.sd_digests Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_sd_digests'::regclass)

Идентификатор
c_version text NOT NULL

Версия
c_description text

Описание
core.sd_divisions.id f_division integer

Отделение
b_hidden boolean NOT NULL DEFAULT false

Скрыт
ba_file bytea NOT NULL

Файл для обновления
dx_created timestamp with time zone NOT NULL DEFAULT now()
n_version bigint

Номер версии

Index - Schema core


Table: core.sd_divisions

Отделения

core.sd_divisions Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_sd_divisions'::regclass)

Идентификатор
core.sd_divisions.id f_division integer

Вышестоящее отделение
c_name text NOT NULL

Наименование
c_dep_code text

Код отделения (филиала)
n_code integer

Код
b_disabled boolean NOT NULL DEFAULT false

Отключено
n_longitude numeric
n_latitude numeric
c_phone text

Для возможности осуществления вызова в экстренной ситуации

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.sd_subdivisions

Участки

core.sd_subdivisions Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('core.auto_id_sd_subdivisions'::regclass)

Идентификатор
core.sd_divisions.id f_division integer NOT NULL

Отделение
n_code integer

Код
c_name text NOT NULL

Наименование
b_disabled boolean NOT NULL DEFAULT false

Отключено
c_dep_code text

Текстовый код

Tables referencing this one via Foreign Key Constraints:

Index - Schema core


Table: core.sd_table_change

Изменение состояния таблицы

core.sd_table_change Structure
F-Key Name Type Description
c_table_name text UNIQUE#1 NOT NULL

Имя таблицы
n_change double precision NOT NULL

Версия изменения
core.pd_users.id f_user integer UNIQUE#1
id bigserial PRIMARY KEY

Index - Schema core


Table: core.sd_table_change_ref

Зависимость таблиц состояний

core.sd_table_change_ref Structure
F-Key Name Type Description
id smallint PRIMARY KEY DEFAULT nextval('core.sd_table_change_ref_id_seq'::regclass)
c_table_name text NOT NULL

Таблица
c_table_name_ref text NOT NULL

Зависимая таблица

Index - Schema core


Table: core.sd_table_states

Состояние таблиц

core.sd_table_states Structure
F-Key Name Type Description
id bigserial PRIMARY KEY
core.pd_users.id f_user integer NOT NULL
c_table_name text NOT NULL
jb_data jsonb

Index - Schema core


View: core.sv_objects

core.sv_objects Structure
F-Key Name Type Description
table_name character varying
table_type character varying
table_title character varying
primary_key character varying
table_comment character varying
table_schema information_schema.sql_identifier
SELECT table1.table_name
,
    table1.table_type
,
    table1.table_title
,
    table1.primary_key
,
    table1.table_comment
,
    table1.table_schema
   
FROM (
SELECT (t.table_name)::character varying AS table_name
     ,
            
     (t.table_type)::character varying AS table_type
     ,
            
     (pgd.description)::character varying AS table_title
     ,
            
     (cc.column_name)::character varying AS primary_key
     ,
            ''::character varying AS table_comment
     ,
            t.table_schema
           
  FROM (
           (
                 (
                       (information_schema.tables t
             
                     LEFT JOIN pg_statio_all_tables st 
                            ON (
                                   (st.relname = 
                                         (t.table_name)::name
                                   )
                             )
                       )
             
               LEFT JOIN pg_description pgd 
                      ON (
                             (
                                   (pgd.objoid = st.relid)
                                 AND (pgd.objsubid = 0)
                             )
                       )
                 )
             
         LEFT JOIN information_schema.table_constraints tc 
                ON (
                       (
                             (
                                   (t.table_name)::text = 
                                   (tc.table_name)::text
                             )
                           AND (
                                   (t.table_catalog)::text = 
                                   (tc.table_catalog)::text
                             )
                       )
                 )
           )
             
   LEFT JOIN information_schema.constraint_column_usage cc 
          ON (
                 (
                       (tc.constraint_name)::text = 
                       (cc.constraint_name)::text
                 )
           )
     )
          
 WHERE (
           (
                 (t.table_catalog)::text = 
                 (current_database
                       ()
                 )::text
           )
         AND (
                 (tc.constraint_type)::text = 'PRIMARY KEY'::text
           )
     )
        
 UNION
         
SELECT (t.table_name)::character varying AS table_name
     ,
            
     (t.table_type)::character varying AS table_type
     ,
            
     (pgd.description)::character varying AS table_title
     ,
            ''::character varying AS primary_key
     ,
            ''::character varying AS table_comment
     ,
            t.table_schema
           
  FROM (
           (information_schema.tables t
             
         LEFT JOIN pg_class pgc 
                ON (
                       (pgc.relname = 
                             (t.table_name)::name
                       )
                 )
           )
             
   LEFT JOIN pg_description pgd 
          ON (
                 (pgd.objoid = pgc.oid)
           )
     )
          
 WHERE (
           (
                 (t.table_type)::text = 'VIEW'::text
           )
         AND (
                 (t.table_catalog)::text = 
                 (current_database
                       ()
                 )::text
           )
     )
        
 UNION
         
SELECT (r.routine_name)::character varying AS table_name
     ,
            
     (r.routine_type)::character varying AS table_type
     ,
            
     (pgd.description)::character varying AS table_title
     ,
            ''::character varying AS primary_key
     ,
            ''::character varying AS table_comment
     ,
            r.routine_schema AS table_schema
           
  FROM (
           (information_schema.routines r
             
         LEFT JOIN pg_proc pgp 
                ON (
                       (pgp.proname = 
                             (r.routine_name)::name
                       )
                 )
           )
             
   LEFT JOIN pg_description pgd 
          ON (
                 (pgd.objoid = pgp.oid)
           )
     )
          
 WHERE (
           (r.routine_catalog)::text = 
           (current_database
                 ()
           )::text
     )
) table1
  
WHERE (
     (
           (table1.table_schema)::text <> 'pg_catalog'::text
     )
   AND (
           (table1.table_schema)::text <> 'information_schema'::text
     )
   AND (
           (table1.table_schema)::text <> 'public'::text
     )
);

Index - Schema core


View: core.sv_users

Системный список пользователей

core.sv_users Structure
F-Key Name Type Description
id integer
f_parent integer
c_login text
c_first_name text
c_last_name text
c_middle_name text
c_user_name text
c_password text
s_salt text
s_hash text
b_pgcrypto boolean
c_claims text
c_all_divisions text
b_disabled boolean
c_version text
n_version bigint
SELECT u.id
,
    u.f_parent
,
    u.c_login
,
    u.c_first_name
,
    u.c_last_name
,
    u.c_middle_name
,
    concat
(u.c_first_name
     ,' '
     , u.c_last_name
     ,' '
     , u.c_middle_name
) AS c_user_name
,
    u.c_password
,
    u.s_salt
,
    u.s_hash
,
    u.b_pgcrypto
,
    concat
('.'
     , (
      SELECT string_agg
           (t.c_name
                 ,'.'::text
           ) AS string_agg
           
        FROM (
            SELECT r.c_name
                   
              FROM (core.pd_userinroles uir
                     
                    JOIN core.pd_roles r 
                      ON (
                             (uir.f_role = r.id)
                       )
                 )
                  
             WHERE (uir.f_user = u.id)
                  
          ORDER BY r.n_weight DESC
           ) t
     )
     ,'.'
) AS c_claims
,
    
( WITH RECURSIVE tab_rec AS 
     (
                 
      SELECT sd_divisions.id AS id_parent
           ,
                    sd_divisions.id
           ,
                    sd_divisions.f_division
           ,
                    1 AS num
                   
        FROM core.sd_divisions
                  
       WHERE (sd_divisions.id IN 
                 (
                  SELECT pud.f_division
                           
                    FROM core.pd_userindivisions pud
                          
                   WHERE (pud.f_user = u.id)
                 )
           )
                
   UNION ALL
                 
      SELECT r_2.id_parent
           ,
                    d.id
           ,
                    d.f_division
           ,
                    
           (r_2.num + 1) AS num
                   
        FROM core.sd_divisions d
           ,
                    tab_rec r_2
                  
       WHERE (r_2.id = d.f_division)
                
     )
         
SELECT string_agg
     (
           (r_1.id)::text
           ,','::text
     ) AS string_agg
           
  FROM tab_rec r_1
) AS c_all_divisions
,
    u.b_disabled
,
    u.c_version
,
    u.n_version
   
FROM core.pd_users u
  
WHERE (u.sn_delete = false);

Index - Schema core


Function: core.cf_mui_cd_attachment(_id uuid)

Returns: SET OF record

Language: PLPGSQL

Получение "Вложения" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_attachments", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	RETURN QUERY select ad.c_name, f.c_mime, a.d_date, a.n_longitude, a.n_latitude, a.ba_data, f.ba_data as ba_file
	from core.cd_attachments as a
	INNER JOIN core.cd_files as f ON f.id = a.fn_file
	inner join core.cd_results as r ON a.fn_result = r.id
	inner join core.cd_points as p on r.fn_point = p.id
	inner join dbo.ed_registr_pts as rp ON rp.id = p.f_registr_pts
	inner join dbo.ss_address as ad ON ad.id = rp.f_address
	where a.id = _id;
END

Function: core.cf_mui_cd_attachments(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Вложений" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_attachments", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	IF _fn_user IS NOT NULL THEN	
		RETURN QUERY select a.id, f.c_name, f.c_mime, a.fn_type, a.fn_result, a.fn_route, a.fn_point, a.d_date, a.n_longitude, a.n_latitude, a.fn_file, a.c_notice, a.jb_data::text, a.dx_created, a.ba_data, a.n_size, null::bytea as ba_file, f.n_size as n_file_size
		from core.cd_userinroutes as uir
		INNER JOIN core.cd_attachments as a ON a.fn_route = uir.f_route
		INNER JOIN core.cd_files as f ON f.id = a.fn_file
		inner join core.cd_results as r ON r.id = a.fn_result
		where uir.f_user = _fn_user and r.fn_user = _fn_user and core.sf_is_mobile_route(uir.f_route);	
	ELSE
		RETURN QUERY select a.id, f.c_name, f.c_mime, a.fn_type, a.fn_result, a.fn_route, a.fn_point, a.d_date, a.n_longitude, a.n_latitude, a.fn_file, a.c_notice, a.jb_data::text, a.dx_created, a.ba_data, a.n_size, null::bytea as ba_file, f.n_size as n_file_size
		from core.cd_attachments as a
		INNER JOIN core.cd_files as f ON f.id = a.fn_file;
	END IF;
END

Function: core.cf_mui_cd_files(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Файлов" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_files", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	IF _fn_user IS NOT NULL THEN
		-- для файла специально указываем null, чтобы телефон не обрабатывал данные 
		RETURN QUERY select f.id, f.c_name, f.d_date, f.c_mime, f.c_extension, f.jb_data::text, null::bytea, f.n_size, f.dx_created 
		from core.cd_userinroutes as uir
		INNER JOIN core.cd_attachments as a ON a.fn_route = uir.f_route
		INNER JOIN core.cd_files as f ON f.id = a.fn_file
		inner join core.cd_results as r ON r.id = a.fn_result
		where uir.f_user = _fn_user and r.fn_user = _fn_user and core.sf_is_mobile_route(uir.f_route);
		
		--RETURN QUERY select f.id, f.c_name, f.d_date, f.c_mime, f.c_extension, f.jb_data::text, null::bytea, f.n_size, f.dx_created 
		--from core.cd_files as f
		--inner join core.cd_attachments as a ON a.fn_file = f.id
		--inner join core.cd_routes as r ON a.fn_route = r.id
		--inner join core.cd_results as rr ON rr.id = a.fn_result
		--where rr.fn_user = _fn_user or core.sf_is_mobile_route(r.id);
		
		--UNION
		
		--select f.id, f.c_name, f.d_date, f.c_mime, f.c_extension, f.jb_data::text, f.ba_data, f.n_size, f.dx_created 
		--from core.cd_files as f
		--where f.id in (select u.fn_file from core.pd_users as u where u.id = _fn_user) or 
			 --f.id in (select fb.fn_question_file from core.cd_feedbacks as fb where fb.fn_user = _fn_user and fb.fn_question_file is not null)
			--or f.id in (select fb.fn_answer_file from core.cd_feedbacks as fb where fb.fn_user = _fn_user and fb.fn_answer_file is not null);
	ELSE
		RETURN QUERY select f.id, f.c_name, f.d_date, f.c_mime, f.c_extension, f.jb_data::text, null::bytea, f.n_size, f.dx_created 
		from core.cd_files as f;
	END IF;
END

Function: core.cf_mui_cd_notifications(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Уведомлений" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_notifications", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY 
	select n.id, n.c_title, n.c_message, n.d_date
	from core.cd_notifications as n
    where n.fn_user_to = _fn_user or n.fn_user_from = _fn_user
	order by n.d_date desc;
END

Function: core.cf_mui_cd_points(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Точек маршрута" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_points", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select p.id, p.f_registr_pts, p.f_route, p.f_type, p.c_notice, p.c_info, p.jb_data::text, p.dx_created, p.n_order, p.b_anomaly, p.sn_delete
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_points as p ON p.f_route = uir.f_route
    INNER JOIN core.cd_routes as r ON r.id = p.f_route
	left join core.cs_route_statuses as rs ON r.f_status = rs.id
	where uir.f_user = _fn_user and core.sf_is_mobile_route(r.id);
END

Function: core.cf_mui_cd_results(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Результаты обхода" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_results", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	RETURN QUERY select r.id, r.fn_route, r.fn_point, r.fn_user_point, r.fn_type, r.fn_user, r.d_date, r.c_notice, r.b_warning, r.jb_data::text, r.dx_created, r.b_check, coalesce(r.n_manual_longitude, 0.0), coalesce(r.n_manual_latitude, 0.0)
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as rt ON rt.id = uir.f_route
    INNER JOIN core.cd_results as r ON r.fn_route = rt.id
	left join core.cs_route_statuses as rs ON rt.f_status = rs.id
	where uir.f_user = _fn_user and r.fn_user = _fn_user and core.sf_is_mobile_route(rt.id);
END

Function: core.cf_mui_cd_route_history(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Истории маршрутов" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_route_history", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select rh.id, rh.fn_route, rh.fn_status, rh.fn_user, rh.d_date, rh.c_notice, rh.dx_created
    from core.cd_userinroutes as uir
	LEFT JOIN core.cd_route_history as rh ON rh.fn_route = uir.f_route
	where uir.f_user = _fn_user and core.sf_is_mobile_route(uir.f_route);
END

Function: core.cf_mui_cd_routes(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Маршрутов" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_routes", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select r.id, r.f_type, r.c_number, r.d_date, r.d_date_start, r.d_date_end, r.c_notice, r.b_extended, r.d_extended, r.jb_data::text, r.dx_created,
	(select count(*) from core.cd_points as p where p.f_route = r.id) as n_count, r.n_order, r.b_draft 
    from core.cd_userinroutes as uir
    INNER JOIN core.cd_routes as r ON r.id = uir.f_route
	left join core.cs_route_statuses as rs ON r.f_status = rs.id
	where uir.f_user = _fn_user and core.sf_is_mobile_route(r.id); -- не старше текущей даты
END

Function: core.cf_mui_cd_user_points(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "Пользовательских точек" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_user_points", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select up.id, up.fn_point, up.fn_user, u.c_login as c_user, up.fn_route, up.fn_type, up.n_longitude, up.n_latitude, up.c_notice, up.jb_data::text, up.d_date_check, up.dx_created, up.d_date, up.c_telephone, false
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as rt ON rt.id = uir.f_route
    INNER JOIN core.cd_user_points as up ON up.fn_route = rt.id
    INNER JOIN core.pd_users as u ON up.fn_user = u.id
	left join core.cs_route_statuses as rs ON rt.f_status = rs.id
	where uir.f_user = _fn_user and up.fn_user = _fn_user and core.sf_is_mobile_route(rt.id);
END

Function: core.cf_mui_cd_userinroutes(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка "пользователей в маршрутах" мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_userinroutes", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select * from core.cd_userinroutes as cuir
    where cuir.f_route in (select DISTINCT r.id from core.cd_userinroutes as uir
    INNER JOIN core.cd_routes as r ON r.id = uir.f_route
	left join core.cs_route_statuses as rs ON r.f_status = rs.id
	where uir.f_user = _fn_user and core.sf_is_mobile_route(r.id));
END

Function: core.cf_mui_cs_attachment_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Типы вложений

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cd_attachment_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select at.id, at.c_name, at.c_const, at.n_order, at.b_default
	from core.cs_attachment_types as at
	where at.b_disabled = false;
END

Function: core.cf_mui_cs_point_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тип точки

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cs_point_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select pt.id, pt.c_name, pt.c_const, pt.n_order
	from core.cs_point_types as pt
	where pt.b_disabled = false;
END

Function: core.cf_mui_cs_result_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тип результат

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cs_result_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select rt.id, rt.c_name, rt.c_short_name, rt.c_const, rt.n_order
	from core.cs_result_types as rt
	where rt.b_disabled = false;
END

Function: core.cf_mui_cs_route_statuses(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тип результат

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cs_route_statuses", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select rs.id, rs.c_name, rs.c_const, rs.n_order
	from core.cs_route_statuses as rs
	where rs.b_disabled = false;
END

Function: core.cf_mui_cs_route_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тип маршрута

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_cs_route_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select rt.id, rt.c_name, rt.c_const, rt.n_order
	from core.cs_route_types as rt
	where rt.b_disabled = false;
END

Function: core.cf_mui_pd_users(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка пользователей мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_pd_users", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select u.id, u.f_parent, u.c_login, u.fn_file, concat(u.c_last_name, ' ', u.c_first_name, ' ', u.c_middle_name), u.c_description, u.b_disabled,
	(select string_agg(d.c_phone, ', ') from core.pd_userindivisions as uid
	inner join core.sd_divisions as d on uid.f_division = d.id
	where uid.f_user = _fn_user)
	from core.pd_users as u
    where u.id in (
    select distinct cuir.f_user from core.cd_userinroutes as cuir
    where cuir.f_route in (
    select r.id 
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as r ON r.id = uir.f_route
    where uir.f_user = _fn_user and core.sf_is_mobile_route(r.id))) OR u.id = _fn_user;
END

Function: core.cf_mui_sd_digests(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка версий мобильным приложением

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_sd_digests", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY select d.id, d.c_version, d.c_description, d.dx_created, d.n_version from core.sd_digests as d;
END

Function: core.cf_mui_sd_table_change(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Получение списка изменений для пользователя

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_sd_table_change", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_b_change boolean;
BEGIN
	select false into _b_change; -- значение по умолчанию

	select (case when c_value = 'true' then true else false end) into _b_change 
	from core.cd_settings
	where c_key = 'MBL_TABLE_CHANGE'
	limit 1;

	IF _b_change then 
		return query 
		select 
			tc.c_table_name,
			max(coalesce(tc.n_change, 0.0)) as n_change,
			max(tc.f_user) as f_user
		from core.sd_table_change as tc
		where tc.f_user is null or tc.f_user = _fn_user
		group by tc.c_table_name;
	else
		return query select null::text, 0.0::double precision, null::integer from core.sd_table_change as tc
		where tc.c_table_name = 'unknow';
	end if;
END

Function: core.cf_update_user_divisions(_user_id integer, _divisions json, _sub_divisions json)

Returns: integer

Language: PLPGSQL

Обновление Филиала/Отделения/Участка у пользователя

/**
* @params {integer} _user_id - идент. пользователя
* @params {json} _divisions - список отделений. Формат строки '[1,2]'
* @params {json} _sub_divisions - список участков. Формат строки '[1,2]'
*
* @returns {integer}
* 0 - ОК
*
* @example
* [{ "action": "cf_update_user_divisions", "method": "Query", "data": [{ "params": [_user_id, _divisions, _sub_divisions] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	delete from core.pd_userindivisions
	where f_user = _user_id;

	-- проверяем divisions
	IF (select count(*) from json_array_elements_text(_divisions)) > 0 THEN
		insert into core.pd_userindivisions(f_user, f_division, f_subdivision)
		SELECT _user_id, t.value::integer, null 
		FROM json_array_elements_text(_divisions) as t;
	END IF;
	
	-- проверяем sub_divisions
	IF (select count(*) from json_array_elements_text(_sub_divisions)) > 0 THEN
		insert into core.pd_userindivisions(f_user, f_division, f_subdivision)
		SELECT _user_id, (select f_division from core.sd_subdivisions where id = t.value::integer), t.value::integer 
		FROM json_array_elements_text(_sub_divisions) as t;
	END IF;
	
	RETURN 0;
END

Function: core.cft_cd_routes_update_history()

Returns: trigger

Language: PLPGSQL

Триггер. Обновление истории в маршрутах

DECLARE
	_f_route uuid;
	_f_status integer;
	_n_status_weight integer;
	_f_user integer;
BEGIN
	-- все вычисления производяться после выполнения операций
    IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
		select NEW.fn_route into _f_route;
		select NEW.fn_user into _f_user;
	ELSE	
		select OLD.fn_route into _f_route;
    END IF;
    
    select rs.id, rs.n_order into _f_status, _n_status_weight from core.cd_route_history as rh 
	inner join core.cs_route_statuses as rs ON rs.id = rh.fn_status
	where rh.fn_route = _f_route 
	order by rh.d_date desc, rs.n_order desc limit 1;
    
    IF ((_n_status_weight <= 1 OR _n_status_weight >= 1000) OR -- если статус меньше чем 1 или больше 1000, то это Диспетчер 
		(select count(*) from core.cd_userinroutes as uir
    	where uir.f_route = _f_route and uir.f_user = _f_user and uir.b_main) >= 1) THEN -- если это главный обходчик
    
		update core.cd_routes as r
		set f_status = _f_status
		where r.id = _f_route;
	
	END IF;

    RETURN NULL; -- result is ignored since this is an AFTER trigger
END

Function: core.cft_log_action()

Returns: trigger

Language: PLPGSQL

Триггер. Процедура логирования действия пользователя

BEGIN
	IF (TG_OP = 'UPDATE') THEN
		INSERT INTO core.cd_action_log(c_table_name, c_operation, jb_old_value, jb_new_value, c_user, d_date)
		VALUES (TG_TABLE_NAME, TG_OP, row_to_json(OLD), row_to_json(NEW), USER, clock_timestamp());
        RETURN NEW;
    ELSIF (TG_OP = 'DELETE') THEN
		INSERT INTO core.cd_action_log(c_table_name, c_operation, jb_old_value, c_user, d_date)
		VALUES (TG_TABLE_NAME, TG_OP, row_to_json(OLD), USER, clock_timestamp());
        RETURN OLD;
    ELSIF (TG_OP = 'INSERT') THEN
		INSERT INTO core.cd_action_log(c_table_name, c_operation, jb_new_value, c_user, d_date)
		VALUES (TG_TABLE_NAME, TG_OP, row_to_json(NEW), USER, clock_timestamp());
	    RETURN NEW;
    ELSE
        RETURN OLD;
	END IF;

EXCEPTION
	WHEN OTHERS
    THEN
		INSERT INTO core.cd_sys_log(d_timestamp, c_descr)
		VALUES(clock_timestamp(), 'Непредвиденная ошибка логирования');
    RETURN OLD;
END;

Function: core.cft_pd_users_update_version()

Returns: trigger

Language: PLPGSQL

Триггер. Обновление версии в пользователях

BEGIN
    IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
		UPDATE core.pd_users as u
		set n_version = core.sf_version_to_number(NEW.c_version),
		c_version = NEW.c_version
		where u.id = NEW.fn_user;
    END IF;

    RETURN NEW;
END

Function: core.cft_sd_digest_update_version()

Returns: trigger

Language: PLPGSQL

Триггер. Обновления версии приложения

BEGIN
    IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
		NEW.n_version = core.sf_version_to_number(NEW.c_version);
    END IF;

    RETURN NEW;
END

Function: core.cft_table_state_change_version()

Returns: trigger

Language: PLPGSQL

Триггер. Обновление справочной версии

DECLARE
	_users json;
BEGIN
	if TG_OP = 'DELETE' and to_jsonb(OLD) ? 'fn_user' then
		select concat('[{"f_user":', OLD.fn_user::text ,'}]')::json into _users;
	else
		if TG_OP != 'DELETE' and to_jsonb(NEW) ? 'fn_user' then
			select concat('[{"f_user":', NEW.fn_user::text ,'}]')::json into _users;
		else
			select '[{"f_user":null}]'::json into _users;
		end if;
	end if;
			
	perform core.sf_table_change_update(t.c_table_name_ref, (u.value#>>'{f_user}')::integer)
	from json_array_elements(_users) as u
	left join (select TG_TABLE_NAME as c_table_name_ref
				UNION
				select c_table_name_ref
				from core.sd_table_change_ref
				where c_table_name = TG_TABLE_NAME) as t on 1=1;

    RETURN null;
END

Function: core.pf_accesses(n_user_id integer)

Returns: SET OF record

Language: PLPGSQL

Системная функция. Получение прав доступа для пользователя. Используется NodeJS

/**
* @params {integer} n_user_id - иден. пользователя
*/
BEGIN
	RETURN QUERY select * from (select 
        a.c_name,
        a.c_criteria,
        a.c_path,
        a.c_function,
        a.c_columns,
        a.b_editable, 
        a.b_deletable, 
        a.b_creatable, 
        a.b_full_control, 
        core.sf_accesses(r.c_name, u.id, u.c_claims, a.f_user) as access 
    from core.pd_accesses as a
    left join core.sv_users as u on n_user_id = u.id
    left join core.pd_roles as r on a.f_role = r.id
    where a.sn_delete = false) as t 
	where t.access > 0;
END; 

Function: core.pf_update_user_roles(_user_id integer, _claims json)

Returns: integer

Language: PLPGSQL

Обновление ролей у пользователя

/**
* @params {integer} _user_id - идент. пользователя
* @params {json} _claims - роли в виде строки '["manager", "inspector"]'
*
* @returns {integer} идент. пользователя
*/
BEGIN
	delete from core.pd_userinroles
	where f_user = _user_id;

	insert into core.pd_userinroles(f_user, f_role, sn_delete)
	SELECT _user_id, (select id from core.pd_roles where t.value = c_name), false 
	FROM json_array_elements_text(_claims) as t;
	
	RETURN _user_id;
END

Function: core.sf_accesses(c_role_name text, n_currentuser integer, c_claims text, n_user_id integer)

Returns: integer

Language: PLPGSQL

Системная функция для обработки прав. Для внешнего использования не применять

/**
* @params {text} c_role_name - имя роли в безопасности
* @params {integer} n_currentuser - идент. пользователя в безопасности
* @params {text} c_claims - список ролей
* @params {integer} n_user_id - иден. пользователя
* 
* @returns
* 0 - доступ запрещен
*/
BEGIN
    IF c_role_name is null and n_user_id is null then
		RETURN 1;
	ELSEIF (c_role_name is not null and c_claims is not null and POSITION(CONCAT('.', c_role_name, '.') IN c_claims) > 0) then
		RETURN 2;
	ELSEIF (c_role_name is not null and c_claims is not null and POSITION(CONCAT('.', c_role_name, '.') IN c_claims) > 0) then  
		RETURN 3;
	ELSEIF (c_role_name is null and n_currentuser = n_user_id) then
        RETURN 4;
    ELSEIF (c_role_name = 'anonymous' or n_user_id = -1) then
		RETURN 5;
	else
		RETURN 0;
	end if;
 END

Function: core.sf_build_version(status integer)

Returns: text

Language: PLV8

Генерация версии БД

var birthday = '2020-11-09';
	var newVersion = '1.' + Math.floor(Math.abs(new Date().getTime() - new Date(birthday).getTime()) / (1000 * 3600 * 24)) + '.' + status + '.'
											  + ((new Date().getHours() * 60) + new Date().getMinutes());
	return newVersion;

Function: core.sf_del_route(_route_id uuid)

Returns: integer

Language: PLPGSQL

Окончательное удаление маршрута без сохранения истории

/**
* @params {uuid} _route_id - идентификатор маршрута
* 
* @returns {integer} 0 - маршрут удален, 1 - ошибка при удалении
*/
DECLARE
	_result integer;
BEGIN	
	delete from core.cd_files
	where id IN (select fn_file from core.cd_attachments
	where fn_route = _route_id);
	
	delete from core.cd_attachments
	where fn_route = _route_id;

	delete from core.cd_results
	where fn_route = _route_id;
	
	delete from core.cd_user_points
	where fn_route = _route_id;

	delete from core.cd_route_history
	where fn_route = _route_id;
	
	delete from core.cd_userinroutes
	where f_route = _route_id;
	
	delete from dbo.ed_output_meter_readings
	where fn_route = _route_id;	
	
	delete from core.cd_points
	where f_route = _route_id;

	delete from core.cd_routes
	where id = _route_id;
	
  	RETURN 0;
END

Function: core.sf_finish_date(_d_date date)

Returns: boolean

Language: PLPGSQL

Проверка даты завершения маршрута, true - маршрут активный

/**
* @params {date} _d_date - дата
* @returns {boolean} false - маршрут завершен
*/
BEGIN
	RETURN (_d_date + interval '1 day') >= now();
END

Function: core.sf_get_version()

Returns: text

Language: PLPGSQL

Версия БД

/**
* @returns {text} версия базы данных
*/
DECLARE
	_ver text;
BEGIN
	SELECT c_value INTO _ver FROM core.cd_settings WHERE lower(c_key) = lower('DB_VERSION');
	RETURN _ver;
END

Function: core.sf_hard_reset_route(_route_id uuid)

Returns: integer

Language: PLPGSQL

Сброс результатов прохождния маршрута. Системная функция, не применять на production

/**
* @params {uuid} _route_id - идентификатор маршрута
* 
* @returns {integer} 0 - маршрут очищен
*/
BEGIN
	delete from dbo.ed_output_meter_readings
	where fn_route = _route_id;
	
	delete from dbo.ed_output_conn_seals
	where fn_route = _route_id;
	
	delete from core.cd_files
	where id IN (select fn_file from core.cd_attachments
	where fn_route = _route_id);
	
	delete from core.cd_attachments
	where fn_route = _route_id;
	
	delete from core.cd_results
	where fn_route = _route_id;
	
	delete from core.cd_user_points
	where fn_route = _route_id;

	delete from core.cd_route_history
	where fn_route = _route_id and fn_status not IN (2,3);
	
	delete from core.cd_points
	where f_route = _route_id and b_anomaly = true;
	
	RETURN 0;
END

Function: core.sf_is_mobile_route(_f_route uuid)

Returns: boolean

Language: PLPGSQL

Является ли маршрут доступным для мобильного устройства

/**
* @params {uuid} _f_route - иден. маршрута
*
* @returns {boolean} true - маршрут доступен для мобильного устройства
*/
BEGIN
	IF (select count(*) from core.cd_routes as r
		inner join core.cs_route_statuses as rs ON r.f_status = rs.id
		where r.id = _f_route and rs.n_order > 0 and core.sf_finish_date(CASE WHEN r.b_extended = true THEN r.d_extended ELSE r.d_date_end END)) = 1 THEN
		RETURN true;
	ELSE
		RETURN false;	
	END IF;
END

Function: core.sf_remove_outdated()

Returns: void

Language: PLPGSQL

Процедура очистки устаревших данных

/**
* системная функция должна выполнять от postgres
*/
DECLARE
    _n_val      integer = 100;
    _d_data     timestamptz = date_trunc('day', now()) + '1 day'::interval; -- начало следующего дня
	_dg_cnt		integer; --diagnostic
	_dg_text	text = '';
BEGIN

    -- опрос настройки
    BEGIN
        select
            c_value::integer
        into _n_val
        from core.cd_settings
        where c_key = 'ALL_DEL_AFTER';

    --в любых непонятных ситуациях берем 100 дней
    EXCEPTION
        WHEN OTHERS
        THEN _n_val = 100;
    END;

    _d_data  = _d_data - _n_val * '1 day'::interval;

    delete from core.ad_audits where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.ad_audits: удалено '|| _dg_cnt::text || E'\n';

    delete from core.ad_mobile_devices where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.ad_mobile_devices: удалено '|| _dg_cnt::text || E'\n';

    delete from core.ad_mobile_indicators where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.ad_mobile_indicators: удалено '|| _dg_cnt::text || E'\n';

    delete from core.cd_notifications where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.cd_notifications: удалено '|| _dg_cnt::text || E'\n';

	delete from core.cd_action_log where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.cd_action_log: удалено '|| _dg_cnt::text || E'\n';
	
	delete from core.cd_action_log_user where d_date < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.cd_action_log_user: удалено '|| _dg_cnt::text || E'\n';
	
	delete from core.sd_client_errors where d_created < _d_data;
	get diagnostics _dg_cnt = row_count;
	_dg_text = _dg_text || ' core.sd_client_errors: удалено '|| _dg_cnt::text || E'\n';

	insert into core.cd_sys_log(d_timestamp, c_descr)
	values(clock_timestamp(), 'Очистка таблиц выполнена. ' || E'\n' || _dg_text);

	EXCEPTION
	WHEN OTHERS
    THEN
		insert into core.cd_sys_log(d_timestamp, c_descr)
		values(clock_timestamp(), 'Непредвиденная ошибка очистки таблиц');

END;

Function: core.sf_table_change_update(_c_table_name text, _f_user integer)

Returns: integer

Language: PLPGSQL

/**
* @params {text} _c_table_name - имя таблицы
* @params {integer} _f_user - иднтификатор пользователя
*
* @returns {integer} - 0 результат выполнения
*
* @example
* [{ "action": "sf_table_change_update", "method": "Query", "data": [{ "params": [_c_table_name, _f_user] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	IF (select count(*) from core.sd_table_change where c_table_name = _c_table_name
		and (case when _f_user is null then _f_user is null else f_user = _f_user end)) = 0 then
		INSERT INTO core.sd_table_change (c_table_name, n_change, f_user)
		VALUES (_c_table_name, (SELECT EXTRACT(EPOCH FROM now())), _f_user);
	else
		update core.sd_table_change
		set n_change = (SELECT EXTRACT(EPOCH FROM now()))
		where c_table_name = _c_table_name and (case when _f_user is null then _f_user is null else f_user = _f_user end);
	end if;

	RETURN 0;
END

Function: core.sf_update_version()

Returns: text

Language: PLPGSQL

Принудительное обновление версии базу данных

/**
* принудительное обновление
*
* @returns {text} новая версия базы данных
*/
DECLARE
	_ver text;
BEGIN
	UPDATE core.cd_settings
	SET c_value = core.sf_build_version(0)
	WHERE lower(c_key) = lower('DB_VERSION');
	
	SELECT c_value INTO _ver FROM core.cd_settings WHERE lower(c_key) = lower('DB_VERSION');
	RETURN _ver;
END;

Function: core.sf_version_to_number(c_version text)

Returns: bigint

Language: PLV8

Преобразование версии в число

/**
* @params {text} c_version - версия приложения
* @returns {bigint} числовой вариант версии
*/
try {
		var data = c_version.split('.');
		return (parseInt(data[1]) * 24 * 60) + parseInt(data[3]);
	} catch(e) { 
		return 0;
	}

Schema dbo


View: dbo.cv_tracking

dbo.cv_tracking Structure
F-Key Name Type Description
f_user integer
c_name text
d_date_str text
d_date timestamp with time zone
n_longitude numeric
n_latitude numeric
c_network_status text
SELECT t.f_user
,
    concat
(u.c_last_name
     ,' '
     , u.c_first_name
     ,' '
     , u.c_middle_name
) AS c_name
,
    t.d_date_str
,
    t.d_date
,
    t.n_longitude
,
    t.n_latitude
,
    t.c_network_status
   
FROM (
     (
      SELECT t_1.fn_user AS f_user
           ,
            to_char
           (t_1.d_date
                 ,'dd.MM.YYYY HH24:MI'::text
           ) AS d_date_str
           ,
            max
           (t_1.d_date) AS d_date
           ,
            avg
           (t_1.n_longitude) AS n_longitude
           ,
            avg
           (t_1.n_latitude) AS n_latitude
           ,
            max
           (t_1.c_network_status) AS c_network_status
           
        FROM core.ad_tracking t_1
          
    GROUP BY t_1.fn_user
           , (to_char
                 (t_1.d_date
                       ,'dd.MM.YYYY HH24:MI'::text
                 )
           )
        
   UNION ALL
         
      SELECT t_1.fn_user AS f_user
           ,
            to_char
           (t_1.d_date
                 ,'dd.MM.YYYY HH24:MI'::text
           ) AS d_date_str
           ,
            t_1.d_date
           ,
            t_1.n_longitude
           ,
            t_1.n_latitude
           ,
            'online'::text AS c_network_status
           
        FROM core.cd_user_points t_1
          
       WHERE (t_1.n_longitude > 
                 (1)::numeric
           )
     ) t
     
  JOIN core.pd_users u 
    ON (
           (t.f_user = u.id)
     )
)
  
ORDER BY t.d_date;

Index - Schema dbo


Table: dbo.ed_blanks

Бланки строгой отчетности

dbo.ed_blanks Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор пломбы
core.cs_result_types.id f_result_type integer NOT NULL

Тип результата к которому привязан бланк
c_number text NOT NULL

Номер бланка
core.pd_users.id core.pd_users.id f_user_from integer

Кто выдал
dx_created timestamp with time zone DEFAULT now()

Дата создания
fn_result uuid

Видимо это должен быть FK на "результат выполнения" (core.cd_results)
jb_history json

История изменения
n_order integer

Порядок
c_prefix text

Префикс
n_number bigint

Номер бланка (числовой)
core.sd_subdivisions.id f_subdivision integer

Подразделение
core.pd_users.id f_user_to integer

Кто получил
d_date_to timestamp with time zone

Дата выдачи
dbo.es_blank_status.id f_status integer
c_document_trash text

Номер акта списания
dbo.es_notice_trash.id f_notice_trash integer
c_notice text
core.pd_users.id f_user_mol integer

Материально ответственное лицо

Index - Schema dbo


Table: dbo.ed_devices

Приборы учета

dbo.ed_devices Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

ID
link integer

Идентификтор из Омнис
dbo.es_device_types.id f_device_type integer

Тип прибора учета
c_serial_number text

Серийный номер ПУ
n_rate numeric(19,6)

Коэффициент трансформации
n_manufacture_year integer

Год выпуска
d_setup_date date

Дата установки
d_valid_date date

Дата гос. поверки
dbo.es_device_location.id f_device_location integer

Ссылка на Справочник в Омнис Место установки
f_owner_type integer

Ссылка на Справочник в Омнис Эксплуатационная ответственность
n_owner_type integer

Эксплуатационная ответственность
c_device_location text

временное поле. т.к. в присланных данных более 700 строк по 1 РЭС
imp_int integer

временно поле при импорте
dbo.ed_registr_pts.id f_registr_pts uuid

Ссылка на ТУ
imp_text text

временное поле для импорта
b_askue boolean DEFAULT false

ПУ включен в АСКУЭ
d_close_date date

Дата снятия ПУ
d_last_check_date date

Дата последней инструментальной проверки
c_last_check_doc text

Номер акта инструментальной проверки
n_power_disc_speed numeric

Активная мощность по оборотам диска
n_power_network_devices numeric

Активная мощность по приборам в силовой сети

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.ed_input_meter_readings

Показания ПУ

dbo.ed_input_meter_readings Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
n_value_prev numeric(19,6)

Пред. показание
d_date_prev timestamp with time zone

Дата пред. показания
n_digit numeric(2,1)

Разрядность
dbo.es_scales.id f_scale integer NOT NULL

Шкала показания
dx_created timestamp with time zone DEFAULT now()

Дата создания записи
dbo.ed_registr_pts.id f_registr_pts uuid NOT NULL

Ссылка на точку учета
dbo.es_tariff_zones.id f_tariff_zone integer NOT NULL

Тарифная зона
dbo.es_energy_types.id f_energy_type integer

Ссылка на измеряемый показатель
dbo.es_delivery_methods.id f_delivery_method integer

Ссылка на источик показаний
d_replace_date timestamp with time zone

Дата снятия/замены
dbo.es_reading_statuses.id f_reading_status integer NOT NULL DEFAULT 1

Статус показания
dbo.ed_devices.id f_device uuid

Прибор учета
jb_sources jsonb

Index - Schema dbo


Table: dbo.ed_output_conn_seals

Привязка новых пломб к точке учета

dbo.ed_output_conn_seals Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

[e110] Идентификатор
fn_seal uuid

Ссылка на пред. пломбу
fn_point uuid NOT NULL

[e90] Точка маршрута
fn_route uuid NOT NULL

[e80] Маршрута
fn_user_point uuid NOT NULL

[e70] Пользовательская точка
fn_seal_new uuid NOT NULL

[e50|d] Новая пломба
fn_type integer

[e40] Тип пломбы
fn_place integer

[e30] Место установки
d_date timestamp with time zone NOT NULL

[e20] Дата
dx_created timestamp with time zone DEFAULT now()

[e10] Дата создания записи
fn_result uuid NOT NULL

Результат
b_export boolean DEFAULT false

Экспортировано

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.ed_output_meter_readings

Показания ПУ

dbo.ed_output_meter_readings Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_meter_reading uuid NOT NULL

Показание ПУ
fn_point uuid

Точка маршрута
fn_route uuid

Маршрута
fn_user_point uuid

Пользовательская точка
n_value numeric(19,6)

Показание
d_date timestamp with time zone NOT NULL

Дата показания
dx_created timestamp with time zone DEFAULT now()

Дата создания записи
b_export boolean DEFAULT false

Экспортировано
fn_result uuid

Идентификатор результата (акта)

Index - Schema dbo


Table: dbo.ed_output_transformers

Исходящая информация о трансформаторах

dbo.ed_output_transformers Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
fn_route uuid

Маршрута
fn_point uuid

Точка маршрута
fn_user_point uuid

Пользовательский результат
fn_result uuid

Результат
fn_transformer uuid

Пред. трансформатор
c_number text

Номер трансформатора
n_year integer

Год выпуска
d_date timestamp with time zone

Дата установки??
n_rate numeric

Коэффициент трансформации
fn_phase integer

Фаза
dx_created timestamp with time zone DEFAULT now()

Дата создания записи
d_date_check timestamp with time zone

Дата поверки
b_voltage boolean

Является трансформатором напряжения
fn_device_type integer

Тип
b_export boolean DEFAULT false

Экспортировано
n_check_cycle integer

Межповерочный интервал, лет
n_tt1 numeric(19,6)

Величина на первичнй обмотке
n_tt2 numeric(19,6)

Величина на вторичной обмотке

Index - Schema dbo


Table: dbo.ed_registr_pts

Учетный показатель

dbo.ed_registr_pts Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

ID
core.sd_divisions.id f_division integer NOT NULL

Филиал/Отделение
core.sd_subdivisions.id f_subdivision integer NOT NULL

Участок
b_disabled boolean NOT NULL DEFAULT false

Отлючено
dx_created timestamp with time zone DEFAULT now()

Дата создания
sn_delete boolean NOT NULL DEFAULT false

Признак что запись удалена
c_registr_pts text

Наименование точки учета
dbo.es_status_consume.id f_status_consume integer

Статус точки учета
b_technical_metering boolean

Признак Тех. Учета
c_substation text

Подстанция
c_line_substation text

Фидер 6-10/35кВ
c_rp text

РП
c_line_rp text

Фидер 6-10/35кВ
c_tp text

Трансформаторная подстанция
c_line_tp text

Фидер 0,4кВ
c_line_segment text

№ опоры ВЛ-0,4кВ
f_violation integer

Ссылка на Тип нарушения
d_violation_date date

Дата нарушения
d_date_before date

Срок устранения нарушения
dbo.sd_subscr.id f_subscr uuid

Ссылка на абонента
dbo.ss_address.id f_address uuid

Ссылка на адресную витрину
f_subscr_int integer

Наверно для импорта
f_device_int integer

Наверно для импорта
imp_int integer

временно поле при импорте
c_line_tp_1 text

Линия 0,4 кВ
c_line_segment_1 text

Участок линии 0,4 кВ
imp_text text

Код УП
d_close_date date

Дата закрытия ТУ
c_status_registr_pts text

Статус ТУ
c_status text

Внеплановые работы
c_predictr text

Показатель из системы ПредиктР
n_geo_lat numeric(19,6)
n_geo_lon numeric(19,6)
d_restriction_date date

Дата введения ограничения
c_restriction_method text

Способ ограничения
c_network_pts_code text

Номер точки поставки
n_max_cap integer

Величина максимальной мощности
b_sub boolean NOT NULL DEFAULT false

Признак: точка учета является субабонентом
b_transit boolean NOT NULL DEFAULT false

Признак: транзитер
dbo.es_registr_pts_status.id f_registr_pts_status integer

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.ed_registr_pts_history

История точек учета

dbo.ed_registr_pts_history Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()
dbo.ed_registr_pts.id f_registr_pts uuid UNIQUE#1 NOT NULL

Идентификатор точки учета
b_plan boolean NOT NULL

Является плановым точкой
dbo.es_no_plan_works.id f_no_plan_work smallint UNIQUE#1

Тип внеплановой работы
d_date_period date UNIQUE#1 NOT NULL

Период работ
core.cs_point_types.id f_point_type integer UNIQUE#1

Тип работ по точке
b_no_plan boolean NOT NULL

признак что точка является внеплановой
d_no_plan_date date

планируемая дата выполнения работ по внеплановой точке. Будет заполняться при импорте внеплановых работ/ручном указании внеплановых работ по точке учета через АРМ Диспетчера.

Index - Schema dbo


Table: dbo.ed_seals

Плобмы

dbo.ed_seals Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
c_number text NOT NULL

Номер пломбы
core.pd_users.id f_user_from integer

Кто выдал
dx_created timestamp with time zone DEFAULT now()

Дата создания
dbo.ed_registr_pts.id f_registr_pts uuid

Точка
c_prefix text

Префикс
c_type text

Типы пломб (скорее всего избыточно, так как есть FK f_type)
c_location text

Место установки пломбы (скорее всего избыточно, так как есть FK f_place)
imp_int integer

временно для импорта
d_replace_date timestamp with time zone

Дата замены
n_order integer

Порядок
jb_history json

История изменений
dbo.es_seal_types.id f_type integer

Типы пломб
dbo.es_seal_places.id f_place integer

Место установки пломбы
dbo.ed_output_conn_seals.id f_output_conn_seal uuid

Ссылка на результат из мобильного приложения
n_number bigint

Номер сквозной
core.pd_users.id f_user_to integer

Кто получил
d_date_to timestamp without time zone

Дата выдачи - заполняется при указании поля f_user_to
core.sd_subdivisions.id f_subdivision integer

Подразделение
dbo.es_seal_status.id f_status integer NOT NULL
c_document_trash text

Номер акта списания
dbo.es_notice_trash.id f_notice_trash smallint

Причина забраковки пломбы
core.pd_users.id f_user_mol integer

Материально ответственное лицо за получение пломб в РЭС
c_notice text

Поле для списания пломб, установленных без использования мобильного приложения. Ввод вручную

Index - Schema dbo


Table: dbo.ed_transformers

Трансформаторы

dbo.ed_transformers Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

ID
dbo.ed_registr_pts.id f_registr_pts uuid

Ссылка на идентификатор ТУ
b_voltage boolean

Признак, что это ТН
c_serial_number text

Серийниый номер
d_replace_before date

Дата следующей госповерки
c_phase text

Фаза ТТ/ТН
imp_int integer

Ссылка на идентификатор ТТ/ТН из сторонней системы
n_manufacture_year integer

Год выпуска
d_check_date date

Дата гос.поверки
d_replace_date date

Дата сняти прибора (признак отключения)
imp_text text

временно для импорта
dx_created timestamp with time zone DEFAULT now()

Дата создания записи
f_device_type integer

Ссылка на тип документа
n_rate numeric(10,2)

Коэффициент трансформации

Index - Schema dbo


Table: dbo.ed_violation

Нарушения

dbo.ed_violation Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор нарушения
c_violation_type text

Тип нарушения
d_violation_date date

Дата нарушения
d_date_elimination date

Срок устранения нарушения
f_registr_pts text

Идентификатор точки учета

Index - Schema dbo


Table: dbo.es_blank_status

Статусы бланков

dbo.es_blank_status Structure
F-Key Name Type Description
id smallint PRIMARY KEY DEFAULT nextval('dbo.es_blank_status_id_seq'::regclass)
c_name text NOT NULL
n_code smallint NOT NULL
c_const text NOT NULL

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_delivery_methods

Источник показаний

dbo.es_delivery_methods Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text

Наименование
c_const text

Константа
b_default boolean

Признак значения по-умолчанию

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_device_categories

Категории приборов

dbo.es_device_categories Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text

Наименование
b_meter boolean NOT NULL

Признак: Наличие показаний
b_tranf boolean NOT NULL

Признак: Является трансформатором
b_default boolean NOT NULL

Категория по-умолчанию
b_disabled boolean NOT NULL

Признак: Категория не используется

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_device_location

Место установки

dbo.es_device_location Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование места установки
c_const text

Константа
b_default boolean NOT NULL

Признак значения по-умолчанию
core.sd_divisions.id f_division integer

Ссылка на филиал/отделение ЦиП
core.sd_subdivisions.id f_subdivision integer

Ссылка на участок/РЭС ЦиП

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_device_types

Типы прибора

dbo.es_device_types Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
dbo.es_device_categories.id f_device_categories integer NOT NULL

Категория
c_name text

Наименование
c_modification text

Модификация
n_check_cycle integer

Межповерочный интервал, лет
dbo.es_tariff_zones.id f_tariff_zone integer

Количество временных зон
b_phase3 boolean

Признак: Трехфазный
b_disabled boolean NOT NULL

Признак: Тип прибора не используется
f_device_types integer

Наверно это идентификатор из внешней системы
n_tariff integer

Количество тарифных зон
n_digits numeric(2,1)

Разрядность
n_tt1 numeric(19,6)

Величина на первичнй обмотке
n_tt2 numeric(19,6)

Величина на вторичной обмотке
n_rate numeric(10,2)

Коэффициент трансформации
f_main_division integer

Филиал
f_division integer

Отделение
f_subdivision integer

Участок

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_energy_types

Виды измерения

dbo.es_energy_types Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_const text

Константа
b_default boolean NOT NULL

Признак значения по-умолчанию
c_code_out text

Код из внешней системы

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_failure_reason

Причины недопуска

dbo.es_failure_reason Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Index - Schema dbo


Table: dbo.es_no_plan_works

Справочник внеплановых работ

dbo.es_no_plan_works Structure
F-Key Name Type Description
id smallint PRIMARY KEY DEFAULT nextval('dbo.es_no_plan_work_id_seq'::regclass)
c_name text NOT NULL

Наименование
c_const text NOT NULL

Константа
b_disabled boolean NOT NULL

Отключено
n_order smallint NOT NULL

Сортировка
n_code smallint

Код
c_short_name text

Сокращенное наименование

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_notice_trash

Причина списания пломбы/бланка

dbo.es_notice_trash Structure
F-Key Name Type Description
id smallint PRIMARY KEY DEFAULT nextval('dbo.es_notice_trash_id_seq'::regclass)
c_name text NOT NULL
c_const text NOT NULL
b_default boolean NOT NULL
b_disabled boolean NOT NULL
b_seal boolean NOT NULL

Применяется для пломб

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_phase

Фазы

dbo.es_phase Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_const text

Константа

Index - Schema dbo


Table: dbo.es_precission_classes

Классы точности прибора

dbo.es_precission_classes Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text

Наименование
c_const text

Константа

Index - Schema dbo


Table: dbo.es_reading_statuses

Статусы показаний

dbo.es_reading_statuses Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text

Наименование
c_const text

Константа

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_registr_pts_status

Статус активности ТУ

dbo.es_registr_pts_status Structure
F-Key Name Type Description
id serial PRIMARY KEY
c_name text NOT NULL
c_const text NOT NULL
b_disabled boolean NOT NULL

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_restrictions

Типы ограничений

dbo.es_restrictions Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Index - Schema dbo


Table: dbo.es_scales

Шкалы прибора учета

dbo.es_scales Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('dbo.auto_id_es_scales'::regclass)

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено
c_code_out text

Код из внешней системы

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_seal_places

Справочник мест установки пломб

dbo.es_seal_places Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('dbo.auto_id_es_seal_places'::regclass)

[e80] Идентификатор
n_code integer

[e70] Код
c_name text NOT NULL

[e60|d] Наименование
c_short_name text

[e50] Краткое наименование
c_const text

[e40] Константа
n_order integer

[e30] Сортировка
b_default boolean NOT NULL DEFAULT false

[e20] Отключено
b_disabled boolean NOT NULL DEFAULT false

[e10] Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_seal_status

Статусы пломб

dbo.es_seal_status Structure
F-Key Name Type Description
id smallint PRIMARY KEY DEFAULT nextval('dbo.es_seal_status_id_seq'::regclass)
c_name text NOT NULL
n_code smallint NOT NULL
c_const text NOT NULL

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_seal_types

тип пломбы

dbo.es_seal_types Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('dbo.auto_id_es_seal_types'::regclass)

[e80] Идентификатор
n_code integer

[e70] Код
c_name text NOT NULL

[e60|d] Наименование
c_short_name text

[e50] Краткое наименование
c_const text

[e40] Константа
n_order integer

[e30] Сортировка
b_default boolean NOT NULL DEFAULT false

[e20] Отключено
b_disabled boolean NOT NULL DEFAULT false

[e10] Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_status_consume

Статус потребления ТУ

dbo.es_status_consume Structure
F-Key Name Type Description
id serial PRIMARY KEY
n_code integer
c_name text NOT NULL
c_const text
n_order integer
b_default boolean NOT NULL DEFAULT false
b_disabled boolean NOT NULL DEFAULT false

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_tariff_zones

Тарифные зоны

dbo.es_tariff_zones Structure
F-Key Name Type Description
id integer PRIMARY KEY DEFAULT nextval('dbo.auto_id_es_tariff_zones'::regclass)

Идентификатор
n_count_scale integer NOT NULL

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text NOT NULL

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.es_verification_reason

Причина проверки

dbo.es_verification_reason Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
c_name text NOT NULL

Наименование
c_const text

Константа
n_order integer

Сортировка
b_disabled boolean NOT NULL DEFAULT false

Отключено

Index - Schema dbo


Table: dbo.es_violations

Типы нарушений

dbo.es_violations Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
n_code integer

Код
c_name text NOT NULL

Наименование
c_short_name text

Краткое наименование
c_const text

Константа
n_order integer

Сортировка
b_default boolean NOT NULL DEFAULT false

По умолчанию
b_disabled boolean NOT NULL DEFAULT false

Отключено
c_code_out text

Код из внешней системы

Index - Schema dbo


Table: dbo.es_work_links

Сопоставление видов работ

dbo.es_work_links Structure
F-Key Name Type Description
id serial PRIMARY KEY

Идентификатор
core.cs_route_types.id f_route_type integer NOT NULL

Тип маршрута
core.cs_point_types.id f_point_type integer NOT NULL

Тип точки
core.cs_result_types.id f_result_type integer NOT NULL

Тип результата
b_disabled boolean NOT NULL DEFAULT false

Признак: не используется
dx_created timestamp with time zone NOT NULL DEFAULT now()

Дата создания записи

Index - Schema dbo


Table: dbo.sd_employers

Сотрудники

dbo.sd_employers Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
f_maindivision_int integer

Целочисленная ссылка на филиал
f_division_int integer

Целочисленная ссылка на отделение
f_subfivision_int integer

Целочисленная ссылка на участок
c_name1 text

Фамилия
c_name2 text

Имя
c_name3 text

Отчество
d_date_begin date

Дата трудоустройства 
d_date_end date

Дата увольнения
c_login text

Логин (первичный)
s_password text

Пароль (первичный)
c_tab_number text

Табельный номер
f_roles integer

Ссылка на Справочник Роли
c_telephone text

Номер телефона
c_email text

E-mail 
b_skill1 boolean

Квалификация_1: Контрольное снятие показаний
b_skill2 boolean

Квалификация_2: Инструментальная проверка
b_skill3 boolean

Квалификация_3: Замена (снятие) прибора, Установка прибора
b_skill4 boolean

Квалификация_4: Ввод ограничения энергоснабжения, Возобновление энергоснабжения
b_gpx boolean

Договор ГПХ

Index - Schema dbo


Table: dbo.sd_subscr

Абонент

dbo.sd_subscr Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

Идентификатор
f_division integer

Идентификатор отделения (ПО)
f_subdivision integer

Идентификатор участка (РЭС)
c_code text

Код абонента
c_name1 text

Наименование ЮЛ:c_name_consumer | Фамилия ФЛ
c_name2 text

Имя ФЛ
c_name3 text

Отчество ФЛ
c_telephone text

Номер телефона
b_problem_person boolean NOT NULL DEFAULT false

Проблемный абонент
b_person boolean

Признак ФЛ
n_check_date integer

интервал проверок??
f_subscr integer

Наверно это Идентификатор ЛС из внешней системы
imp_int integer

временное поле для импорта
jb_history json

История изменений номеров телефона
f_partners text

Идентификатор абонента из внешней системы

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


Table: dbo.ss_address

Адреса

dbo.ss_address Structure
F-Key Name Type Description
id uuid PRIMARY KEY DEFAULT uuid_generate_v4()

ID
c_name text

Полный адрес
c_index text

Индекс
c_region text

Наименование области
code_fias_region uuid

Код ФИАС региона
c_raion text

Наименование района
data_area_fias_id uuid
c_city_name text

Наименование города
data_city_fias_id uuid

Код ФИАС города
c_settlement_name text

Наименование населенного пункта
settlement_fias_id uuid

Код ФИАС населенного пункта
c_street_name text

Наименование улицы
data_street_fias_id uuid

Код ФИАС улицы
c_house_name text

Номер дома
data_house_fias_id uuid

Код ФИАС дома
c_block_name text

Корпус
c_flat_name text

Квартира
n_fias_level integer

Уровень ФИАС
n_geo_lat numeric(19,6)

Широта
n_geo_lon numeric(19,6)

Долгота
qc_geo integer

Точность координат
imp_int integer

временное поле для импорта
c_comment_address text

Комментарий к адресу
imp_text text

временное поле для импорта
f_conn_points text

Идентификатор объекта с внешней системы
c_name_obj text

Наименование объекта
b_dadata boolean NOT NULL DEFAULT false

Признак: адрес обработан сервисом DaData

Tables referencing this one via Foreign Key Constraints:

Index - Schema dbo


View: dbo.sv_fias_address

Справочник адресов ФИАС

dbo.sv_fias_address Structure
F-Key Name Type Description
id uuid
c_region text

наименование региона
f_region uuid

идентификатор региона ФИАС
c_province text

наименование района
f_province uuid

идентификатор района ФИАС
c_town text

наименование города
f_town uuid

идентификатор города ФИАС
c_municipality text

наименование нас. пункта
f_municipality uuid

идентификатор нас. пункта ФИАС
c_street text

наименование улицы
f_street uuid

идентификатор улицы ФИАС
c_house_number text

номер дома
f_house uuid

идентификатор дома ФИАС
n_object_type_level integer

регион
SELECT sa.f_house AS id
,
    sa.c_region
,
    sa.f_region
,
    sa.c_province
,
    sa.f_province
,
    sa.c_town
,
    sa.f_town
,
    sa.c_municipality
,
    sa.f_municipality
,
    sa.c_street
,
    sa.f_street
,
    sa.c_house_number
,
    sa.f_house
,
    sa.n_object_type_level
   
FROM dbo.ss_fias_address sa;

Index - Schema dbo


Function: dbo.cf_arm_all_subdivisions(_f_user integer)

Returns: SET OF record

Language: PLPGSQL

Получение дерева подразделений для пользователя

/**
* @params {integer} _f_user - пользователь
* 
* @example
* [{ "action": "cf_arm_all_subdivisions", "method": "Select", "data": [{ "params": [_f_user] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	RETURN QUERY 
	-- поиск subdivisions
	select sd.id, sd.f_division, sd.n_code, sd.c_name, true as b_subdivision
	from core.pd_userindivisions as ud
	inner join core.sd_subdivisions as sd ON ud.f_subdivision = sd.id
	where ud.f_user = _f_user and ud.f_subdivision is not null and b_disabled = false
	UNION
	-- поиск через divisions
	select sd.id, sd.f_division, sd.n_code, sd.c_name, false as b_subdivision from core.sd_subdivisions as sd
	where sd.b_disabled = false and sd.f_division IN (WITH RECURSIVE tree AS (
		SELECT
			d.id,
			d.f_division
		FROM core.sd_divisions as d
		where d.id IN (select ud.f_division
						from core.pd_userindivisions as ud
						where ud.f_user = _f_user and ud.f_division is not null and ud.f_subdivision is null)

		UNION

		SELECT
			d.id,
			d.f_division
		FROM core.sd_divisions as d
		JOIN tree ON d.id = tree.f_division)
	select t.id from tree as t);
END

Function: dbo.cf_arm_assign_route(_f_current_user integer, _users json, _f_route uuid, _b_plan boolean)

Returns: integer

Language: PLPGSQL

Функция предназначена для назначения или переназначения исполнителей в маршруте

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {json} _users - массив пользователей. В функцияю должно передаваться как строка, например: '[{ "id":4, "b_main": true }, { "id": 13, "b_main": false }]'
* @params {uuid} _f_route - иден. маршрута
* @params {boolean} _b_plan - true - применяется в пранировании
*
* @returns {integer}
* 0 - ОК
* 1 - маршрут не найден
* 2 - пользователь не найден
*
* @example
* [{ "action": "cf_arm_assign_route", "method": "Query", "data": [{ "params": [_f_current_user, _users, _f_route, _b_plan] }], "type": "rpc", "tid": 1 }]
*/
DECLARE
	_status_id integer; -- иден. статус передан (назначен)
	_transfered_status_id integer; -- иден. статуса передан
	_re_assign boolean; -- переназначенение
BEGIN
	select false into _re_assign;

	IF (select count(*) from core.cd_routes as r where r.id = _f_route) = 1 THEN
		IF (select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN

			select rs.id into _status_id 
			from core.cs_route_statuses as rs
			where rs.c_const = CASE WHEN _b_plan = true THEN 'CREATED' ELSE 'ASSINGNED' END;

			-- находим информацию о статусе
			IF (select count(*) from core.cd_routes as r
				where r.id = _f_route and r.f_status = _status_id) = 1 THEN

				select true into _re_assign;

				-- удаляем информацию из истории
				delete from core.cd_route_history as rh
				where rh.fn_route = _f_route and rh.fn_status = _status_id;		

				-- удаляем привязку к пользователю
				delete from core.cd_userinroutes as uir
				where uir.f_route = _f_route;
			END IF;

			-- статус не меняется если вес положительный
			IF(select rs.n_order from core.cd_routes as r
				inner join core.cs_route_statuses as rs ON r.f_status = rs.id
				where r.id = _f_route) < 0 THEN

				-- создаем новый статус
				insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date, c_notice)
				values (_f_route, _status_id, _f_current_user, now(), (CASE WHEN _re_assign THEN 'Переназначен' ELSE 'Назначен' END));

			ELSE

				select rs.id into _transfered_status_id 
				from core.cs_route_statuses as rs
				where rs.c_const = 'TRANSFERRED';

				-- создаем новый статус "Передан"
				insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date, c_notice)
				values (_f_route, _transfered_status_id, _f_current_user, now(), 'Назначен(ы) новый(е) пользователь(и)');

			END IF;

			IF _users is not null and (select count(*) from json_array_elements(_users::json)) > 0 THEN
				-- создаем привязку
				insert into core.cd_userinroutes(f_route, f_user, b_main)
				select 
					_f_route, 
					(t.value #>> '{id}')::integer, 
					(t.value #>> '{b_main}')::boolean 
				from json_array_elements(_users::json) as t
				where (t.value #>> '{id}')::integer NOT IN (select uir.f_user from core.cd_userinroutes as uir where uir.f_route = _f_route);
			END IF;

			RETURN 0;
		ELSE
			RETURN 2; -- нет пользователя
		END IF;
	ELSE
		RETURN 1; -- нет маршрута
	END IF;
END

Function: dbo.cf_arm_cd_point_update(_items json, _f_point_type integer)

Returns: integer

Language: PLPGSQL

Массовое обновление типа работ по точкам маршрута

/**
*
* @params {json} _items - список идентификаторов cd_points, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
* @params {integer} _f_point_type - тип работ
*
* @returns {integer}
* 0 - ОК
*
* @example
* [{ "action": "cf_arm_cd_point_update", "method": "Query", "data": [{ "params": [_items, _f_point_type] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	update core.cd_points as p
	set f_type = _f_point_type
	where p.id in (select t.value::uuid from json_array_elements_text(_items) as t);

	RETURN 0;
END

Function: dbo.cf_arm_cd_points(_f_main_division integer, _f_division integer, _f_subdivision integer, _f_manager integer, _f_user integer, _d_date date)

Returns: SET OF record

Language: PLPGSQL

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

/**
* @params {integer} _f_main_division - иден. филиал. Обязателен при передаче
* @params {integer} _f_division - иден. отделение. Обязателен при передаче
* @params {integer} _f_subdivision - иден. участок. Обязателен при передаче
* @params {integer} _f_manager - иден. диспетчер. Может быть null
* @params {integer} _f_user - иден. обходчика. Может быть null
* @params {date} _d_date - дата для фильтрации
*
* @example
* [{ "action": "cf_arm_cd_points", "method": "Select", "data": [{ "params": [_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_routes json;
BEGIN
	IF _d_date is null THEN
		select now()::date into _d_date;
	END IF;
	
	-- обходчики выбраны и находим все маршруты за текущую дату
	select array_to_json(array_agg(t.id)) into _routes
	from (select r.id from core.cd_userinroutes as uir
		INNER JOIN core.cd_routes as r ON r.id = uir.f_route
		where uir.b_main = true and uir.f_user IN (
			select u.id from dbo.cf_arm_pd_users(_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user) as u
		) and _d_date >= r.d_date_start and _d_date <= (CASE WHEN r.b_extended THEN r.d_extended ELSE r.d_date_end END)) as t;

	RETURN QUERY select * from dbo.cf_arm_cd_points(_routes, _d_date);
END

Function: dbo.cf_arm_cd_points(_routes json, _d_date date)

Returns: SET OF record

Language: PLPGSQL

Получить список заданий по маршруту

/**
* @params {json} _routes - массив маршрутов, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
* @params {date} _d_date - дата фильтрации, например 2020-10-01

* @example
* [{ "action": "cf_arm_cd_points", "method": "Select", "data": [{ "params": [_routes, _d_date] }], "type": "rpc", "tid": 0}]
*/ 
BEGIN
    RETURN QUERY WITH user_points as (
		select up.fn_point, up.fn_user, up.d_date from core.cd_user_points as up
		where up.fn_route IN (select t.value::uuid from json_array_elements_text(_routes) as t) --and up.d_date::date = _d_date::date
	) 
	select
		p.id,
		(select count(*) from user_points as up where up.fn_point = p.id) > 0 as b_done,
		ad.c_name as c_address,
		coalesce(rp.n_geo_lon, ad.n_geo_lon) as n_geo_lon,
		coalesce(rp.n_geo_lat, ad.n_geo_lat) as n_geo_lat,
		d.c_serial_number as c_device_number,
		s.c_code as c_subscr,
		(CASE WHEN s.b_person THEN concat(s.c_name1, ' ', s.c_name2, ' ', s.c_name3) ELSE s.c_name1 END) as c_owner,
		(select array_to_json(array_agg(row_to_json(t))) from (
			select r.id as f_result, rt.c_const as c_type_const, rt.c_short_name as c_type_name, r.fn_user as f_user, u.c_first_name, u.c_last_name, u.c_middle_name, r.d_date
			from core.cd_results as r
			inner join core.cs_result_types as rt ON r.fn_type = rt.id
			inner join core.pd_users as u ON u.id = r.fn_user
			where r.fn_route IN (select t.value::uuid from json_array_elements_text(_routes) as t) and r.fn_point = p.id
		) as t) as j_results,
		(select r.d_date
			from core.cd_results as r
			where r.fn_route IN (select t.value::uuid from json_array_elements_text(_routes) as t) and r.fn_point = p.id order by r.d_date desc limit 1) as d_date_result -- дата выполнения
	from core.cd_points as p
	left join dbo.ed_registr_pts as rp ON p.f_registr_pts = rp.id
	left join dbo.ss_address as ad ON ad.id = rp.f_address
	left join dbo.sd_subscr as s ON s.id = rp.f_subscr
	left join dbo.ed_devices as d ON d.f_registr_pts = rp.id
	where d.d_close_date is null and p.f_route IN (select t.value::uuid from json_array_elements_text(_routes) as t)
	order by p.n_order;
END

Function: dbo.cf_arm_cd_results(_f_users json, _d_start_date date, _d_end_date date)

Returns: SET OF record

Language: PLPGSQL

Подсветка дат с выполненными заданиями

/**
* @params {json} _f_users - массив пользователей, например [1, 2, 3]
* @params {date} _d_start_date - дата месяца для просмотра. По умолчанию нужно указать первый день месяца
* @params {date} _d_end_date - дата месяца для просмотра. По умолчанию нужно указать последний день месяца
*
* @returns - список дат с количеством выполненных заданий 
*
* @example
* [{ "action": "cf_arm_cd_results", "method": "Query", "data": [{ "params": [_f_users, _d_start_date, _d_end_date] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_status_weight integer;
BEGIN
	
	select rs.n_order into _status_weight 
	from core.cs_route_statuses as rs
	where rs.c_const = 'ASSINGNED'; -- не ниже этого статуса

	RETURN QUERY 
	select stat.d_date, sum(stat.n_count)::bigint, sum(stat.n_count_route)::bigint, stat.fn_user
	from (
		-- результаты
		select max(rr.d_date)::date as d_date, count(*) as n_count, null::bigint as n_count_route, rr.fn_user as fn_user
		from core.cd_results as rr
		where rr.fn_user IN (select t.value::integer from json_array_elements_text(_f_users) as t) and rr.d_date between _d_start_date and _d_end_date
		group by rr.fn_user, date_part('year', rr.d_date), date_part('month', rr.d_date), date_part('day', rr.d_date)
		union 
		-- активные маршруты на дату
		select max(dy.d_date)::date as d_date, null::bigint as n_count, count(*) as n_count_route, uir.f_user as fn_user
		from core.cd_userinroutes as uir
			inner join core.cd_routes as r ON r.id = uir.f_route
			inner join lateral generate_series(r.d_date_start::date, r.d_date_end::date, '1 day') as dy(d_date) on dy.d_date between _d_start_date and _d_end_date
			left join core.cs_route_statuses as rs ON rs.id = r.f_status
		where 1=1
			and uir.f_user IN (select t.value::integer from json_array_elements_text(_f_users) as t)
			and _d_end_date::date >= r.d_date_start
			and _d_start_date::date <= CASE WHEN r.b_extended THEN r.d_extended ELSE r.d_date_end END 
			and rs.n_order >= _status_weight
		group by uir.f_user, date_part('year', dy.d_date), date_part('month', dy.d_date), date_part('day', dy.d_date)
	) as stat
	group by stat.fn_user, stat.d_date
	order by stat.d_date

	;
END

Function: dbo.cf_arm_cd_routes(_f_author integer)

Returns: SET OF record

Language: PLPGSQL

Этап "Планирование": получение списка маршрутов

/**
* @params {integer} _f_author - автор маршрута
* @example 
* [{ "action": "cf_arm_cd_route", "method": "Select", "data": [{ "params":[_f_author] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_status_weight integer; -- вес статуса Сформирован
	_create_status_id integer; -- идентификатор Формируется
	_routes json; -- список маршрутов для выборки
BEGIN
	select rs.n_order into _status_weight 
	from core.cs_route_statuses as rs
	where rs.c_const = 'CREATED'; -- только до этого состояния
	
	select rs.id into _create_status_id 
	from core.cs_route_statuses as rs
	where rs.c_const = 'CREATE'; -- только до этого состояния	

	-- получаем список маршрутов которые были созданы указанным пользователем
	IF _f_author is not null THEN
		select array_to_json(array_agg(row_to_json(t))) into _routes from (
			select DISTINCT rh.fn_route from core.cd_route_history as rh
			where rh.fn_user = _f_author and rh.fn_status = _create_status_id
		) as t;
	ELSE
		select array_to_json(array_agg(row_to_json(t))) into _routes from (
			select DISTINCT rh.fn_route from core.cd_route_history as rh
			where rh.fn_status = _create_status_id
		) as t;
	END IF;

	-- обходчики выбраны и находим все маршруты за текущую дату
	RETURN QUERY select 
		r.id, 
		r.c_number, 
		r.d_date_start, 
		r.d_date_end,
		rs.c_const, 
		rs.c_name,
		r.f_type, 
		rt.c_name as c_type,
		(select array_to_json(array_agg(row_to_json(t))) from (
			select u.id, u.c_first_name, u.c_last_name, u.c_middle_name, uir.b_main from core.cd_userinroutes as uir 
			inner join core.pd_users as u ON u.id = uir.f_user
			where uir.f_route = r.id
			order by u.c_first_name, u.c_last_name
		) as t) as j_users,
		(select count(*) from core.cd_points as p where r.id = p.f_route) as n_points
	from (select (t.value #>> '{fn_route}')::uuid as fn_route from json_array_elements(_routes) as t) as uir
		INNER JOIN core.cd_routes as r ON r.id = uir.fn_route
		inner join core.cs_route_types as rt ON rt.id = r.f_type
		left join core.cs_route_statuses as rs ON rs.id = r.f_status
	where _status_weight >= rs.n_order 
	order by r.d_date_start;
END

Function: dbo.cf_arm_cd_routes(_f_main_division integer, _f_division integer, _f_subdivision integer, _f_manager integer, _f_user integer, _d_date_start date, _d_date_end date)

Returns: SET OF record

Language: PLPGSQL

Список маршрутов в разделе "Маршруты" - для отчетности

/**
* @params {integer} _f_main_division - иден. филиал. Обязателен при передаче
* @params {integer} _f_division - иден. отделение. Обязателен при передаче
* @params {integer} _f_subdivision - иден. участок. Обязателен при передаче
* @params {integer} _f_manager - иден. диспетчер. Может быть null
* @params {integer} _f_user - иден. обходчика. Может быть null
* @params {date} _d_date_start - дата начала
* @params {date} _d_date_end - дата завершения
*
* @example
* [{ "action": "cf_arm_cd_routes", "method": "Select", "data": [{ "params": [_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user, _d_date_start, _d_date_end] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_users json; -- обходчики
	--_d_date date;
	--_status_weight integer;
BEGIN
	--select now()::date into _d_date;
	
	-- закомментировал по требованию аналитика
	--select rs.n_order into _status_weight 
	--from core.cs_route_statuses as rs
	--where rs.c_const = 'ASSINGNED'; -- не ниже этого статуса
	
	-- обходчики выбраны и находим все маршруты за текущую дату
	RETURN QUERY
	select t.id, t.c_number, t.d_date_start, t.d_date_end, t.c_const, t.c_name, t.f_type, t.c_type, t.j_users, t.n_points, t.n_done_points, t.n_done_today_points
	from (
	with userinroutes as (
		select uir.f_route, uir.f_user, uir.b_main from core.cd_userinroutes as uir
		UNION ALL
		select rh.fn_route, rh.fn_user, true from core.cd_route_history as rh
		inner join core.cs_route_statuses as rs ON rh.fn_status = rs.id
		where rs.c_const = 'CREATE'
	)
	select 
		r.id, 
		r.c_number, 
		r.d_date_start, 
		r.d_date_end,
		rs.c_const, 
		rs.c_name,
		r.f_type, 
		rt.c_name as c_type,
		(select array_to_json(array_agg(row_to_json(t))) from (
			select u.id, u.c_first_name, u.c_last_name, u.c_middle_name, uir.b_main 
			from core.cd_userinroutes as uir 
			inner join core.pd_users as u ON u.id = uir.f_user
			where uir.f_route = r.id
			order by u.c_first_name, u.c_last_name
		) as t) as j_users,
		(select count(*) from core.cd_points as p where r.id = p.f_route) as n_points,
		(select count(DISTINCT fn_point) from core.cd_user_points as up where r.id = up.fn_route and up.fn_user = _f_user) as n_done_points,
		(select count(DISTINCT fn_point) from core.cd_user_points as up where r.id = up.fn_route and up.fn_user = _f_user and up.d_date::date = now()::date) as n_done_today_points,
		row_number() over(partition by r.id) as n_row
	from userinroutes as uir
		INNER JOIN core.cd_routes as r ON r.id = uir.f_route
		inner join core.cs_route_types as rt ON rt.id = r.f_type
		left join core.cs_route_statuses as rs ON rs.id = r.f_status
		where (case when _f_user is not null then uir.f_user = _f_user else (uir.b_main and 
																			 uir.f_user IN (select u.id from dbo.cf_arm_pd_users(_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user) as u)
																			) end) and r.d_date_start >= _d_date_start and _d_date_end >= (CASE WHEN r.b_extended THEN r.d_extended ELSE r.d_date_end END)
		order by r.d_date_start) as t
		where t.n_row = 1;
END

Function: dbo.cf_arm_cd_routes(_f_user integer, _d_date date)

Returns: SET OF record

Language: PLPGSQL

Этап "Назначение": получить список маршрутов по заданным параметрам фильтров "Обходчик" и "Дата"

/**
* @params {integer} _f_user - обходчик
* @params {date} _d_date - дата для фильтрации маршрутов
*
* @example
* [{ "action": "cf_arm_cd_routes", "method": "Select", "data": [{ "params": [_f_user, _d_date] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_status_weight integer;
	_result_types_oov integer;
BEGIN
	select rs.n_order into _status_weight 
	from core.cs_route_statuses as rs
	where rs.c_const = 'ASSINGNED'; -- не ниже этого статуса

	--тип документа "отказ от выполнения"
	select rt.id into _result_types_oov
	from core.cs_result_types as rt 
	where rt.c_const = 'OOV';

    RETURN QUERY WITH routes as (
		select r.id, r.c_number, r.d_date_start, r.d_date_end, rs.c_const, rs.c_name, r.f_type, rt.c_name as c_type
		from core.cd_userinroutes as uir
		INNER JOIN core.cd_routes as r ON r.id = uir.f_route
		inner join core.cs_route_types as rt ON rt.id = r.f_type
		left join core.cs_route_statuses as rs ON rs.id = r.f_status
		where 1=1
			--and uir.b_main = true 
			and uir.f_user = _f_user 
			and _d_date::date >= r.d_date_start
			and _d_date::date <= CASE WHEN r.b_extended THEN r.d_extended ELSE r.d_date_end END 
			and rs.n_order >= _status_weight
	) select 
		r.*,
		(select array_to_json(array_agg(row_to_json(t))) from (
			select u.id, u.c_first_name, u.c_last_name, u.c_middle_name, uir.b_main from core.cd_userinroutes as uir 
			inner join core.pd_users as u ON u.id = uir.f_user
			where uir.f_route = r.id
			order by u.c_first_name, u.c_last_name
		) as t) as j_users,
		(select count(*) from core.cd_points as p where r.id = p.f_route) as n_points,
		(select count(DISTINCT fn_point) from core.cd_user_points as up where r.id = up.fn_route and up.fn_user = _f_user) as n_done_points,
		(select count(DISTINCT cr.fn_point) 
			from (
				select case when max(cr.fn_type) = _result_types_oov and count(distinct cr.fn_type) = 1 then cr.fn_point end as fn_point
				from core.cd_results as cr 
				where r.id = cr.fn_route and cr.fn_user = _f_user
				group by cr.fn_point) as cr) as n_refuse_points,
		(select count(DISTINCT fn_point) from core.cd_user_points as up where r.id = up.fn_route and up.fn_user = _f_user and up.d_date::date = _d_date::date) as n_done_today_points,
		t.n_cnt_fl::int,
		t.n_cnt_ul::int,
		t.n_cnt_tu::int
	from routes as r
		left join lateral
		(select 
			sum(case when ss.b_person then 1 else 0 end) as n_cnt_fl,
			sum(case when not ss.b_person then 1 else 0 end) as n_cnt_ul,
			sum(case when rp.b_technical_metering then 1 else 0 end) as n_cnt_tu -- техучет
		from core.cd_points cp 
			inner join dbo.ed_registr_pts rp on rp.id = cp.f_registr_pts 
			inner join dbo.sd_subscr ss on ss.id = rp.f_subscr 
		where cp.f_route = r.id 
		) t on true
order by r.d_date_start;
END

Function: dbo.cf_arm_close_route(_f_current_user integer, _route_id uuid)

Returns: integer

Language: PLPGSQL

Отмена маршрута на исполнение

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {uuid} _route_id - идентификатор маршрута
*
* @returns {integer}
* 0 - ОК
* 1 - маршрут не найден
* 2 - пользователь не найден
* 3 - статус документ отличается от "Выполняется"
*
* @example
* [{ "action": "cf_arm_transfer_close", "method": "Query", "data": [{ "params": [_f_current_user, _route_id] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_c_status text; -- текущий статус маршрута
	_f_next_status_id integer; -- статус - передан
BEGIN

	IF(select count(*) from core.cd_routes as r where r.id = _route_id) = 1 THEN
	
		IF(select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN
		
			-- текущий статус
			select rs.c_const into _c_status from core.cd_routes as r
			left join core.cs_route_statuses as rs ON rs.id = r.f_status
			where r.id = _route_id;
			
			-- 488125 Операция должна быть доступна для маршрутов в статусе "Выполняется", при этом должен быть доступен множественный выбор маршрутов для выполнения операции.
			IF _c_status = 'PROCCESS' THEN
			
				-- новый статус
				select rs.id into _f_next_status_id 
				from core.cs_route_statuses as rs
				where rs.c_const = 'CANCEL';
			
				-- создаем новый статус "Выполняется"
				insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date)
				values (_route_id, _f_next_status_id, _f_current_user, now());
				
				update core.cd_routes
				set b_extended = true,
				d_extended = now() - interval '1 day'
				where id = _route_id;
				
				RETURN 0;
				
			ELSE
				RETURN 3; -- статус документ отличается от "назначен"
			END IF;
			
		ELSE
			RETURN 2; -- нет пользователя
		END IF;	
		
	ELSE
		RETURN 1; -- нет маршрута
	END IF;
END

Function: dbo.cf_arm_close_routes(_f_current_user integer, _routes json)

Returns: SET OF record

Language: PLPGSQL

Отмена нескольких маршрутов

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {json} _routes - массив маршрутов, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
*
* @returns
* возвращается таблица с двумя колонками route_id:uuid и status_id: integer, где статус может содержать значение 0 - ОК, 1 - пользователь не найден.
* дополнительные статусы можно узнать в функции dbo.cf_arm_transfer_route 
*
* @example
* [{ "action": "cf_arm_transfer_close", "method": "Query", "data": [{ "params": [_f_current_user, routes] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN
		RETURN QUERY 
		select t.value::uuid, dbo.cf_arm_close_route(_f_current_user, t.value::uuid)
		from json_array_elements_text(_routes) as t;
	ELSE
		RETURN QUERY select null, 1;
	END IF;
END

Function: dbo.cf_arm_create_route(_f_current_user integer, _registr_pts json, _d_start date, _d_end date, _c_number text, _users json, _f_route_type integer, _b_draft boolean)

Returns: SET OF record

Language: PLPGSQL

Создание маршрута на основе точек учета

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {json} _registr_pts - идент-ры точек учета, передавать в виде строку иден-ров, например '[{"id": "40170afe-498d-4ff0-a1e7-9f29d470cf0a", "f_type": 1}, {"id": "16dc8d78-04db-45ac-ab02-2112000478c2", "f_type": 2}]'
* @params {date} _d_start - дата начала, например 2020-10-07
* @params {date} _d_end - дата завершения, например 2020-10-30
* @params {text} _c_number - номер маршрута
* @params {json} _users - список исполнителей, передается в виде строки '[{"id": 4, "b_main": true}, {"id": 23, "b_main": false}]'
* @params {integer} _f_route_type - тип маршрута
* @params {boolean} _b_draft - является черновиком, предназначена для указания демонстрационного маршрута. По умолчанию передать false
*
* @returns
* 0 - OK
* 1 - нет пользователя
* 2 - точки учета не переданы
*
* @example
* [{ "action": "cf_arm_create_route", "method": "Query", "data": [{ "params": [_f_current_user, _registr_pts, _d_start, _d_end, _c_number, _users, _f_route_type, _b_draft] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_status_id integer; -- статус "Сформирован"
	_route_id uuid;
	_status_create_id integer;
BEGIN
	IF (select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN
		IF (select count(*) from json_array_elements(_registr_pts)) > 0 THEN
			select uuid_generate_v4() into _route_id;

			insert into core.cd_routes (id, f_type, c_number, d_date, d_date_start, d_date_end, c_notice, b_extended, d_extended, n_order, b_draft)
			values (_route_id, _f_route_type, _c_number, now(), _d_start, _d_end, '', false, null, 1, _b_draft);

			select rs.id into _status_create_id 
			from core.cs_route_statuses as rs
			where rs.c_const = 'CREATE';

			insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date, c_notice)
			values (_route_id, _status_create_id, _f_current_user, now(), '');

			IF _users is not null and (select count(*) from json_array_elements(_users::json)) > 0 THEN
				-- ищем статус "Сформирован"
				select rs.id into _status_id 
				from core.cs_route_statuses as rs
				where rs.c_const = 'CREATED';

				-- создаем привязку
				insert into core.cd_userinroutes(f_route, f_user, b_main)
				select 
					_route_id, 
					(t.value #>> '{id}')::integer, 
					(t.value #>> '{b_main}')::boolean 
				from json_array_elements(_users::json) as t;

				-- создаем новый статус
				insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date, c_notice)
				values (_route_id, _status_id, _f_current_user, now(), '');
			END IF;

			-- f_type = 1 задание для снятия показаний 
			insert into core.cd_points (f_registr_pts, f_route, f_type, c_notice, c_info, jb_data, n_order, sn_delete)
			select (t.value #>> '{id}')::uuid, _route_id, (t.value #>> '{f_type}')::integer, null, dbo.sf_generate_point_info(rp.id), dbo.sf_generate_point_jb_data(rp.id), 1, false
			from json_array_elements(_registr_pts) as t
			inner join dbo.ed_registr_pts as rp ON rp.id = (t.value #>> '{id}')::uuid
			left join dbo.ss_address as ad ON ad.id = rp.f_address
			order by ad.c_name;

			RETURN QUERY select _route_id, 0;
		ELSE
			RETURN QUERY select null::uuid, 2; -- точки не переданы
		END IF;
	ELSE
		RETURN QUERY select null::uuid, 1; -- нет пользователя
	END IF;
END

Function: dbo.cf_arm_ed_blank_create(_f_subdivision integer, _c_prefix text, _start bigint, _end bigint, _f_type integer, _f_user_from integer, _f_user_to integer, _f_user_mol integer, _c_notice text)

Returns: integer

Language: PLPGSQL

Создание бланк

/**
* @params {integer} _f_subdivision - подразделение, брать из справочника. По умолчанию установить из пользователя
* @params {text} _c_prefix - префикс, можно не указывать
* @params {bigint} _start - начальное заначение
* @params {bigint} _end - конечное значение
* @params {integer} _f_type - тип документа
* @params {integer} _f_user_from - текущий пользователь, который работает с бланками
* @params {integer} _f_user_to - кому передается бланк
* @params {integer} _f_user_mol - Материально ответственное лицо за получение бланков в РЭС
* @params {text} _c_notice - примечание
* Все поля должны быть обязательными, кроме префикса
*
* @returns {integer}
* 0 - ОК
* 1 - нет подразделения
* 2 - текущий пользователь не найден
* 3 - МОЛ не указан
* 4 - доступны бланки с указанными комбинациями
* 5 - запрещено создавать больше, чем 100000
*
* @example
* [{ "action": "cf_arm_ed_blank_create", "method": "Query", "data": [{ "params": [_f_subdivision, _c_prefix, _start, _end, _f_type, _f_user_from, _f_user_to, _f_user_mol, _c_notice] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.sd_subdivisions as d where d.id = _f_subdivision) = 1 THEN
		IF (select count(*) from core.pd_users as u where u.id = _f_user_from) = 1 THEN
			IF (select count(*) from core.pd_users as u where u.id = _f_user_mol) = 1 THEN
				IF (select count(*) from dbo.ed_blanks as b where b.c_prefix = _c_prefix and b.n_number between _start and _end) > 0 THEN
					RETURN 4;
				ELSE
					IF ABS(_end - _start) > 100000 THEN
						RETURN 5;
					ELSE
					insert into dbo.ed_blanks(id, n_number, f_result_type, c_prefix, c_number, f_user_from, f_user_to, f_subdivision, jb_history, f_status, n_order, dx_created, f_user_mol, c_notice)
					select 
						uuid_generate_v4(), 
						generate_series, 
						_f_type,
						_c_prefix, 
						concat(coalesce(_c_prefix, ''), generate_series::text),
						_f_user_from, 
						_f_user_to,
						--now(), -- d_date_to сказали не заполнять
						_f_subdivision,
						-- таким образом сохраняем историю
						dbo.sf_update_jb_history('[]'::json, json_build_object('f_user_to', _f_user_to,
																   			   --'d_date_to', now(),
																			   'f_status', 1)),
						1, -- По умолчания статус пломбы "Зарегистрировано"
						generate_series / 2147483647,
						now(),
						_f_user_mol,
						_c_notice
					from generate_series(_start, _end, 1);
					END IF;
				END IF;

				RETURN 0;
			ELSE
				RETURN 3;
			END IF;	
		ELSE
			RETURN 2;
		END IF;	
	ELSE
		RETURN 1;
	END IF;	
END

Function: dbo.cf_arm_ed_blank_update(_f_subdivision integer, _blanks json, _f_user_from integer, _f_user_to integer, _f_status integer, _c_document_trash text, _f_notice_trash integer, _f_user_mol integer, _c_notice text)

Returns: integer

Language: PLPGSQL

Обновление бланков

/**
* При списание указать поле f_user_to и поле d_date_to, которое потом будет являться датой списания
*
* @params {integer} _f_subdivision - подразделение
* @params {json} _blanks - список бланков, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
* @params {integer} _f_user_from - текущий пользователь, который работает с пломбами
* @params {integer} _f_user_to - кому передаются пломбы 
* @params {integer} _f_status - статус пломбы
* @params {text} _c_document_trash - номер акта списания пломбы. Указывается при статусе "Списано"
* @params {integer} _f_notice_trash - причина забраковки. Указывается при статусе "Списано". Получать из es_notice_trash
* @params {integer} _f_user_mol - Материально ответственное лицо за получение бланков в РЭС
* @params {text} _c_notice - примечание
*
* @returns {integer}
* 0 - ОК
* 1 - пользователь не найден
*
* @example
* [{ "action": "cf_arm_ed_seals_update", "method": "Query", "data": [{ "params": [_f_subdivision, _blanks, _f_user_from, _f_user_to, _f_status, _c_document_trash, _f_notice_trash, _f_user_mol, _c_notice] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF _f_user_to is null or (select count(*) from core.pd_users as u where u.id = _f_user_to) = 1 THEN
		update dbo.ed_blanks as b
		set f_status = _f_status,
		f_subdivision = _f_subdivision,
		f_user_from = _f_user_from,
		f_user_to = _f_user_to,
		d_date_to = now(),
		c_document_trash = _c_document_trash,
		f_notice_trash = _f_notice_trash,
		c_notice = _c_notice,
		f_user_mol = case when _f_user_mol is null then b.f_user_mol else _f_user_mol end
		where b.id IN (select t.value::uuid from json_array_elements_text(_blanks) as t);
		RETURN 0;
	ELSE
		RETURN 1; -- пользователь не найден
	END IF;	
END

Function: dbo.cf_arm_ed_blanks(_id uuid, _f_subdivision integer, _f_user_from integer, _f_user_to integer, _c_prefix text, _n_start_number bigint, _n_end_number bigint, _d_start_send date, _d_end_send date, _d_start_setup date, _d_end_setup date, _d_start_trash date, _d_end_trash date, _f_type integer, _f_user_mol integer, _c_owner text, _f_status integer)

Returns: SET OF record

Language: PLPGSQL

Поиск бланков

/**
* @params {uuid} _id - иден. пломбы
* @params {integer} _f_subdivision - подразделение
* @params {integer} _f_user_from - выдал
* @params {integer} _f_user_to - получил
* @params {text} _c_prefix - префикс
* @params {integer} _n_start_number - номер с
* @params {integer} _n_end_number - номер по
* @params {date} _d_start_send - дата выдачи с
* @params {date} _d_end_send - дата выдачи по
* @params {date} _d_start_setup - дата установки с
* @params {date} _d_end_setup - дата установки по
* @params {date} _d_start_trash - дата списания с
* @params {date} _d_end_trash - дата списания по
* @params {integer} _f_type - Тип документа
* @params {text} _c_owner - ФИО/наименование
* @params {integer} _f_status - статус
* @params {integer} _f_user_mol - Материально ответственное лицо за получение бланков в РЭС
*
* @example
* [{ "action": "cf_arm_ed_blanks", "method": "Query", "data": [{ "params": [_id, _f_subdivision, _f_user_from, _f_user_to, _c_prefix, _n_start_number, _n_end_number, _d_start_send, _d_end_send, _d_start_setup, _d_end_setup, _d_start_trash, _d_end_trash, _f_type, _f_user_mol, _c_owner, _f_status] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	return query 
	select 
		t.*, 
		nt.c_name as c_notice_trash
	from (select
		b.id, -- иден. пломбы
		b.f_subdivision, -- иден. подразделение
		sd.c_name as c_subdivision, -- подразделение
		rtb.id as f_result_type, -- иден.типа документа
		rtb.c_name as c_result_type, -- наимен. типа документа
		b.c_prefix, -- префикс
		b.c_number, -- номер бланков
		b.n_number, -- номер бланков
		uf.c_first_name as c_first_name_from, -- кто выдал
		uf.c_last_name as c_last_name_from, -- кто выдал
		uf.c_middle_name as c_middle_name_from, -- кто выдал
		uf.id as f_user_from, -- иден. кто выдал
		ut.c_first_name as c_first_name_to, -- кто получил
		ut.c_last_name as c_last_name_to, -- кто получил
		ut.c_middle_name as c_middle_name_to, -- кто получил
		ut.id as f_user_to, -- иден. кто получил
		b.d_date_to::date, -- дата выдачи
		bs.c_name as c_blank_status, -- статус бланков
		bs.id as f_blank_status, -- иден. статуса бланков
		b.dx_created, -- дата создания
		r.d_date::date as d_date_setup, -- дата установки
		r.id as f_result, -- иден. документа
		rt.c_name as c_result_name, -- наименование документа
		(case when bs.c_const = 'TRASH' then ut.id else null end) as f_user_trashed, -- кто списал, тот же кто и получил ранее
		(case when bs.c_const = 'TRASH' then b.d_date_to::date else null end) as d_date_trashed, -- дата списания	   
		(case when bs.c_const = 'TRASH' then b.c_document_trash else null end) as c_document_trash, -- Номер акта списания
		(case when bs.c_const = 'TRASH' then b.f_notice_trash else null end) as f_notice_trash, -- Причина списания
		case when sub.b_person then concat(sub.c_name1, ' ', sub.c_name2, ' ', sub.c_name3) else sub.c_name1 end as c_owner, -- потребитель
		b.f_user_mol, -- Материально ответственное лицо за получение бланков в РЭС
		b.c_notice -- Примечание
	from dbo.ed_blanks as b
	inner join core.cs_result_types as rtb ON b.f_result_type = rtb.id
	inner join dbo.es_blank_status as bs ON b.f_status = bs.id
	left join core.sd_subdivisions as sd ON sd.id = b.f_subdivision
	left join core.cd_results as r ON r.jb_data#>>'{f_act_number}' = b.id::text
	left join core.cs_result_types as rt ON rt.id = r.fn_type
	left join core.cd_points as p ON p.id = r.fn_point
	left join dbo.ed_registr_pts as rp ON rp.id = p.f_registr_pts
	left join dbo.sd_subscr as sub ON sub.id = rp.f_subscr
	left join core.pd_users as uf ON b.f_user_from = uf.id
	left join core.pd_users as ut ON b.f_user_to = ut.id) as t
	left join dbo.es_notice_trash as nt ON nt.id = t.f_notice_trash
	where 
	(case when _id is null then 1=1 else t.id = _id end) and
	(case when _f_subdivision is null then 1=1 else t.f_subdivision = _f_subdivision end) and
	(case when _f_user_from is null then 1=1 else t.f_user_from = _f_user_from end) and
	(case when _f_user_to is null then 1=1 else t.f_user_to = _f_user_to end) and
	(case when _c_prefix is null then 1=1 else t.c_prefix = _c_prefix end) and
	(case when _n_start_number is null then 1=1 when _n_start_number is not null and _n_end_number is null then t.n_number = _n_start_number else t.n_number between _n_start_number and _n_end_number + 1 end) and
	(case when _d_start_send is null then 1=1 when _d_start_send is not null and _d_end_send is null then t.d_date_to = _d_start_send else t.d_date_to between _d_start_send and _d_end_send + interval '1 day' end) and
	(case when _d_start_setup is null then 1=1 when _d_start_setup is not null and _d_end_setup is null then t.d_date_setup = _d_start_setup else t.d_date_setup between _d_start_setup and _d_end_setup + interval '1 day' end) and
	(case when _d_start_trash is null then 1=1 when _d_start_trash is not null and _d_end_trash is null then t.d_date_trashed = _d_start_trash else t.d_date_trashed between _d_start_trash and _d_end_trash + interval '1 day' end) and
	(case when _f_type is null then 1=1 else t.f_result_type = _f_type end) and
	(case when _f_status is null then 1=1 else t.f_blank_status = _f_status end) and
	(case when _f_user_mol is null then 1=1 else t.f_user_mol = _f_user_mol end);
END

Function: dbo.cf_arm_ed_blanks_remove(_blanks json)

Returns: integer

Language: PLPGSQL

Удление бланков

/**
* Внимание! Удаление бланков может привести к потере данных
*
* @params {json} _blanks - список пломб, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
*
* @returns {integer}
* 0 - ОК
*
* @example
* [{ "action": "cf_arm_ed_blanks_remove", "method": "Query", "data": [{ "params": [_blanks] }], "type": "rpc", "tid": 0}]
*/
BEGIN
		delete from dbo.ed_blanks as b
		where b.f_status = 1 and -- статус "Зарегистрировано"
		b.id in (select t.value::uuid from json_array_elements_text(_blanks) as t);
		
		RETURN 0;
END

Function: dbo.cf_arm_ed_registr_pts()

Returns: SET OF record

Language: PLPGSQL

Этап "Планирование": получение списка точек учета

/**
* @example 
* [{ "action": "cf_arm_ed_registr_pts", "method": "Select", "data": [{ }], "type": "rpc", "tid": 0 }]
*
* @todo 
* колонка b_meter_exists - возвращается доступность показания, для снятия показаний точка валидна
*/
BEGIN
	RETURN QUERY
	select 
		rp.id, 
		rp.c_address, 
		ad.n_geo_lon, 
		ad.n_geo_lat, 
		rp.f_division, 
		d.c_name, 
		rp.f_subdivision, 
		sd.c_name, 
		rp.c_device_number, 
		rp.c_subscr, 
		rp.c_owner, 
		rp.d_meter_date, 
		rp.c_network_item, 
		rp.c_network_type, 
		rp.f_device_type, 
		dt.c_name, 
		(select count(*) from dbo.ed_output_meter_readings as omr
		inner join dbo.ed_input_meter_readings as imr ON imr.id = omr.fn_meter_reading
		where imr.f_registr_pts = rp.id) > 0, 
		rp.b_disabled 
	from dbo.ed_registr_pts as rp
	left join dbo.ss_address as ad ON ad.id = rp.f_address
	inner join core.sd_divisions as d ON rp.f_division = d.id
	inner join core.sd_subdivisions as sd ON rp.f_subdivision = sd.id
	inner join dbo.es_device_types as dt ON rp.f_device_type = dt.id;
END

Function: dbo.cf_arm_ed_seals(_id uuid, _f_subdivision integer, _f_user_from integer, _f_user_to integer, _c_prefix text, _n_start_number bigint, _n_end_number bigint, _d_start_send date, _d_end_send date, _d_start_setup date, _d_end_setup date, _d_start_trash date, _d_end_trash date, _f_type integer, _f_place integer, _c_device_number text, _f_registr_pts uuid, _f_status integer, _f_user_mol integer)

Returns: SET OF record

Language: PLPGSQL

Поиск пломбы

/**
* @params {uuid} _id - иден. пломбы
* @params {integer} _f_subdivision - подразделение
* @params {integer} _f_user_from - выдал
* @params {integer} _f_user_to - получил
* @params {text} _c_prefix - префикс
* @params {bigint} _n_start_number - номер с
* @params {bigint} _n_end_number - номер по
* @params {date} _d_start_send - дата выдачи с
* @params {date} _d_end_send - дата выдачи по
* @params {date} _d_start_setup - дата установки с
* @params {date} _d_end_setup - дата установки по
* @params {date} _d_start_trash - дата списания с
* @params {date} _d_end_trash - дата списания по
* @params {integer} _f_type - Тип пломбы
* @params {integer} _f_place - Место установки
* @params {uuid} _f_registr_pts - потребитель
* @params {text} _c_device_number - Номер ПУ
* @params {integer} _f_status - статус
* @params {integer} _f_user_mol - Материально ответственное лицо за получение пломб в РЭС
*
* @example
* [{ "action": "cf_arm_ed_seals", "method": "Query", "data": [{ "params": [_id, _f_subdivision, _f_user_from, _f_user_to, _c_prefix, _n_start_number, _n_end_number, _d_start_send, _d_end_send, _d_start_setup, _d_end_setup, _d_start_trash, _d_end_trash, _f_type, _f_place, _f_registr_pts, _c_device_number, _f_status, _f_user_mol] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	return query 
	select 
		t.*, 
		nt.c_name as c_notice_trash 
	from (select
		s.id, -- иден. пломбы
		s.f_subdivision, -- иден. подразделение
		sd.c_name as c_subdivision, -- подразделение
		st.id as f_seal_type, -- иден. типа пломбы
		st.c_name as c_seal_type, -- тип пломбы
		s.c_prefix, -- префикс
		s.c_number, -- номер пломбы
		s.n_number, -- номер пломбы
		uf.c_first_name as c_first_name_from, -- кто выдал
		uf.c_last_name as c_last_name_from, -- кто выдал
		uf.c_middle_name as c_middle_name_from, -- кто выдал
		uf.id as f_user_from, -- иден. кто выдал
		ut.c_first_name as c_first_name_to, -- кто получил
		ut.c_last_name as c_last_name_to, -- кто получил
		ut.c_middle_name as c_middle_name_to, -- кто получил
		ut.id as f_user_to, -- иден. кто получил
		s.d_date_to::date, -- дата выдачи
		ss.c_name as c_seal_status, -- статус пломбы
		ss.id as f_seal_status, -- иден. статуса пломбы
		s.dx_created, -- дата создания
		ocs.d_date::date as d_date_setup, -- дата установки
		coalesce(sp.id, sp1.id) as f_seal_place, -- иден. место установки
		coalesce(sp.c_name, sp1.c_name) as c_seal_place, -- место установки
		d.c_serial_number, -- Номер ПУ
		rp.id as f_registr_pts, -- иден. точки учета
		case when sub.b_person then concat(sub.c_name1, ' ', sub.c_name2, ' ', sub.c_name3) else sub.c_name1 end as c_owner, -- потребитель
		r.id as f_result, -- иден. документа
		rt.c_name as c_result_name, -- наименование документа
		(case when ss.c_const = 'TRASH' then ut.id else null end) as f_user_trashed, -- кто списал, тот же кто и получил ранее
		(case when ss.c_const = 'TRASH' then s.d_date_to::date else null end) as d_date_trashed, -- дата списания
		(case when ss.c_const = 'TAKE_OFF' then s.d_date_to::date else null end) as d_date_take_off, -- дата снятия		   
		(case when ss.c_const = 'TRASH' then s.c_document_trash else null end) as c_document_trash, -- Номер акта списания
		(case when ss.c_const = 'TRASH' then s.f_notice_trash else null end) as f_notice_trash, -- Причина забраковки
		s.f_user_mol, -- Материально ответственное лицо за получение пломб в РЭС
		s.c_notice -- Примечание
	from dbo.ed_seals as s
	inner join dbo.es_seal_status as ss ON s.f_status = ss.id
	left join core.sd_subdivisions as sd ON sd.id = s.f_subdivision
	left join dbo.ed_output_conn_seals as ocs ON s.id = ocs.fn_seal_new
	left join core.cd_results as r ON ocs.fn_result = r.id
	left join core.cs_result_types as rt ON rt.id = r.fn_type
	left join dbo.ed_registr_pts as rp ON rp.id = s.f_registr_pts
	left join dbo.sd_subscr as sub ON sub.id = rp.f_subscr
	left join dbo.es_seal_places as sp ON s.f_place = sp.id
	left join dbo.es_seal_types as st ON s.f_type = st.id
		  
	left join dbo.es_seal_places as sp1 ON ocs.fn_place = sp1.id
	left join dbo.es_seal_types as st1 ON ocs.fn_type = st1.id
		  
	left join dbo.ed_devices as d ON s.f_registr_pts = d.f_registr_pts
	left join core.pd_users as uf ON s.f_user_from = uf.id
	left join core.pd_users as ut ON s.f_user_to = ut.id) as t
	left join dbo.es_notice_trash as nt ON nt.id = t.f_notice_trash
	where 
	(case when _id is null then 1=1 else t.id = _id end) and
	(case when _f_subdivision is null then 1=1 else t.f_subdivision = _f_subdivision end) and
	(case when _f_user_from is null then 1=1 else t.f_user_from = _f_user_from end) and
	(case when _f_user_to is null then 1=1 else t.f_user_to = _f_user_to end) and
	(case when _c_prefix is null then 1=1 else t.c_prefix = _c_prefix end) and
	(case when _n_start_number is null then 1=1 when _n_start_number is not null and _n_end_number is null then t.n_number = _n_start_number else t.n_number between _n_start_number and _n_end_number + 1 end) and
	(case when _d_start_send is null then 1=1 when _d_start_send is not null and _d_end_send is null then t.d_date_to = _d_start_send else t.d_date_to between _d_start_send and _d_end_send + interval '1 day' end) and
	(case when _d_start_setup is null then 1=1 when _d_start_setup is not null and _d_end_setup is null then t.d_date_setup = _d_start_setup else t.d_date_setup between _d_start_setup and _d_end_setup + interval '1 day' end) and
	(case when _d_start_trash is null then 1=1 when _d_start_trash is not null and _d_end_trash is null then t.d_date_trashed = _d_start_trash else t.d_date_trashed between _d_start_trash and _d_end_trash + interval '1 day' end) and
	(case when _f_type is null then 1=1 else t.f_seal_type = _f_type end) and
	(case when _f_place is null then 1=1 else t.f_seal_place = _f_place end) and
	(case when _c_device_number is null then 1=1 else t.c_serial_number = _c_device_number end) and
	(case when _f_registr_pts is null then 1=1 else t.f_registr_pts = _f_registr_pts end) and
	(case when _f_status is null then 1=1 else t.f_seal_status = _f_status end) and
	(case when _f_user_mol is null then 1=1 else t.f_user_mol = _f_user_mol end);
END

Function: dbo.cf_arm_ed_seals_create(_f_subdivision integer, _c_prefix text, _start bigint, _end bigint, _f_type integer, _f_user_from integer, _f_user_to integer, _f_user_mol integer, _c_notice text)

Returns: integer

Language: PLPGSQL

Создание пломбы

/**
* @params {integer} _f_subdivision - подразделение, брать из справочника. По умолчанию установить из пользователя
* @params {text} _c_prefix - префикс, можно не указывать
* @params {bigint} _start - начальное заначение
* @params {bigint} _end - конечное значение
* @params {integer} _f_type - тип пломбы
* @params {integer} _f_user_from - текущий пользователь, который работает с пломбами
* @params {integer} _f_user_to - кому передается пломба
* @params {integer} _f_user_mol - Материально ответственное лицо за получение пломб в РЭС
* @params {text} _c_notice - примечание
* Все поля должны быть обязательными, кроме префикса
*
* @returns {integer}
* 0 - ОК
* 1 - нет подразделения
* 2 - текущий пользователь не найден
* 3 - кому передается пломба не найдена
* 4 - доступны пломбы с указанными комбинациями
* 5 - запрещено создавать больше, чем 100000
*
* @example
* [{ "action": "cf_arm_ed_seals_create", "method": "Query", "data": [{ "params": [_f_subdivision, _c_prefix, _start, _end, _f_type, _f_user_from, _f_user_to, _f_user_mol, _c_notice] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.sd_subdivisions as d where d.id = _f_subdivision) = 1 THEN
		IF (select count(*) from core.pd_users as u where u.id = _f_user_from) = 1 THEN
			--IF (select count(*) from core.pd_users as u where u.id = _f_user_to) = 1 THEN
				IF (select count(*) from dbo.ed_seals as b where b.c_prefix = _c_prefix and b.n_number between _start and _end) > 0 THEN
					RETURN 4;
				ELSE
					IF ABS(_end - _start) > 100000 THEN
						RETURN 5;
					ELSE
					insert into dbo.ed_seals(id, n_number, f_type, c_prefix, c_number, f_user_from, f_user_to, f_subdivision, jb_history, f_status, n_order, dx_created, f_user_mol, c_notice)
					select 
						uuid_generate_v4(), 
						generate_series, 
						_f_type,
						_c_prefix, 
						generate_series::text,
						_f_user_from, 
						_f_user_to,
						--now(), -- d_date_to сказали не заполнять
						_f_subdivision,
						-- таким образом сохраняем историю
						dbo.sf_update_jb_history('[]'::json, json_build_object('f_user_to', _f_user_to,
																   			   --'d_date_to', now(),
																			   'f_status', 1)),
						1, -- По умолчания статус пломбы "Зарегистрировано"
						generate_series / 2147483647,
						now(),
						_f_user_mol,
						_c_notice
					from generate_series(_start, _end, 1);
					END IF;
				END IF;

				RETURN 0;
			--ELSE
				--RETURN 3;
			--END IF;	
		ELSE
			RETURN 2;
		END IF;	
	ELSE
		RETURN 1;
	END IF;	
END

Function: dbo.cf_arm_ed_seals_remove(_seals json)

Returns: integer

Language: PLPGSQL

Удление пломб

/**
* Внимание! Удаление пломб может привести к потере данных
*
* @params {json} _seals - список пломб, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
*
* @returns {integer}
* 0 - ОК
*
* @example
* [{ "action": "cf_arm_ed_seals_remove", "method": "Query", "data": [{ "params": [_seals] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	delete from dbo.ed_seals as s
	where s.f_status = 1 and -- статус "Зарегистрировано"
	s.id in (select t.value::uuid from json_array_elements_text(_seals) as t);

	RETURN 0;
END

Function: dbo.cf_arm_ed_seals_update(_f_subdivision integer, _seals json, _f_user_from integer, _f_user_to integer, _f_status integer, _c_document_trash text, _f_notice_trash integer, _f_user_mol integer, _c_notice text)

Returns: integer

Language: PLPGSQL

Обновление пломб

/**
* При списание указать поле f_user_to и поле d_date_to, которое потом будет являться датой списания
*
* @params {integer} _f_subdivision - подразделение
* @params {json} _seals - список пломб, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
* @params {integer} _f_user_from - текущий пользователь, который работает с пломбами
* @params {integer} _f_user_to - кому передаются пломбы 
* @params {integer} _f_status - статус пломбы
* @params {text} _c_document_trash - номер акта списания пломбы. Указывается при статусе "Списано"
* @params {integer} _f_notice_trash - причина забраковки. Указывается при статусе "Списано". Получать из es_notice_trash
* @params {integer} _f_user_mol - Материально ответственное лицо за получение пломб в РЭС
* @params {text} _c_notice - примечание
*
* @returns {integer}
* 0 - ОК
* 1 - пользователь не найден
*
* @example
* [{ "action": "cf_arm_ed_seals_update", "method": "Query", "data": [{ "params": [_f_subdivision, _seals, _f_user_from, _f_user_to, _f_status, _c_document_trash, _f_notice_trash, _f_user_mol, _c_notice] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF _f_user_to is null or (select count(*) from core.pd_users as u where u.id = _f_user_to) = 1 THEN
		update dbo.ed_seals as s
		set f_status = _f_status,
		f_subdivision = _f_subdivision,
		f_user_from = _f_user_from,
		f_user_to = _f_user_to,
		d_date_to = now(),
		c_document_trash = _c_document_trash,
		f_notice_trash = _f_notice_trash,
		c_notice = _c_notice,
		f_user_mol = case when _f_user_mol is null then s.f_user_mol else _f_user_mol end
		where s.id IN (select t.value::uuid from json_array_elements_text(_seals) as t);
		RETURN 0;
	ELSE
		RETURN 1; -- пользователь не найден
	END IF;	
END

Function: dbo.cf_arm_filtration(_c_ps text, _c_line_ps text, _c_rp text, _c_line_rp text, _c_tp text, _c_line_tp text, _c_line_segment_1 text, _c_raion text, _c_city text, _c_settle text, _c_street text, _c_house text, _c_house_build text, _c_device_location text, _b_askue boolean, _c_askue text, _n_mpi smallint, _f_div integer, _f_subdiv integer, _n_registr_pts_type integer, _c_registr_pts_name text, _f_consume_status integer, _b_problem boolean, _b_violation boolean, _n_check_date integer, _b_person boolean, _f_delivery integer, _d_date_begin date, _d_date_end date, _n_absent_period integer, _b_strong_check boolean, _f_event integer, _d_date_period date, _b_plan boolean, _f_no_plan_work smallint, _f_point_type integer, _b_no_plan boolean, _d_no_plan_date date, _f_registr_pts_status integer, _n_month_last_check_date integer, _f_fias uuid)

Returns: SET OF record

Language: PLPGSQL

/*
  	Список возможных параметров:
 		_c_ps text default null, -- ПС
		_c_line_ps text default null, -- фидер от ПС
		_c_rp text default null, -- РП
		_c_line_rp text default null, -- фидер от РП
		_c_tp text default null, --ТП
		_c_line_tp text default null, -- фидер от ТП
		
		-- адрес
		_c_raion text default null, -- район
		_c_city text default null, -- город
		_c_settle text default null, -- населенный пункт
		_c_street text default null, -- улица
		_c_house text default null, -- дом
		_c_house_build text default null, -- корпус
		_f_fias uuid default null, -- идентификатор адреса в ФИАС
	
		-- ПУ
		_c_device_location text default null,
		_b_ASKUE bool default null,
		_c_ASKUE text default null,
		_n_mpi smallint default null,
	
		-- ТУ
		_f_div int default null, -- ссылка на отделение 37. Обязательно к заполнению
		_f_subdiv int default null, -- ссылка на участок 66. Обязательно к заполнению
		_n_registr_pts_type int default null, -- ЮЛ\ТУ\ФЛ
		_с_registr_pts_name text default null, -- наименование ТУ
		_f_consume_status int default null, -- сссылка на статус потребления
		_b_problem bool default null, -- признак проблемного абонента
		_b_violation bool default null, --наличие неисполненного предписания
		_n_check_date int default null, -- дата (день) обхода
		_b_person boolean default null -- признак ФЛ/ЮЛ
	
		-- показания
		_f_delivery int default null, -- источник показаний
		_d_date_begin date default null, -- начало периода даты показаний
		_d_date_end date default null, -- окончание периода даты показаний
		_n_absent_period int default null, -- период (количество месяцев) с отсутствующими показаниями
		_b_strong_check bool default null, -- ищем строго заданное количество месяцев с отсутствующими показаниями (true) или более (false)
		_f_event int default null -- вид работ
		
		-- планирование
		_d_date_period date DEFAULT NULL::date -- период просмотра данных, если это поле не передавать, то фильтрации в истории ТУ не будет см. ed_registr_pts_history
		_b_plan boolean DEFAULT NULL::boolean -- является плановым или нет
		_f_no_plan_work smallint DEFAULT NULL::smallint -- тип внеплановой работы. см. es_no_plan_works
		_b_no_plan boolean DEFAULT NULL::boolean, -- признак что точка является внеплановой
		_d_no_plan_date date DEFAULT NULL::date, -- планируемая дата выполнения работ по внеплановой точке. Будет заполняться при импорте внеплановых работ/ручном указании внеплановых работ по точке учета через АРМ Диспетчера
		_f_registr_pts_status integer DEFAULT NULL::integer -- Статус активности ТУ
		_n_month_last_check_date integer DEFAULT NULL::integer -- Последняя инструментальная проверка была проведена более чем n месяцев
		
	Пример запроса:
		select * from dbo.cf_arm_filtration(
			_f_div => 37,
			_f_subdiv => 66,
			_c_ps => 'руд')
*/
DECLARE
	_d_start_period date;
	_p_date_begin date = (now() - interval'3 year')::date; -- начало периода даты показаний. По умолчанию начальная дата годь назад
	_p_date_end date = now()::date; -- окончание периода даты показаний. По умолчанию текущая дата
	_n_object_type_level int4; -- уровень адреса ФИАС
	_f_fias_nil uuid = uuid_nil(); -- пустой идентификатор фиас
BEGIN	
	-- проверка обязательных параметров
	if _f_div is null and _f_subdiv is null then
		raise exception 'Не заданы Филиал/РЭС';
	end if;

	if _d_date_begin is not null then _p_date_begin = _d_date_begin; end if;
	if _d_date_end is not null then _p_date_end = _d_date_end; end if;

	select n_object_type_level into _n_object_type_level from dbo.ss_fias_address as sfa where sfa.id = _f_fias;

		--  список ТУ заданной РЭС
	create temp table t_registr_pts (
		id uuid,
		c_registr_pts text,
		f_status_consume int,
		b_technical_metering bool,
		f_subscr uuid,
		f_address uuid,
		c_ps text,
		c_line_ps text,
		c_rp text,
		c_line_rp text,
		c_tp text,
		c_line_tp text,
		c_line_segment_1 text,
		c_raion text,
		c_city_name text,
		c_settlement_name text,
		c_street_name text,
		c_house text,
		c_house_build text,
		b_person boolean,
		f_registr_pts_status integer
	) on commit drop;

/*
	if _c_ps is not null then
		create index trgm_c_ps_idx ON t_registr_pts USING GIN (c_ps gin_trgm_ops);
	end if;
	if _c_line_ps is not null then
		create index trgm_c_line_ps_idx ON t_registr_pts USING GIN (c_line_ps gin_trgm_ops);
	end if;
	if _c_rp is not null then
		create index trgm_c_rp_idx ON t_registr_pts USING GIN (c_rp gin_trgm_ops);
	end if;
	if _c_line_rp is not null then
		create index trgm_c_line_rp_idx ON t_registr_pts USING GIN (c_line_rp gin_trgm_ops);
	end if;
	if _c_tp is not null then
		create index trgm_c_tp_idx ON t_registr_pts USING GIN (c_tp gin_trgm_ops);
	end if;
	if _c_line_tp is not null then
		create index trgm_c_line_tp_idx ON t_registr_pts USING GIN (c_line_tp gin_trgm_ops);
	end if;
	if _c_raion is not null then
		create index trgm_c_raion_idx ON t_registr_pts USING GIN (c_raion gin_trgm_ops);
	end if;
	if _c_city is not null then
		create index trgm_c_city_name_idx ON t_registr_pts USING GIN (c_city_name gin_trgm_ops);
	end if;
	if _c_settle is not null then
		create index trgm_c_settlement_name_idx ON t_registr_pts USING GIN (c_settlement_name gin_trgm_ops);
	end if;
	if _c_street is not null then
		create index trgm_c_street_name_idx ON t_registr_pts USING GIN (c_street_name gin_trgm_ops);
	end if;
*/
	insert into t_registr_pts(
		id,
		c_registr_pts,
		f_status_consume,
		b_technical_metering,
		f_subscr,
		f_address,
		c_ps,
		c_line_ps,
		c_rp,
		c_line_rp,
		c_tp,
		c_line_tp,
		c_line_segment_1,
		c_raion,
		c_city_name,
		c_settlement_name,
		c_street_name,
		c_house,
		c_house_build,
		b_person,
		f_registr_pts_status
	)
	select 
		t.id,
		t.c_registr_pts,
		t.f_status_consume,
		t.b_technical_metering,
		t.f_subscr,
		t.f_address,
		t.c_substation as c_ps,
		t.c_line_substation as c_line_ps,
		t.c_rp,
		t.c_line_rp,
		t.c_tp,
		t.c_line_tp,
		t.c_line_segment_1,
		sa.c_raion,
		sa.c_city_name,
		sa.c_settlement_name,
		sa.c_street_name,
		sa.c_house_name,
		sa.c_block_name,
		sub.b_person,
		t.f_registr_pts_status
	from dbo.ed_registr_pts as t
	left join dbo.ss_address as sa on sa.id = t.f_address
	left join dbo.sd_subscr as sub ON sub.id = t.f_subscr
	where t.f_division = _f_div and t.f_subdivision = _f_subdiv
	and (case when _f_registr_pts_status is null then 1=1 else _f_registr_pts_status = t.f_registr_pts_status end)
	and (case when _f_consume_status is null then 1=1 else _f_consume_status = t.f_status_consume end)
	and (case when _f_fias is null or _n_object_type_level is null 
			then true 
			else case _n_object_type_level 	when 1 then sa.code_fias_region = _f_fias 
											when 3 then sa.data_area_fias_id = _f_fias
											when 4 then sa.data_city_fias_id = _f_fias
											when 6 then sa.settlement_fias_id = _f_fias
											when 7 then sa.data_street_fias_id = _f_fias
											when 8 then sa.data_house_fias_id = _f_fias
				end 
		end);
--/*
	-- далее отсекать все фильтры
	-- СЕТЬ
	if _c_ps is not null then
		delete from t_registr_pts t
		where coalesce(lower(t.c_ps), '') not like '%'||lower(_c_ps)||'%';
	end if;
	if _c_line_ps is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_line_ps), '') not like '%'||lower(_c_line_ps)||'%';
	end if;
	if _c_rp is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_rp), '') not like '%'||lower(_c_rp)||'%';
	end if;
	if _c_line_rp is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_line_rp), '') not like '%'||lower(_c_rp)||'%';
	end if;
	if _c_tp is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_tp), '') not like '%'||lower(_c_tp)||'%';
	end if;
	if _c_line_tp is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_line_tp), '') not like '%'||lower(_c_line_tp)||'%';
	end if;

	-- АДРЕСА
	if _c_raion is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_raion), '') not like '%'||lower(_c_raion)||'%';
	end if;
	if _c_city is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_city_name), '') not like '%'||lower(_c_city)||'%';
	end if;
	if _c_settle is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_settlement_name), '') not like '%'||lower(_c_settle)||'%';
	end if;
	if _c_street is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_street_name), '') not like '%'||lower(_c_street)||'%';
	end if;
	
	if _c_house is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_house), '') != lower(_c_house);
	end if;

	if _c_house_build is not null then
		delete from t_registr_pts t 
		where coalesce(lower(t.c_house_build), '') != lower(_c_house_build);
	end if;

	if _b_person is not null then
		delete from t_registr_pts t 
		where t.b_person != _b_person;
	end if;

	if _c_line_segment_1 is not null then 
		delete from t_registr_pts t
		where coalesce(lower(t.c_line_segment_1), '') not like '%'||lower(_c_line_segment_1)||'%';
	end if; 

	-- ПОКАЗАНИЯ
	if _f_delivery is not null then
		delete from t_registr_pts t
		where not exists (
			select 1 
			from dbo.ed_input_meter_readings eimr 
			where eimr.f_registr_pts = t.id
				and eimr.f_delivery_method = _f_delivery);
	end if;
--*/
--select count(*) into _n_cnt from t_registr_pts;
--raise notice '%', _n_cnt;

--	убираем ТУ, где нет показаний за указанный период
--/*
	if _d_date_begin is not null then
		delete from t_registr_pts t
		where not exists (
			select 1 
			from dbo.ed_input_meter_readings eimr 
			where eimr.f_registr_pts = t.id
				and eimr.d_date_prev between _p_date_begin and coalesce(_p_date_end, now()::date) );
	end if;
--*/			
	if _n_absent_period is not null then
		select now() - (_n_absent_period + case when _b_strong_check then 0 else 1 end) * interval'1 month'  into _d_start_period;
		-- убираем ТУ, где есть показания после даты _d_start_period
		delete from t_registr_pts t
		where exists (
			select 1 
			from dbo.ed_input_meter_readings eimr 
			where eimr.f_registr_pts = t.id
				and eimr.d_date_prev > _d_start_period);
	end if;

--select count(*) into _n_cnt from t_registr_pts;
--raise notice '%', _n_cnt;

	RETURN QUERY
	with history as (
		select 
			rpth.id,
			rpth.f_registr_pts, 
			rpth.b_plan, 
			rpth.f_no_plan_work,
			npw.c_name as c_no_plan_work,
			rt.c_const as c_route_const,
			pt.id as f_point_type,
			pt.c_name as c_point_type,
			rpth.b_no_plan,
			rpth.d_no_plan_date
		from dbo.ed_registr_pts_history as rpth
		left join dbo.es_no_plan_works as npw ON npw.id = rpth.f_no_plan_work
		left join (select p.f_registr_pts, p.f_route, r.b_extended, r.d_extended, r.d_date_end, p.f_type from core.cd_points as p
				  inner join core.cd_routes as r ON p.f_route = r.id
				  where date_trunc('MONTH',(case when r.b_extended then r.d_extended else r.d_date_end end))::date = _d_date_period) as t ON rpth.f_registr_pts = t.f_registr_pts and t.f_type = rpth.f_point_type
		left join core.cd_routes as r ON r.id = t.f_route and date_trunc('MONTH',(case when r.b_extended then r.d_extended else r.d_date_end end))::date = _d_date_period
		left join core.cs_route_types as rt ON rt.id = r.f_type
		left join core.cs_point_types as pt ON pt.id = rpth.f_point_type
		where
			(case when _d_no_plan_date is not null then rpth.d_no_plan_date = _d_no_plan_date else 1=1 end) and
			(case when _d_date_period is not null then rpth.d_date_period = _d_date_period else rpth.d_date_period is null end) and
			(case when _b_plan is not null then rpth.b_plan = _b_plan else 1=1 end) and
			(case when _b_no_plan is not null then rpth.b_no_plan = _b_no_plan else 1=1 end) and
			(case when _f_no_plan_work is not null then rpth.f_no_plan_work = _f_no_plan_work else 1=1 end) and
			(case when _f_point_type is not null then rpth.f_point_type = _f_point_type else 1=1 end)
	)
	select 
		t.id,
		sd2.c_name as c_filial,
		sd.c_name as c_pes,
		ss2.c_name as c_res,
		
		ss.f_partners as c_partners_code,
		case when ss.b_person then ss.c_name1 || ' ' || ss.c_name2 || ' ' || ss.c_name3 else ss.c_name1 end as c_subscr_name,
		ss.c_code as c_subscr_code,
		
		erp.imp_text as c_registr_pts_code,
		t.c_registr_pts,
		erp.c_status_registr_pts,
		erp.d_close_date as d_tu_close_date,
		ss.n_check_date,
		ss.b_problem_person,
		t.f_status_consume, -- привести справочник
		esc.c_name as c_status_consume,
		t.b_technical_metering,
		erp.c_status,
		erp.c_predictr,
		
		ed.c_serial_number,
		edt.c_name as c_device_type,
		coalesce(ed.b_askue, false) as b_askue,
		edt.b_phase3,
		ed.d_setup_date,
		ed.d_close_date as d_pu_close_date,
		ed.d_valid_date,

		t.c_ps,
		t.c_line_ps,
		t.c_rp,
		t.c_line_rp,
		t.c_tp,
		t.c_line_tp,
		t.c_raion,
		t.c_city_name,
		t.c_settlement_name,
		t.c_street_name,
		erp.c_line_segment_1,
		sa.c_house_name,
		sa.c_block_name,
		sa.c_flat_name,
		sa.n_geo_lat,
		sa.n_geo_lon,
		case 
			when sa.c_name is not null then '(Оригинальный адрес: '||sa.c_name ||') '
			else ''
		end || coalesce(sa.c_comment_address, '') as c_comment_address,
		t.b_person,
		_d_date_period as d_date_period,
		hst.b_plan as b_plan,
		hst.f_no_plan_work as f_no_plan_work,
		hst.c_no_plan_work as c_no_plan_work,
		hst.c_route_const as c_route_const,
		hst.f_point_type as f_point_type,
		hst.c_point_type as c_point_type,
		hst.id as f_registr_pts_history,
		hst.b_no_plan,
		hst.d_no_plan_date,
		t.f_registr_pts_status,
		rps.c_name,
		de.d_last_check_date,
		erp.b_sub,
		erp.b_transit
	from t_registr_pts as t
		left join dbo.es_registr_pts_status as rps ON t.f_registr_pts_status = rps.id
		inner join dbo.ed_registr_pts as erp
			on erp.id = t.id
		inner join dbo.sd_subscr as ss
			on ss.id = erp.f_subscr 
		left join dbo.ss_address as sa
			on sa.id = t.f_address
		left join dbo.ed_devices as ed
			left join dbo.es_device_types as edt 
				on edt.id = ed.f_device_type 
			on ed.f_registr_pts = t.id
			and ed.d_close_date is null
		left join core.sd_divisions sd
			left join core.sd_divisions as sd2 
				on sd2.id = sd.f_division 
			on sd.id = erp.f_division
		left join core.sd_subdivisions as ss2 
			on ss2.id = erp.f_subdivision
		left join dbo.es_status_consume as esc
			on esc.id = coalesce(erp.f_status_consume, 2)
		left join dbo.ed_devices as de ON de.f_registr_pts = t.id and de.d_close_date is null
		left join history as hst
			on hst.f_registr_pts = t.id
		where case when _d_date_period is not null then hst.id is not null else 1=1 end
		and (case when _n_month_last_check_date is null then 1=1 else de.d_last_check_date < (now() - (_n_month_last_check_date::text || ' month')::interval) end);
END

Function: dbo.cf_arm_get_statistics_by_day(_f_div integer, _f_subdiv integer, _d_date_begin date, _d_date_end date)

Returns: SET OF record

Language: PLPGSQL

Общая статистика обходов по дням


begin 
	

	RETURN QUERY
		SELECT 
			r.d_date::date as d_date,
			sum(r.n_count_plan)::integer 	as n_count_plan,
			sum(r.n_count)::integer			as n_count
		from dbo.cf_arm_get_users_statistics_by_hour(_f_div,_f_subdiv, null, _d_date_begin, _d_date_end) as stat
			-- по ЭСУ
			inner join lateral json_to_recordset(stat.j_results) as r(d_date date, n_count_plan integer, n_count integer) on true
		group by r.d_date::date
		order by r.d_date::date
	
		
	;

end 

Function: dbo.cf_arm_get_statistics_by_month(_f_div integer, _f_subdiv integer, _d_date_begin date, _d_date_end date)

Returns: SET OF record

Language: PLPGSQL

Статистика количества обходов за месяц


begin 
	
	RETURN QUERY
	SELECT 
		r.d_date,
		avg(case when r.f_div = _f_div and r.f_subdiv = coalesce(_f_subdiv,r.f_subdiv) then r.n_count::real end)::integer as n_count_avg_div,
		avg(r.n_count::real)::integer as n_count_abg_all,
		max(case when r.f_div = _f_div and r.f_subdiv = coalesce(_f_subdiv,r.f_subdiv) then r.n_count::real end)::integer as n_count_max
	FROM 
	(
		SELECT 
			stat.f_div, 
			stat.f_subdiv,
			stat.f_user,
			r.d_date::date as d_date,
			sum(r.n_count) as n_count
		from dbo.cf_arm_get_users_statistics_by_hour(null,null, null, _d_date_begin, _d_date_end) as stat
			inner join lateral json_to_recordset(stat.j_results) as r(d_date date, n_count integer) on true
		group by stat.f_div,stat.f_subdiv,stat.f_user,r.d_date
		order by stat.f_div,stat.f_subdiv,stat.f_user,r.d_date
	) as r
	group by r.d_date
	order by r.d_date
	;

end 

Function: dbo.cf_arm_get_users_statistics_by_hour(_f_div integer, _f_subdiv integer, _fn_user integer, _d_date_begin date, _d_date_end date)

Returns: SET OF record

Language: PLPGSQL

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


begin 
	

	-- буфер для пользователей и часов
	create temp table t_userdivisions (
		f_div 			int4,
		f_subdiv		int4,
		f_user 			int4,
		c_user 			text,
		d_date 			date,
		n_hour			integer
	) on commit drop;

	insert into t_userdivisions(f_div, f_subdiv, f_user, c_user, d_date, n_hour)
	select
		max(sd.f_division)		as f_div,
		max(ssd.id)								as f_subdiv,
		pu.id,
		concat(pu.c_last_name || ' ', pu.c_first_name || ' ', pu.c_middle_name)::text as c_user,
 		dy.d_date::date,
 		date_part('hour', dy.d_date)::integer
	from  generate_series(_d_date_begin::date, _d_date_end::date  + INTERVAL '23 hours', '1 hours') as dy(d_date) 
		inner join core.pd_userindivisions as pud
			on 	true
		-- отделение
		inner join core.sd_divisions as sd
			on 	sd.id 				= pud.f_division
		-- участок
		left join core.sd_subdivisions as ssd
			on 	ssd.id 				= pud.f_subdivision
		inner join core.pd_users as pu 
			on 	pu.id 				= pud.f_user
			and (	pu.id 				= _fn_user
				or 	_fn_user 			is null)
	where 	1=1
		--and date_part('hour', dy.d_date) between 6 and 23
		and (	sd.id 			= _f_div
			or 	sd.f_division 	= _f_div
			or 	_f_div 			is null)
		and (	ssd.id 			= _f_subdiv
			or 	_f_subdiv 		is null)
	group by 
		pu.id,
		concat(pu.c_last_name || ' ', pu.c_first_name || ' ', pu.c_middle_name),
 		dy.d_date,
 		date_part('hour', dy.d_date);

	RETURN QUERY
	
	select 
		t.f_div,
		t.f_subdiv,
		t.f_user,
		t.c_user,
		sum(rres.n_count_plan)::integer as n_count_plan,
		array_to_json(array_agg(row_to_json(rres) order by t.d_date, t.n_hour))
		
	from t_userdivisions as t
		-- руз-ты
		left join (
			select  
				tt.f_user,
				tt.d_date as d_date, 
				tt.n_hour as n_hour, 
				coalesce(rr.n_count_plan,0) 	as n_count_plan,
				coalesce(rr.n_count, 0) 		as n_count,
				sum(coalesce(rr.n_count, 0)) over(partition by tt.f_user, tt.d_date) as n_count_all, -- всего за день
				max(coalesce(rr.n_count, 0)) over(partition by tt.d_date, tt.n_hour) as n_max, -- максимум по предприятию за час
				avg(coalesce(rr.n_count::real, 0)) over(partition by tt.d_date, tt.n_hour)::integer as n_avg, -- среднее по предприятию за час
				coalesce(rr.n_count_ABDP, 0) as n_count_ABDP

			from t_userdivisions as tt
				left join (	
					select 
						uir.f_user,
						coalesce(rr.d_date, cr.d_date)::date as d_date, 
						date_part('hour', coalesce(rr.d_date, cr.d_date)) as n_hour, 
						count(distinct cp.id) 		as n_count_plan,
						count(distinct rr.fn_point) as n_count,
						count(distinct case when b_ABDP then rr.fn_point end) as n_count_ABDP
					from core.cd_routes as cr
						inner join core.cd_userinroutes as uir
							on uir.f_route 	= cr.id
						inner join core.cd_points as cp
							on 	cp.f_route 	= cr.id
						left join (
							select rr.fn_point, rr.fn_user, case when crt.c_const = 'ABDP' then true else false end as b_ABDP, max(rr.d_date) as d_date
							from core.cd_results as rr
								left join core.cs_result_types as crt
									on 	crt.id 	= rr.fn_type
							group by rr.fn_point, rr.fn_user, case when crt.c_const = 'ABDP' then true else false end 
						) as rr
						 	on 	rr.fn_point = cp.id
						 	and rr.fn_user 	= uir.f_user
					group by uir.f_user, coalesce(rr.d_date, cr.d_date)::date, date_part('hour', coalesce(rr.d_date, cr.d_date))
				) as rr
					on 	1=1
					and rr.f_user 	= tt.f_user
					and rr.d_date 	= tt.d_date
					and rr.n_hour 	= tt.n_hour
			where 	1=1
				
			order by tt.f_user, tt.d_date, tt.n_hour, rr.n_count_plan
		) as rres
			on 	1=1
			and rres.f_user 	= t.f_user
			and rres.d_date 	= t.d_date
			and rres.n_hour 	= t.n_hour
	group by t.f_div,t.f_subdiv,t.c_user,t.f_user
	order by sum(rres.n_count) desc, t.f_div,t.f_subdiv,t.c_user,t.f_user

		
	;

end 

Function: dbo.cf_arm_pd_user_managers(_f_current_user integer, _f_main_division integer, _f_division integer, _f_subdivision integer)

Returns: SET OF record

Language: PLPGSQL

Получение диспетчеров по заданному фильтру

/**
* @params {integer} _f_current_user - иден. текущего пользователя
* @params {integer} _f_main_division - иден. филиал
* @params {integer} _f_division - иден. отделение
* @params {integer} _f_subdivision - иден. участок
*
* @example
* [{ "action": "cf_arm_pd_user_managers", "method": "Select", "data": [{ "params": [_f_current_user, _f_main_division, _f_division, _f_subdivision] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_f_role integer;
BEGIN
	select r.id into _f_role from core.pd_roles as r
	where r.c_name = 'manager';

	IF _f_current_user is not null AND _f_main_division is not null THEN
		CASE WHEN _f_division is null AND _f_subdivision is null THEN
			-- пользователь и Филиал выбраны
			RETURN QUERY 
			select u.id, u.c_login, u.c_first_name, u.c_last_name, u.c_middle_name 
			from core.pd_userindivisions as uid 
			inner join core.pd_users as u ON uid.f_user = u.id
			inner join core.pd_userinroles as uir ON uir.f_user = u.id
			inner join dbo.cf_arm_sd_main_divisions(_f_current_user) as smd ON smd.id = uid.f_division
			where uir.f_role = _f_role and smd.id = _f_main_division;		
		WHEN _f_division is not null AND _f_subdivision is null THEN
			-- пользователь, Филиал и Отделение выбраны
			RETURN QUERY 
			select u.id, u.c_login, u.c_first_name, u.c_last_name, u.c_middle_name 
			from core.pd_userindivisions as uid 
			inner join core.pd_users as u ON uid.f_user = u.id
			inner join core.pd_userinroles as uir ON uir.f_user = u.id
			inner join dbo.cf_arm_sd_divisions(_f_current_user, _f_main_division) as smd ON smd.id = uid.f_division
			where uir.f_role = _f_role and smd.id = _f_division;
		WHEN _f_division is not null AND _f_subdivision is not null THEN
			-- пользователь, Филиал, Отделение и Участок выбраны
			RETURN QUERY 
			select u.id, u.c_login, u.c_first_name, u.c_last_name, u.c_middle_name
			from dbo.cf_arm_sd_subdivisions(_f_current_user, _f_division) as smd
			inner join core.pd_userindivisions as uid ON smd.f_division = uid.f_division OR smd.id = uid.f_subdivision
			inner join core.pd_users as u ON uid.f_user = u.id
			inner join core.pd_userinroles as uir ON uir.f_user = u.id
			where uir.f_role = _f_role and smd.id = _f_subdivision;
		END CASE;
	END IF;
END

Function: dbo.cf_arm_pd_user_stat(_fn_user integer, _d_date date)

Returns: SET OF record

Language: PLPGSQL

Получение статистик по обходчику

/**
* @params {integer} _fn_user - иден. обходчика
* @params {date} _d_date - дата
*
* @example
* [{ "action": "cf_arm_pd_user_stat", "method": "Select", "data": [{ "params": [_fn_user, _d_date] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_status_weight integer;
	_result_types_oov integer;
BEGIN
	select rs.n_order into _status_weight 
	from core.cs_route_statuses as rs
	where rs.c_const = 'ASSINGNED'; -- не ниже этого статуса

	--тип документа "отказ от выполнения"
	select rt.id into _result_types_oov
	from core.cs_result_types as rt 
	where rt.c_const = 'OOV';

	RETURN QUERY 
	with points as (	-- все задания для контролера
		select (CASE WHEN s.b_person THEN 1 ELSE 0 END) as b_person
		from core.cd_routes as r
		inner join core.cd_userinroutes as uir ON r.id = uir.f_route
		INNER join core.cs_route_statuses as rs ON rs.id = r.f_status
		INNER JOIN core.cd_points as p ON p.f_route = r.id
		left join dbo.ed_registr_pts as rp ON rp.id = p.f_registr_pts
		left join dbo.sd_subscr as s ON s.id = rp.f_subscr
		where uir.f_user = _fn_user
		and _d_date::date >= r.d_date_start 
		and _d_date::date <= CASE WHEN r.b_extended THEN r.d_extended ELSE r.d_date_end END 
		and rs.n_order >= _status_weight
	), userpoints as ( -- выполненные контролером задания
		select 
			max(CASE WHEN s.b_person THEN 1 ELSE 0 END) as b_person,
			CASE WHEN max(cr.fn_type) = _result_types_oov and count(distinct cr.fn_type) = 1 then 1 else 0 end as b_refuse, 
			max(up.d_date) as d_date
		from core.cd_userinroutes as uir
		INNER JOIN core.cd_routes as rt ON rt.id = uir.f_route
		INNER join core.cs_route_statuses as rs ON rs.id = rt.f_status
		INNER JOIN core.cd_points as p ON p.f_route = uir.f_route
		left join dbo.ed_registr_pts as rp ON rp.id = p.f_registr_pts
		left join dbo.sd_subscr as s ON s.id = rp.f_subscr
		inner JOIN core.cd_user_points as up ON up.fn_point = p.id
		left join core.cd_results as cr on cr.fn_user_point = up.id
		where uir.f_user = _fn_user 
		and _d_date::date >= rt.d_date_start 
		and _d_date::date <= CASE WHEN rt.b_extended THEN rt.d_extended ELSE rt.d_date_end END 
		and rs.n_order >= _status_weight
		group by p.id
	) select
		u.id,
		u.c_login,
		u.c_first_name,
		u.c_last_name,
		u.c_middle_name,
		u.c_email,
		u.c_phone,
		u.fn_file,
		(select a.d_date from core.ad_tracking as a where a.fn_user = u.id order by a.d_date desc limit 1) as d_tracking_date, -- время последнего получения геокординаты
		(select count(*) from userpoints where b_person = 1 and d_date::date = _d_date) as n_today_done_person,  -- Выполнено сегодня ФЛ
		(select count(*) from userpoints where b_person = 1) as n_all_done_person,  -- Выполнено ФЛ
		(select count(*) from userpoints where b_person = 1 and b_refuse = 1) as n_refuse_person,  -- Отказ от выполнения ФЛ
		((select count(*) from points where b_person = 1) - (select count(*) from userpoints where b_person = 1)) as n_lost_person,  -- Осталось ФЛ
		(select count(*) from points where b_person = 1) as n_all_person, -- Общее кол-во ФЛ 
		(select count(*) from userpoints where b_person = 0 and d_date::date = _d_date) as n_today_done, -- Выполнено сегодня ЮЛ
		(select count(*) from userpoints where b_person = 0) as n_all_done, -- Выполнено ЮЛ
		(select count(*) from userpoints where b_person = 0 and b_refuse = 1)  as n_refuse, -- Отказ от выполнения ЮЛ
		((select count(*) from points where b_person = 0) - (select count(*) from userpoints where b_person = 0)) as n_lost, -- Осталось ЮЛ
		(select count(*) from points where b_person = 0) as n_all -- Общее кол-во ЮЛ 
	from core.pd_users as u
	where u.id = _fn_user;
END

Function: dbo.cf_arm_pd_users(_f_main_division integer, _f_division integer, _f_subdivision integer, _f_manager integer, _f_user integer)

Returns: SET OF record

Language: PLPGSQL

Получение обходчиков по заданному фильтру

/**
* @params {integer} _f_main_division - иден. филиал. Обязателен при передаче
* @params {integer} _f_division - иден. отделение. Может быть null
* @params {integer} _f_subdivision - иден. участок. Может быть null
* @params {integer} _f_manager - иден. диспетчер. Может быть null
* @params {integer} _f_user - иден. обходчика. Может быть null
*
* @example
* [{ "action": "cf_arm_pd_users", "method": "Select", "data": [{ "params": [_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_users json; -- обходчики
BEGIN
	RETURN QUERY select 
		u.id, 
		max(u.c_login), 
		max(u.c_first_name), 
		max(u.c_last_name), 
		max(u.c_middle_name), 
		max(u.fn_file),
		concat('.', string_agg(distinct r.c_name, '.'), '.')
	from core.pd_userindivisions as uid
	inner join core.pd_users as u ON uid.f_user = u.id
	inner join core.pd_userinroles as uir ON uir.f_user = uid.f_user
	inner join core.pd_roles as r ON r.id = uir.f_role
	left join core.sd_divisions as dd on dd.id = uid.f_division
	where --r.c_name = 'inspector' and
	(case when _f_main_division is null then 1=1 else _f_main_division = dd.f_division end) and
	(case when _f_division is null then 1=1 else _f_division = dd.id end) and
	(case when _f_subdivision is null then 1=1 else _f_subdivision = uid.f_subdivision end) and
	(case when _f_manager is null then 1=1 else _f_manager = u.f_parent end) and
	(case when _f_user is null then 1=1 else _f_user = u.id end)
	group by u.id;

END

Function: dbo.cf_arm_pd_users_stat(_f_main_division integer, _f_division integer, _f_subdivision integer, _f_manager integer, _f_user integer, _d_date date)

Returns: SET OF record

Language: PLPGSQL

Получение статистика для обходчиков по заданному фильтру

/**
* @params {integer} _f_main_division - иден. филиал. Обязателен при передаче
* @params {integer} _f_division - иден. отделение. Обязателен при передаче
* @params {integer} _f_subdivision - иден. участок. Обязателен при передаче
* @params {integer} _f_manager - иден. диспетчер. Может быть null
* @params {integer} _f_user - иден. обходчика. Может быть null
*
* @example
* [{ "action": "cf_arm_pd_users_stat", "method": "Select", "data": [{ "params": [_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user] }], "type": "rpc", "tid": 0}]
*/

BEGIN
	RETURN QUERY select 
		u.id, -- общая информация о пользователе
		u.c_login,
		u.c_first_name,
		u.c_last_name,
		u.c_middle_name,
		u.fn_file,
		(select count(*) from dbo.cf_arm_cd_routes(u.id, now()::date)) as n_route_active, -- кол-во активных маршрутов
		(select a.d_date from core.ad_tracking as a where a.fn_user = u.id order by a.d_date desc limit 1) as d_tracking_date, -- время последнего получения геокординаты
		coalesce(s.n_today_done_person, 0) + coalesce(s.n_today_done, 0) as n_today_done, 	-- выполнено сегодня
		coalesce(s.n_all_done_person, 0) + coalesce(s.n_all_done, 0) as n_all_done,   		-- выполнено всего
		coalesce(s.n_refuse_person, 0) + coalesce(s.n_refuse, 0) as n_refuse, 				-- отказ от выполнения
		coalesce(s.n_lost_person, 0) + coalesce(s.n_lost, 0) as n_lost,						-- осталось
		coalesce(s.n_all_person, 0) + coalesce(s.n_all, 0) as n_all 						-- Общее количество
	from dbo.cf_arm_pd_users(_f_main_division, _f_division, _f_subdivision, _f_manager, _f_user) as u
		left join lateral dbo.cf_arm_pd_user_stat(u.id, _d_date::date) s on true
	where u.c_claims ilike '%.inspector.%';
END

Function: dbo.cf_arm_remove_route(_route_id uuid)

Returns: integer

Language: PLPGSQL

Удаление маршрута со статусом "Сформирован"

/**
* @params {uuid} _route_id - идентификатор маршрута
*
* @returns {integer}
* 0 - ОК
* 1 - статус документ отличается от "сформирован" и "формируется"
*
* @example
* [{ "action": "cf_arm_remove_route", "method": "Query", "data": [{ "params": [_route_id] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_c_status text;
BEGIN
	select rs.c_const into _c_status from core.cd_routes as r
	inner join core.cs_route_statuses as rs ON rs.id = r.f_status
	where r.id = _route_id;
	
	-- лучше статус не менять иначе при синхронизации может быть потеря данных
	IF _c_status = 'CREATE' OR _c_status = 'CREATED' THEN
		RETURN core.sf_del_route(_route_id);
	ELSE
		RETURN 1; -- статус документ отличается от "сформирован" и "формируется"
	END IF;
END

Function: dbo.cf_arm_remove_routes(_routes json)

Returns: SET OF record

Language: PLPGSQL

Массовое удаление маршрутов со статусом "Сформирован" или "Формируется"

/**
* @params {json} _routes - массив маршрутов, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
*
* @returns возвращается таблица с двумя колонками id:uuid и n_status: integer, дополнительно о статусах можно узнать в функции dbo.cf_arm_remove_route
*
* @example
* [{ "action": "cf_arm_remove_routes", "method": "Query", "data": [{ "params": [_f_current_user, routes] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	RETURN QUERY select 
		t.value::uuid as id, 
		dbo.cf_arm_remove_route(t.value::uuid) as n_status 
	from json_array_elements_text(_routes) as t;
END

Function: dbo.cf_arm_route_details(_f_route uuid)

Returns: SET OF record

Language: PLPGSQL

DECLARE
	_d_date_period date;
BEGIN	
	-- период вычисляется на основе даты завершения маршрута
	select date_trunc('MONTH',(case when r.b_extended then r.d_extended else r.d_date_end end))::date into _d_date_period from core.cd_routes as r
	where r.id = _f_route;

	create temp table t_keys (
		id uuid,
		f_registr_pts uuid,
 		f_point_type int,
 		c_point_name text
	) on commit drop;

	insert into t_keys(
		id,
		f_registr_pts,
 		f_point_type,
 		c_point_name
	)
	select 
		cp.id,
		rp.id as f_registr_pts,
		cp.f_type as f_point_type,
		cpt.c_name as c_point_name
	from core.cd_points as cp 
		inner join dbo.ed_registr_pts as rp
			on rp.id = cp.f_registr_pts
		left join core.cs_point_types as cpt 
			on cpt.id = cp.f_type 
	where cp.f_route = _f_route; --'a499211a-2714-4552-a45c-45ac8959c7a1'

	RETURN QUERY
	with history as (
		select distinct
			rpth.id,
			t.id as f_point,
			rpth.f_point_type,
			rpth.f_registr_pts, 
			rpth.b_plan, 
			rpth.f_no_plan_work,
			npw.c_name as c_no_plan_work,
			row_number() over(partition by rpth.f_registr_pts, rpth.f_point_type, rpth.b_plan, rpth.f_no_plan_work order by rpth.d_date_period desc, rpth.id) as n_row
		from t_keys as t
		inner join dbo.ed_registr_pts_history as rpth ON t.f_registr_pts = rpth.f_registr_pts and rpth.f_point_type = t.f_point_type
		left join dbo.es_no_plan_works as npw ON npw.id = rpth.f_no_plan_work
		where case when _d_date_period is not null then rpth.d_date_period = _d_date_period else rpth.d_date_period is null end
	)
	select 
		t.id,
		t.f_registr_pts,
		t.f_point_type,
		t.c_point_name,
		sd2.c_name as c_filial,
		sd.c_name as c_pes,
		ss2.c_name as c_res,
		
		case when ss.b_person then ss.c_name1 || ' ' || ss.c_name2 || ' ' || ss.c_name3 else ss.c_name1 end as c_subscr_name,
		ss.c_code as c_subscr_code,
		
		erp.c_registr_pts,
		erp.c_status_registr_pts,
		erp.d_close_date as d_tu_close_date,
		ss.n_check_date,
		ss.b_problem_person,
		erp.f_status_consume::text, -- привести справочник
		esc.c_name as c_status_consume,
		erp.b_technical_metering,
		erp.c_status,
		erp.c_predictr,
		
		ed.c_serial_number,
		edt.c_name as c_device_type,
		coalesce(ed.b_askue, false) as b_askue,
		edt.b_phase3,
		ed.d_setup_date,
		ed.d_close_date as d_pu_close_date,
		ed.d_valid_date,

		erp.c_substation ,
		erp.c_line_substation ,
		erp.c_rp,
		erp.c_line_rp,
		erp.c_tp,
		erp.c_line_tp,
		sa.c_raion,
		sa.c_city_name,
		sa.c_settlement_name,
		sa.c_street_name,
		sa.c_house_name,
		sa.c_block_name,
		sa.c_flat_name,
		sa.n_geo_lat,
		sa.n_geo_lon,
		sa.c_comment_address,
		_d_date_period as d_date_period,
		hst.b_plan as b_plan,
		hst.f_no_plan_work as f_no_plan_work,
		hst.c_no_plan_work as c_no_plan_work
	from t_keys as t
		inner join dbo.ed_registr_pts as erp
			on erp.id = t.f_registr_pts
		inner join dbo.sd_subscr as ss
			on ss.id = erp.f_subscr 
		left join dbo.ss_address as sa
			on sa.id = erp.f_address
		inner join dbo.ed_devices as ed
			left join dbo.es_device_types as edt 
				on edt.id = ed.f_device_type 
			on ed.f_registr_pts = t.f_registr_pts
			and ed.d_close_date is null
		left join core.sd_divisions sd
			left join core.sd_divisions as sd2 
				on sd2.id = sd.f_division 
			on sd.id = erp.f_division
		left join core.sd_subdivisions as ss2 
			on ss2.id = erp.f_subdivision
		left join dbo.es_status_consume as esc
			on esc.id = coalesce(erp.f_status_consume, 2)
		left join history as hst
			on 	hst.f_point 		= t.id
			and hst.f_point_type 	= t.f_point_type
			and hst.n_row 			= 1
			;

END

Function: dbo.cf_arm_sd_divisions(_f_current_user integer, _f_main_division integer)

Returns: SET OF record

Language: PLPGSQL

Список отделений доступных для пользователя

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {integer} _f_main_division - филиал
*
* @example
* [{ "action": "cf_arm_sd_divisions", "method": "Select", "data": [{ "params": [_f_current_user, _f_main_division] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	-- список разрешеннных отделений см. core.pd_userindivisions -> f_division
	RETURN QUERY WITH RECURSIVE tree AS (
		SELECT
			d.id,
			d.f_division,
			d.c_name,
			d.c_dep_code,
			d.n_code,
			d.b_disabled
		FROM core.sd_divisions as d
		where d.id IN (select ud.f_division
						from core.pd_userindivisions as ud
						where ud.f_user = _f_current_user)

		UNION

		SELECT
			d.id,
			d.f_division,
			d.c_name,
			d.c_dep_code,
			d.n_code,
			d.b_disabled
		FROM core.sd_divisions as d
		JOIN tree ON d.id = tree.f_division)
	select t.id, t.f_division, t.c_name, t.c_dep_code, t.n_code from tree as t
	where t.b_disabled = false and t.f_division = _f_main_division;
END

Function: dbo.cf_arm_sd_main_divisions(_f_current_user integer)

Returns: SET OF record

Language: PLPGSQL

Список филиалов доступных для пользователя

/**
* @params {integer} _f_current_user - текущий пользователь
*
* @example
* [{ "action": "cf_arm_sd_main_divisions", "method": "Select", "data": [{ "params": [_f_current_user] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	-- список разрешеннных отделений см. core.pd_userindivisions -> f_division
	RETURN QUERY WITH RECURSIVE tree AS (
		SELECT
			d.id,
			d.f_division,
			d.c_name,
			d.c_dep_code,
			d.n_code,
			d.b_disabled
		FROM core.sd_divisions as d
		where d.id IN (select ud.f_division
						from core.pd_userindivisions as ud
						where ud.f_user = _f_current_user)

		UNION

		SELECT
			d.id,
			d.f_division,
			d.c_name,
			d.c_dep_code,
			d.n_code,
			d.b_disabled
		FROM core.sd_divisions as d
		JOIN tree ON d.id = tree.f_division)
	select t.id, t.c_name, t.c_dep_code, t.n_code from tree as t
	where t.b_disabled = false and t.f_division is null;
END

Function: dbo.cf_arm_sd_subdivisions(_f_current_user integer, _f_division integer)

Returns: SET OF record

Language: PLPGSQL

Список участков доступных для пользователя

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {integer} _f_division - отделение
*
* @example
* [{ "action": "cf_arm_sd_subdivisions", "method": "Select", "data": [{ "params": [_f_current_user, _f_division] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	-- список разрешеннных отделений см. core.pd_userindivisions -> f_subdivision
	RETURN QUERY 
	-- поиск subdivisions
	select sd.id, sd.f_division, sd.c_name, sd.n_code, true as b_subdivision -- b_subdivision прямой доступ к участку
	from core.pd_userindivisions as ud
	inner join core.sd_subdivisions as sd ON ud.f_subdivision = sd.id
	where ud.f_user = _f_current_user and ud.f_subdivision is not null and b_disabled = false
	UNION
	-- поиск через divisions
	select sd.id, sd.f_division, sd.c_name, sd.n_code, false as b_subdivision 
	from core.sd_subdivisions as sd
	where sd.b_disabled = false and sd.f_division IN (WITH RECURSIVE tree AS (
		SELECT
			d.id,
			d.f_division
		FROM core.sd_divisions as d
		where d.id IN (select ud.f_division
						from core.pd_userindivisions as ud
						where ud.f_user = _f_current_user and ud.f_division is not null and ud.f_subdivision is null)

		UNION

		SELECT
			d.id,
			d.f_division
		FROM core.sd_divisions as d
		JOIN tree ON d.id = tree.f_division)
	select t.id from tree as t);
END

Function: dbo.cf_arm_transfer_route(_f_current_user integer, _route_id uuid)

Returns: integer

Language: PLPGSQL

Передача маршрута на исполнение

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {uuid} _route_id - идентификатор маршрута
*
* @returns {integer}
* 0 - ОК
* 1 - маршрут не найден
* 2 - пользователь не найден
* 3 - статус документ отличается от "назначен"
*
* @example
* [{ "action": "cf_arm_transfer_route", "method": "Query", "data": [{ "params": [_f_current_user, _route_id] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_c_status text; -- текущий статус маршрута
	_f_next_status_id integer; -- статус - передан
BEGIN

	IF(select count(*) from core.cd_routes as r where r.id = _route_id) = 1 THEN
	
		IF(select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN
		
			-- текущий статус
			select rs.c_const into _c_status from core.cd_routes as r
			left join core.cs_route_statuses as rs ON rs.id = r.f_status
			where r.id = _route_id;
			
			-- Передаем только после назначен
			IF _c_status = 'ASSINGNED' THEN
			
				-- новый статус
				select rs.id into _f_next_status_id 
				from core.cs_route_statuses as rs
				where rs.c_const = 'TRANSFERRED';
			
				-- создаем новый статус "передан"
				insert into core.cd_route_history (fn_route, fn_status, fn_user, d_date)
				values (_route_id, _f_next_status_id, _f_current_user, now());
				
				RETURN 0;
				
			ELSE
				RETURN 3; -- статус документ отличается от "назначен"
			END IF;
			
		ELSE
			RETURN 2; -- нет пользователя
		END IF;	
		
	ELSE
		RETURN 1; -- нет маршрута
	END IF;
END

Function: dbo.cf_arm_transfer_routes(_f_current_user integer, _routes json)

Returns: SET OF record

Language: PLPGSQL

Передача нескольких маршрутов на исполнение

/**
* @params {integer} _f_current_user - текущий пользователь
* @params {json} _routes - массив маршрутов, требуется передать в виде строки '["e7ded0cd-12dd-47f5-a75b-192376291e83"]'
*
* @returns
* возвращается таблица с двумя колонками route_id:uuid и status_id: integer, где статус может содержать значение 0 - ОК, 1 - пользователь не найден.
* дополнительные статусы можно узнать в функции dbo.cf_arm_transfer_route 
*
* @example
* [{ "action": "cf_arm_transfer_routes", "method": "Query", "data": [{ "params": [_f_current_user, routes] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.pd_users as u where u.id = _f_current_user) = 1 THEN
		RETURN QUERY 
		select t.value::uuid, dbo.cf_arm_transfer_route(_f_current_user, t.value::uuid)
		from json_array_elements_text(_routes) as t;
	ELSE
		RETURN QUERY select null, 1;
	END IF;
END

Function: dbo.cf_arm_update_route(_f_route uuid, _registr_pts json, _b_delete boolean)

Returns: integer

Language: PLPGSQL

Обновление точек маршрута на основе точек учета

/**
* @params {uuid} _f_route - маршрут
* @params {json} _registr_pts - идент-ры точек учета, передавать в виде строку иден-ров, например '[{"id": "40170afe-498d-4ff0-a1e7-9f29d470cf0a", "f_type": 1}, {"id": "16dc8d78-04db-45ac-ab02-2112000478c2", "f_type": 2}]'
* @params {boolean} _b_delete - нужно ли удалить указанные точки учета. true - да
*
* @returns
* 0 - OK
* 1 - нет маршрута
* 2 - точки учета не переданы
*
* @example
* [{ "action": "cf_arm_update_route", "method": "Query", "data": [{ "params": [_f_route, _registr_pts, _b_delete] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.cd_routes as r where r.id = _f_route) = 1 THEN
		IF (select count(*) from json_array_elements(_registr_pts)) > 0 THEN

			IF _b_delete THEN 
				delete from core.cd_points as p 
				where p.f_route = _f_route and p.f_registr_pts in (select (t.value #>> '{id}')::uuid from json_array_elements(_registr_pts) as t);
				
				RETURN 0;
			ELSE
				insert into core.cd_points (f_registr_pts, f_route, f_type, c_notice, c_info, jb_data, n_order, sn_delete)
				select (t.value #>> '{id}')::uuid, _f_route, (t.value #>> '{f_type}')::integer, null, dbo.sf_generate_point_info(rp.id), dbo.sf_generate_point_jb_data(rp.id), 1, false
				from json_array_elements(_registr_pts) as t
				inner join dbo.ed_registr_pts as rp ON rp.id = (t.value #>> '{id}')::uuid
				left join dbo.ss_address as ad ON ad.id = rp.f_address
				order by ad.c_name;

				RETURN 0;
			END IF;
		ELSE
			RETURN 2; -- точки не переданы
		END IF;
	ELSE
		RETURN 1; -- нет маршрута
	END IF;
END

Function: dbo.cf_arm_update_route(_f_route uuid, _registr_pts_history json)

Returns: integer

Language: PLPGSQL

Обновление точек маршрута для раздела планирования

/**
* @params {uuid} _f_route - маршрут
* @params {json} _registr_pts_history - идент-ры точек, передавать в виде строку иден-ров, например '[{"f_registr_pts_history": "40170afe-498d-4ff0-a1e7-9f29d470cf0a", "f_type": 1}, {"f_registr_pts_history": "16dc8d78-04db-45ac-ab02-2112000478c2", "f_type": 2}]'
*
* @returns
* 0 - OK
* 1 - нет маршрута
* 2 - точки учета не переданы
*
* @example
* [{ "action": "cf_arm_update_route", "method": "Query", "data": [{ "params": [_f_route, _registr_pts_history] }], "type": "rpc", "tid": 0}]
*/
BEGIN
	IF (select count(*) from core.cd_routes as r where r.id = _f_route) = 1 THEN
		IF (select count(*) from json_array_elements(_registr_pts_history)) > 0 THEN

			insert into core.cd_points (f_registr_pts, f_route, f_type, c_notice, c_info, jb_data, n_order, sn_delete)
			select rph.f_registr_pts, _f_route, (t.value #>> '{f_type}')::integer, null, dbo.sf_generate_point_info(rp.id), dbo.sf_generate_point_jb_data(rp.id), 1, false
			from json_array_elements(_registr_pts_history) as t
			inner join dbo.ed_registr_pts_history as rph ON rph.id = (t.value #>> '{f_registr_pts_history}')::uuid
			inner join dbo.ed_registr_pts as rp ON rp.id = rph.f_registr_pts
			left join dbo.ss_address as ad ON ad.id = rp.f_address
			order by ad.c_name;

			-- 476674: далее нужно проставить b_plan 

			update dbo.ed_registr_pts_history as rph
			set b_plan = true
			where rph.id in (select (t.value #>> '{f_registr_pts_history}')::uuid from json_array_elements(_registr_pts_history) as t);

			RETURN 0;
		ELSE
			RETURN 2; -- точки не переданы
		END IF;
	ELSE
		RETURN 1; -- нет маршрута
	END IF;
END

Function: dbo.cf_mim_create_user(_c_last_name text, _c_first_name text, _f_maindivision integer, _f_division integer, _f_subdivision integer, _c_login text, _c_tab_number text, _c_password text, _c_middle_name text, _c_post_code text, _c_post text, _c_phone text, _c_email text)

Returns: integer

Language: PLPGSQL

Создание пользователя с ролями

BEGIN	

	-- не переданы обязательные атрибуты
	if 		_c_last_name 					is null
		or _c_first_name 					is null 
		or _f_maindivision 					is null 
		or _f_division 						is null 
		or _f_subdivision 					is null 
		or nullif(trim(_c_login), '') 		is null 
		or nullif(trim(_c_tab_number), '') 	is null 
		or nullif(trim(_c_password), '') 	is null
	then 
		return 1;
	end if;

	-- пользователь с таким табельным номером уже существует
	if exists(select 1 from core.pd_users where c_tab_number = _c_tab_number)
	then 
		return 2;
	end if;

	-- пользователь с таким логином уже существует
	if exists(select 1 from core.pd_users where c_login = _c_login)
	then 
		return 3;
	end if;

	-- удостовериться что переданные рэс есть в справочнике
	select id into _f_maindivision 	from core.sd_divisions 		where id = _f_maindivision 	and f_division is null;
	select id into _f_division 		from core.sd_divisions 		where id = _f_division 		and f_division = _f_maindivision;
	select id into _f_subdivision 	from core.sd_subdivisions 	where id = _f_subdivision 	and f_division = _f_division;

	with ins_users as (
		-- создание пользователя
		insert into core.pd_users (c_last_name, c_first_name, c_middle_name, c_login, c_tab_number, c_post_code, c_post, c_phone, c_email, s_hash, b_pgcrypto)
		select _c_last_name, _c_first_name, _c_middle_name, _c_login, _c_tab_number, _c_post_code, _c_post, _c_phone, _c_email, crypt(_c_password, gen_salt('bf', 8)), true
		returning id
	)
		-- привязка к участку
		insert into core.pd_userindivisions (f_user, f_division, f_subdivision)
		select pu.id as f_user, _f_division, _f_subdivision
		from ins_users as pu
		where 	_f_division is not null 
			and _f_subdivision is not null
		union 
		-- привязка к отделению
		select pu.id as f_user, _f_division, null
		from ins_users as pu
		where 	_f_division is not null 
		union 
		-- привязка к филиалу
		select pu.id as f_user, _f_maindivision, null
		from ins_users as pu
		where 	_f_maindivision is not null ;


	RETURN 0;

END

Function: dbo.cf_mim_get_user_info(_c_tab_number text)

Returns: SET OF record

Language: PLPGSQL

Получение карточки пользователя (детальная информация о пользователе)

BEGIN	

	RETURN QUERY 
	select 
		pd.id, 
		pd.c_last_name, 
		pd.c_first_name,
		pd.c_middle_name, 
		pd.c_login, 
		pd.c_tab_number,
		pd.c_post_code,
		pd.c_post,
		(
			select string_agg(distinct coalesce(sdd.c_name, sd.c_name), ',')
			from core.pd_userindivisions as pud 
				inner join core.sd_divisions as sd 
					on 	sd.id 		= pud.f_division
				left join core.sd_divisions as sdd
					on 	sdd.id 		= sd.f_division
			where pud.f_user = pd.id
		) as c_maindivision,
		(
			select string_agg(distinct sd.c_name, ',')
			from core.pd_userindivisions as pud 
				inner join core.sd_divisions as sd 
					on 	sd.id 		= pud.f_division
			where pud.f_user = pd.id
				and sd.f_division is null
		) as c_division,
		(
			select string_agg(distinct ss.c_name, ',')
			from core.pd_userindivisions as pud 
				inner join core.sd_subdivisions as ss 
					on 	ss.id 		= pud.f_subdivision
			where pud.f_user = pd.id
		) as c_subdivision,
		pd.c_phone,
		( 	SELECT string_agg(t_1.c_description, ',') AS string_agg
           	FROM ( 	SELECT r.c_description
                    FROM core.pd_userinroles uir
                        JOIN core.pd_roles r ON uir.f_role = r.id
                    WHERE uir.f_user = pd.id
                    ORDER BY r.n_weight DESC
                 ) t_1
        ) as c_claims,
        pd.c_email,
        case when pd.b_disabled then 'Отключен' else 'Действующий' end as c_status,
        null::date as d_date_work,
        null::date as d_date_dismiss		
	from core.pd_users as pd
	where 	1=1
		and pd.c_tab_number = _c_tab_number
	;

END

Function: dbo.cf_mim_get_user_roles_list()

Returns: SET OF record

Language: PLPGSQL

Получение списка ролей

BEGIN	

	RETURN QUERY 
	select pd.id, pd.c_name, pd.c_description
	from core.pd_roles as pd
	where 	1=1
		and not sn_delete;

END

Function: dbo.cf_mim_get_users_list(_f_maindivision integer, _b_disabled boolean, _c_post_code text, _f_role integer)

Returns: SET OF record

Language: PLPGSQL

Получение списка пользователей

BEGIN	

	RETURN QUERY 
	select 
		pd.id, 
		pd.c_last_name, 
		pd.c_first_name, 
		pd.c_login, 
		pd.c_tab_number,
		pd.c_post_code,
		(
			select string_agg(distinct coalesce(sdd.c_name, sd.c_name), ',') as string_agg
			from core.pd_userindivisions as pud 
				inner join core.sd_divisions as sd 
					on 	sd.id 		= pud.f_division
				left join core.sd_divisions as sdd
					on 	sdd.id 		= sd.f_division
			where pud.f_user = pd.id
		) as c_maindivision,
		( 	SELECT string_agg(t_1.c_name, ',') AS string_agg
           	FROM ( 	SELECT r.c_name
                    FROM core.pd_userinroles uir
                        JOIN core.pd_roles r ON uir.f_role = r.id
                    WHERE uir.f_user = pd.id
                    ORDER BY r.n_weight DESC
                 ) t_1
        ) AS c_claims		
	from core.pd_users as pd
	where 	1=1
		and not pd.sn_delete 											-- не удаленные
		and case 
				when _f_maindivision is null then true
				else _f_maindivision in (select pud.f_division from core.pd_userindivisions as pud  where pud.f_user = pd.id)
			end 														-- фильтр по филиалу
		and pd.b_disabled 	= coalesce(_b_disabled, pd.b_disabled)		-- фильтр по статусу 
		and case 
				when _c_post_code is null then true
				else pd.c_post_code  = _c_post_code
			end 														-- фильтр по коду должности
	order by pd.id
	;

END

Function: dbo.cf_mim_update_user(_c_tab_number text, _c_last_name text, _c_first_name text, _c_middle_name text, _c_login text, _c_post_code text, _c_post text, _f_maindivision integer, _f_division integer, _f_subdivision integer, _c_phone text, _c_email text)

Returns: integer

Language: PLPGSQL

Изменение профиля пользователя

DECLARE 	
	_f_user int4; -- идентификатор пользователя
BEGIN	
	
	-- не передан табельный номер
	if 		nullif(trim(_c_tab_number), '') 	is null 
	then 
		return 1;
	end if; 
		
	-- идентификатор пользователя по табельному номеру
	select id into _f_user from core.pd_users where c_tab_number = _c_tab_number;

	-- пользователя с таким табельным номером не существует
	if _f_user is null
	then 
		return 2;
	end if;

	-- модификация атрибутов
	update core.pd_users
	set 
		_c_last_name	= _c_last_name,
		_c_first_name 	= _c_first_name,
		_c_middle_name 	= _c_middle_name,
		_c_login 		= _c_login,
		_c_post_code 	= _c_post_code,
		_c_post 		= _c_post,
		_c_phone 		= _c_phone,
		_c_email 		= _c_email
	where id = _f_user;

	-- изменение подразделения пользователя (подумать)
/*
	select id into _f_maindivision 	from core.sd_divisions 		where id = _f_maindivision 	and f_division is null;
	select id into _f_division 		from core.sd_divisions 		where id = _f_division 		and f_division = _f_maindivision;
	select id into _f_subdivision 	from core.sd_subdivisions 	where id = _f_subdivision 	and f_division = _f_division;

	if 		_f_maindivision is not null
		and _f_division 	is not null
		and _f_subdivision 	is not null

	then 



		insert into core.pd_userindivisions(f_user, f_division, f_subdivision)
		select _f_division, _f_subdivision



	end if;
*/
	RETURN 0;

END

Function: dbo.cf_mim_update_user_roles(_c_tab_number text, _f_role integer)

Returns: integer

Language: PLPGSQL

Назначение пользователю роли

DECLARE
	_f_user int4;
BEGIN	

	if 		nullif(trim(_c_tab_number), '') 	is null 
		or 	_f_role							 	is null 
	then 
		return 1;
	end if; 

	select id into _f_user from core.pd_users where c_tab_number = _c_tab_number;

	-- пользователя с таким табельным номером не существует
	if _f_user is null
	then 
		return 2;
	end if;

	-- переданной роли нет в справочнике ролей
	if not exists(select 1 from core.pd_roles where id = _f_role)
	then 
		return 3;
	end if;

	-- у пользователя уже есть такая роль
	if exists (	select 1 from core.pd_userinroles as pur where pur.f_role = _f_role and pur.f_user = _f_user)
	then 
		return 4;
	end if;

	insert into core.pd_userinroles (f_user, f_role)
	select  _f_user, _f_role;

	RETURN 0;

END

Function: dbo.cf_mim_user_disable(_c_tab_number text, _b_disabled boolean)

Returns: integer

Language: PLPGSQL

Блокировка/Разблокировка пользователя

BEGIN	

	-- если табельный номер не передан - то выход
	if nullif(trim(_c_tab_number), '') is null then
		RETURN 1;
	end if;

	-- пользователя с таким табельным номером не существует
	if not exists(select 1 from core.pd_users where c_tab_number = _c_tab_number)
	then 
		return 2;
	end if;

	-- если есть что менять - то необходимо выполнить изменение
	if exists (select 1 from core.pd_users where c_tab_number = _c_tab_number and (b_disabled::int4 # _b_disabled::int4)::bool) then 
		update core.pd_users 
		set b_disabled = _b_disabled
		where c_tab_number = _c_tab_number;
	end if;

	RETURN 0;

END

Function: dbo.cf_mim_user_pwd_change(_c_tab_number text, _c_new_pwd text)

Returns: integer

Language: PLPGSQL

Изменение пароля

BEGIN	

	if 		nullif(trim(_c_tab_number), '') 	is null 
		or 	_c_new_pwd							is null 
	then 
		return 1;
	end if; 
	

	-- пользователя с таким табельным номером не существует
	if not exists(select 1 from core.pd_users where c_tab_number = _c_tab_number)
	then 
		return 2;
	end if;

	-- изменение пароля
	update core.pd_users 
	set s_salt 		= null,
		s_hash 		= crypt(_c_new_pwd, gen_salt('bf', 8)), 
		b_pgcrypto 	= true
	where c_tab_number = _c_tab_number;

	-- успешный выход
	RETURN 0;

END

Function: dbo.cf_mui_ed_blanks(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Список бланков для обходчика

DECLARE 
	_day text;
BEGIN
	select coalesce(s.c_value, '30') into _day from core.cd_settings as s
	where s.c_key = 'DB_SEAL_DAY';
	
    RETURN QUERY select 
		b.id, 
		b.f_result_type,
		coalesce(b.c_number, concat(b.c_prefix, b.n_number::text)) as c_number, 
		b.f_user_to, 
		b.f_status, 
		b.dx_created
	from dbo.ed_blanks as b
	where b.f_user_to = _fn_user and b.f_status != 4 and b.f_status != 1 and (b.dx_created + (_day || ' day')::interval)::date >= now()::date;
END

Function: dbo.cf_mui_ed_input_conn_seals(_fn_user integer, _c_version text, _f_point uuid)

Returns: SET OF record

Language: PLPGSQL

Список входных пломб для обходчика

BEGIN
    RETURN QUERY 
	select
		t.uuid_id,
		t.id,
		t.f_registr_pts,
		t.f_point,
		t.c_number,
		t.c_name,
		t.c_location,
		t.dx_created,
		t.d_replace_date,
		t.n_row
	from (select
		t.*,
		row_number() over(partition by t.id, t.f_point order by t.dx_created desc) as n_row
	from (select uuid_generate_v4() as uuid_id, s.id, s.f_registr_pts, p.id as f_point, concat(coalesce(s.c_prefix, ''), s.c_number) as c_number, st.c_name, s.c_location, s.dx_created, s.d_replace_date
    from core.cd_userinroutes as uir
    inner JOIN core.cd_points as p ON p.f_route = uir.f_route
    inner JOIN core.cd_routes as rt ON rt.id = uir.f_route
	inner JOIN dbo.ed_seals as s ON s.f_registr_pts = p.f_registr_pts
	inner join dbo.es_seal_types as st ON st.id = s.f_type
    left join dbo.ed_output_conn_seals as ocs ON ocs.fn_point = p.id 
	where uir.f_user = _fn_user and (s.d_replace_date is null or ocs.fn_seal = s.id) and CASE WHEN _f_point is null THEN core.sf_is_mobile_route(rt.id) ELSE p.id = _f_point END) as t
	) as t
	where t.n_row = 1
	;
END

Function: dbo.cf_mui_ed_input_meter_readings(_fn_user integer, _c_version text, _f_point uuid)

Returns: SET OF record

Language: PLPGSQL

Получение входящих показаний мобильным устройством

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_ed_input_meter_readings", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY 
	select uuid_generate_v4() as uuid_id, imp.id, p.id as f_point, imp.n_value_prev, imp.d_date_prev, imp.n_digit, imp.f_scale, s.n_order, s.c_name, et.c_const, imp.d_replace_date, imp.jb_sources::text
    from core.cd_userinroutes as uir
    inner JOIN core.cd_points as p ON p.f_route = uir.f_route
    inner JOIN core.cd_routes as rt ON rt.id = uir.f_route
    inner JOIN dbo.ed_input_meter_readings as imp ON imp.f_registr_pts = p.f_registr_pts
	inner join dbo.es_energy_types as et ON et.id = imp.f_energy_type
	inner join dbo.es_scales as s on imp.f_scale = s.id 
	left join dbo.ed_output_meter_readings as omr ON omr.fn_point = p.id 
	left join core.cd_user_points as up ON up.id = omr.fn_user_point
    where uir.f_user = _fn_user and 
		(case when up.id is not null then up.fn_user = _fn_user else 1=1 end) and 
		(imp.d_replace_date is null or omr.fn_meter_reading = imp.id) and CASE WHEN _f_point is null THEN core.sf_is_mobile_route(rt.id) ELSE p.id = _f_point END;
END

Function: dbo.cf_mui_ed_input_transformers(_fn_user integer, _c_version text, _f_point uuid)

Returns: SET OF record

Language: PLPGSQL

Список входных трансформаторов для обходчика

BEGIN
    RETURN QUERY select uuid_generate_v4(), tf.id, p.id, dt.c_name, tf.b_voltage, tf.c_serial_number, tf.n_manufacture_year, coalesce(dt.n_rate, tf.n_rate), tf.c_phase, tf.f_registr_pts, tf.d_check_date, tf.dx_created, tf.d_replace_date
    from core.cd_userinroutes as uir
    inner JOIN core.cd_points as p ON p.f_route = uir.f_route
    inner JOIN core.cd_routes as rt ON rt.id = uir.f_route
    inner JOIN dbo.ed_transformers as tf ON tf.f_registr_pts = p.f_registr_pts
	inner join dbo.es_device_types as dt ON dt.id = tf.f_device_type
    where uir.f_user = _fn_user and (tf.d_replace_date is null or tf.id in (select et.fn_transformer from dbo.ed_output_transformers as et where et.fn_point = p.id)) and CASE WHEN _f_point is null THEN core.sf_is_mobile_route(rt.id) ELSE p.id = _f_point END;
END

Function: dbo.cf_mui_ed_output_conn_seals(_fn_user integer, _c_version text, _f_point uuid)

Returns: SET OF record

Language: PLPGSQL

Выходные пломбы для обходчика

BEGIN
	RETURN QUERY select s.id, s.fn_seal, s.fn_point, s.fn_route, s.fn_user_point, s.fn_result, s.fn_seal_new, concat(coalesce(ss.c_prefix, ''), ss.c_number), s.fn_type, st.c_name, s.fn_place, sp.c_name, s.d_date, s.dx_created, ss.d_replace_date
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as r ON r.id = uir.f_route
    INNER JOIN dbo.ed_output_conn_seals as s ON s.fn_route = r.id
	inner join dbo.es_seal_places as sp ON sp.id = s.fn_place
	inner join dbo.es_seal_types as st ON st.id = s.fn_type
	inner join dbo.ed_seals as ss ON ss.id = s.fn_seal_new
    where uir.f_user = _fn_user and CASE WHEN _f_point is null THEN core.sf_is_mobile_route(r.id) ELSE s.fn_point = _f_point END;
END

Function: dbo.cf_mui_ed_output_meter_readings(_fn_user integer, _c_version text, _f_result uuid)

Returns: SET OF record

Language: PLPGSQL

Получение исходящих показаний мобильным устройством

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_ed_output_meter_readings", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
    RETURN QUERY 
	select omr.id, omr.fn_meter_reading, omr.fn_route, omr.fn_point, omr.fn_user_point, omr.fn_result, omr.n_value, omr.d_date
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as r ON r.id = uir.f_route
    INNER JOIN dbo.ed_output_meter_readings as omr ON omr.fn_route = r.id
	left join core.cd_user_points as up ON up.id = omr.fn_user_point
	inner join dbo.ed_input_meter_readings as imr ON imr.id = omr.fn_meter_reading
    where uir.f_user = _fn_user and up.fn_user = _fn_user and (CASE WHEN _f_result is null THEN core.sf_is_mobile_route(r.id) ELSE omr.fn_result = _f_result END);
END

Function: dbo.cf_mui_ed_output_transformers(_fn_user integer, _c_version text, _f_point uuid)

Returns: SET OF record

Language: PLPGSQL

Исходящая информация о трансформаторах для обходчика

BEGIN
	RETURN QUERY select t.id, t.fn_route, t.fn_point, t.fn_user_point, t.fn_result, t.fn_transformer, t.fn_device_type, dt.c_name, t.c_number, t.n_year, t.d_date, t.n_rate, t.fn_phase, ph.c_name, t.b_voltage, t.d_date_check, t.n_check_cycle, t.n_tt1, t.n_tt2
    from core.cd_userinroutes as uir
    LEFT JOIN core.cd_routes as r ON r.id = uir.f_route
    inner JOIN dbo.ed_output_transformers as t ON t.fn_route = r.id
	left join dbo.es_device_types as dt ON dt.id = t.fn_device_type
	left join dbo.es_phase as ph ON t.fn_phase = ph.id
    where uir.f_user = _fn_user and CASE WHEN _f_point is null THEN core.sf_is_mobile_route(r.id) ELSE t.fn_point = _f_point END;
END

Function: dbo.cf_mui_ed_seals(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Список пломб для обходчика

DECLARE 
	_day text;
BEGIN
	select coalesce(s.c_value, '30') into _day from core.cd_settings as s
	where s.c_key = 'DB_SEAL_DAY';
	
    RETURN QUERY select 
		s.id, 
		concat(coalesce(s.c_prefix, ''), s.c_number), 
		s.f_user_to, 
		s.f_type,
		st.c_name,
		s.f_status, 
		s.dx_created
	from dbo.ed_seals as s
	inner join dbo.es_seal_types as st ON st.id = s.f_type
	left join dbo.ed_output_conn_seals as ocs ON ocs.fn_seal_new = s.id
	where (s.f_user_to = _fn_user and 
		s.f_status != 5 and s.f_status != 1 and 
		(s.dx_created + (_day || ' day')::interval)::date >= now()::date) or
		s.id in (select s.id
				from core.cd_userinroutes as uir
				inner JOIN core.cd_points as p ON p.f_route = uir.f_route
				inner JOIN core.cd_routes as rt ON rt.id = uir.f_route
				inner JOIN dbo.ed_seals as s ON s.f_registr_pts = p.f_registr_pts
				left join dbo.ed_output_conn_seals as ocs ON ocs.fn_point = p.id 
				where uir.f_user = _fn_user and (s.d_replace_date is null or ocs.fn_seal = s.id) and core.sf_is_mobile_route(rt.id));
END

Function: dbo.cf_mui_es_device_location(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Место установки

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_device_location", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select dl.id, dl.c_name, dl.c_const
	from dbo.es_device_location as dl;
END

Function: dbo.cf_mui_es_device_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Типы устройств

BEGIN
    return query 
	with divisions as (select 
					coalesce(sd.f_division, uid.f_division) as f_main_division, 
	   				(case when sd.f_division is null then null else uid.f_division end) as f_division, 
				   	uid.f_subdivision
	from core.pd_userindivisions as uid
	inner join core.sd_divisions as sd on sd.id = uid.f_division 
	where uid.f_user = _fn_user)
	select 
		dt.id, 
		dc.b_meter, 
		dt.c_name,  
		dt.n_check_cycle,
		dt.f_main_division,
		dt.f_division,
		dt.f_subdivision,
		dt.n_tt1,
		dt.n_tt2
	from dbo.es_device_types as dt
	inner join dbo.es_device_categories as dc ON dc.id = dt.f_device_categories
	where dt.b_disabled = false and 
	(dt.f_main_division is null and dt.f_division is null and dt.f_subdivision is null);
END

Function: dbo.cf_mui_es_energy_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тип энергии

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_energy_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select et.id, et.c_name, et.c_const, et.n_code, et.b_default
	from dbo.es_energy_types as et;
END

Function: dbo.cf_mui_es_failure_reason(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Причины недопуска

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_restrictions", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select fr.id, fr.c_name, fr.c_const, fr.n_order
	from dbo.es_failure_reason as fr
	where fr.b_disabled = false;
END

Function: dbo.cf_mui_es_phase(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Фазы

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_phase", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select p.id, p.c_name
	from dbo.es_phase as p;
END

Function: dbo.cf_mui_es_restrictions(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Типы ограничений

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_restrictions", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select r.id, r.c_name, r.c_const, r.n_order
	from dbo.es_restrictions as r
	where r.b_disabled = false;
END

Function: dbo.cf_mui_es_scales(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Шкалы прибора учета

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_scales", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select s.id, s.c_name, s.c_const, s.n_order
	from dbo.es_scales as s
	where s.b_disabled = false;
END

Function: dbo.cf_mui_es_seal_places(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Справочник мест установки пломб

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_seal_places", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select sp.id, sp.c_name, sp.c_const, sp.n_order
	from dbo.es_seal_places as sp
	where sp.b_disabled = false;
END

Function: dbo.cf_mui_es_seal_types(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

тип пломбы

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_seal_types", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select st.id, st.c_name, st.c_const, st.n_order
	from dbo.es_seal_types as st
	where st.b_disabled = false;
END

Function: dbo.cf_mui_es_tariff_zones(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Тарифные зоны

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_work_links", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select tz.id, tz.c_name, tz.c_const, tz.n_order
	from dbo.es_tariff_zones as tz
	where tz.b_disabled = false;
END

Function: dbo.cf_mui_es_verification_reason(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Причина проверки

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_verification_reason", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select vr.id, vr.c_name, vr.c_const, vr.n_order
	from dbo.es_verification_reason as vr
	where vr.b_disabled = false;
END

Function: dbo.cf_mui_es_violations(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Типы нарушений

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_violations", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select v.id, v.c_name, v.c_const, v.n_order
	from dbo.es_violations as v
	where v.b_disabled = false;
END

Function: dbo.cf_mui_es_work_links(_fn_user integer, _c_version text)

Returns: SET OF record

Language: PLPGSQL

Сопоставление видов работ

/**
* @params {integer} _fn_user - идентификатор пользователя
* @params {text} _c_version - текущая версия приложения
*
* @example
* [{ "action": "cf_mui_es_work_links", "method": "Select", "data": [{ "params": [_fn_user, _c_version] }], "type": "rpc", "tid": 0 }]
*/
BEGIN	
	RETURN QUERY select el.id, el.f_route_type, el.f_point_type, el.f_result_type
	from dbo.es_work_links as el
	where el.b_disabled = false;
END

Function: dbo.cf_process_coord_update()

Returns: void

Language: PLPGSQL

	
	DECLARE
		_updates_geo 	int = 0;		-- кол-во вставленных ЛС
begin


	insert into core.cd_sys_log(d_timestamp, c_descr)
	values(clock_timestamp(), 'Запущено обновление пустых координат в справочнике адресов.');

	update dbo.ed_registr_pts AS erp
	set 
		n_geo_lat = geeo.n_geo_lat,
		n_geo_lon = geeo.n_geo_lon
	from 
		(
			select 
				cp.f_registr_pts, 				-- точка учета
				row_number() over(partition by cp.f_registr_pts order by cup.d_date asc, cp.id desc) as n_row, 	-- координат может быть несколько, берется самая первая по дате
				cup.n_latitude  as n_geo_lat,	-- широта
				cup.n_longitude as n_geo_lon 	-- долгота
			from core.cd_points as cp
				inner join core.cd_user_points AS cup
					on 	cup.fn_point 	= cp.id
			where cup.n_latitude > 0 and cup.n_longitude > 0	--координаты только из тех строк где они есть
		) as geeo
	where 1=1
		and (	coalesce(erp.n_geo_lat, 0) <> round(geeo.n_geo_lat, 6)
			or 	coalesce(erp.n_geo_lon, 0) <> round(geeo.n_geo_lon, 6))
		and	geeo.f_registr_pts	= erp.id
		and geeo.n_row		= 1;

	GET DIAGNOSTICS _updates_geo = ROW_COUNT;

	insert into core.cd_sys_log(d_timestamp, c_descr)
	values(clock_timestamp(), 'Обновление пустых координат в справочнике адресов выполнено. Обновлено ' || _updates_geo::text);

	EXCEPTION
	WHEN OTHERS
    THEN
		insert into core.cd_sys_log(d_timestamp, c_descr)
		values(clock_timestamp(), 'Непредвиденная ошибка обновления пустых координат в справочнике адресов');

end;

Function: dbo.cf_process_exp_buffers(_session_id uuid, _f_div text, _f_subdiv text, _d_date_begin date, _d_date_end date)

Returns: void

Language: PLPGSQL

Заполнение буферов экспорта

DECLARE
	_message_text 	text;
	_status_weight 	integer;
BEGIN

	_session_id = coalesce(_session_id, uuid_generate_v4());
	
	select rs.n_order into _status_weight 
	from core.cs_route_statuses as rs
	where rs.c_const = 'ASSINGNED'; -- выгружаются маршруты не ниже этого статуса

	insert into imp.i_integration_sessions(
		sessionId 	,
		startTime 	,
		status 		,
		parameters
	)
	select 
		_session_id 		as sessionId,
		now() 				as startTime,
		'Операция запущена' as status,
		concat(	'Экспорт результатов. Параметры',
				': Отделения: ',	coalesce(_f_div, 'все отделения'), 
				', Участки: ', 		coalesce(_f_subdiv, 'все участки'),
				', Интервал с: ',	_d_date_begin,
				', Интервал по: ',	_d_date_end
		) 					as parameters
	on conflict on CONSTRAINT i_integration_sessions_pkey 
	do update 
		set 
			parameters		= concat(imp.i_integration_sessions.parameters, excluded.parameters)
	;



	begin 
		


		-- маршруты
		begin 

			insert into imp.e_routes
			(
				f_maindivision	,		--Код Филиала	
				f_subdivision	,		--Код участка	
				f_doc			,		--Идентификатор (Первичный ключ) маршрута	
				c_doc_name		,		--Номер (наименование) маршрута	
				d_begin_date	,		--Дата начала маршрута	
				d_end_date		,		--Дата окончания маршрута	
				c_doc_type		,		--Тип маршрута	
				c_doc_status	,		--Статус маршрута
				g_session_id 	 		--идентификатор сессии экспорта
			)
			select 
				max(coalesce(sdf.c_dep_code, sdf.n_code::text, sd.c_dep_code, sd.n_code::text))
											as f_maindivision,
				max(coalesce(ssd.c_dep_code, ssd.n_code::text))
											as f_subdivision,
				cr.id 						as f_doc,
				cr.c_number					as c_doc_name,
				cr.d_date_start				as d_begin_date,
				cr.d_date_end 				as d_end_date,
				--rt.c_name 					as c_doc_type,
				rt.id 	 					as c_doc_type,
				--rs.c_name 					as c_doc_status,
				rs.id 	 					as c_doc_status,
				_session_id 				as g_session_id
			from core.cd_routes as cr
				-- статус маршрута
				inner join core.cs_route_statuses as rs 
					on 	rs.id 			= cr.f_status
				-- исполнитель маршрута
				inner join core.cd_userinroutes as uir 
					on 	uir.f_route 	= cr.id
					and uir.b_main 		= true
				inner join core.pd_userindivisions as ud
					on 	ud.f_user 		= uir.f_user
					and ud.sn_delete 	= false
				-- отделение
				inner join core.sd_divisions as sd
					on 	sd.id 			= ud.f_division
				-- филиал
				left join core.sd_divisions as sdf
					on 	sdf.id 			= sd.f_division
				-- участок
				inner join core.sd_subdivisions as ssd 
					on 	ssd.id 			= ud.f_subdivision
				-- тип маршрута 
				inner join core.cs_route_types as rt
					on 	rt.id 			= cr.f_type

			where 	1=1
				and rs.n_order 			>= _status_weight
				and _d_date_end::date 	>= cr.d_date_start 
				and _d_date_begin::date <= CASE WHEN cr.b_extended THEN cr.d_extended ELSE cr.d_date_end END
				and case 
						when _f_div is null or _f_div = '' then true 
						else  coalesce(sdf.c_dep_code, sdf.n_code::text, sd.c_dep_code) in (select a.elem from unnest(string_to_array(_f_div, ',')) as a(elem) )
					end
				and case 
						when _f_subdiv is null or _f_subdiv = '' then true 
						else  ssd.c_dep_code in (select a.elem from unnest(string_to_array(_f_subdiv, ',')) as a(elem) )
					end
			group by 
				cr.id 			,
				cr.c_number		,
				cr.d_date_start	,
				cr.d_date_end 	,
				rt.id 	 		,
				rs.id;

		end;


		-- Строки заданий
		begin 

			insert into imp.e_points (
				f_maindivision 		,
				f_doc_detail		,		--идентификатор строки	
				f_doc				,		--идентификатор (первичный ключ) маршрута	
				f_registr_pts		,		--ссылка на идентификатор ту (код ту)	
				c_fias_town			,		--код фиас города	
				c_fias_municipality	,		--код фиас населенного пункта 	
				c_fias_street		,		--код фиас улицы	
				c_fias_building		,		--код фиас дома	
				n_latitude			,		--широта	
				n_longitude			,		--долгота
				g_session_id 		
			)
			select 
				r.f_maindivision 		as f_maindivision,
				cp.id 					as f_doc_detail,
				cp.f_route 				as f_doc,
				erp.imp_text 			as f_registr_pts,
				sa.data_city_fias_id::text 		as c_fias_town,
				sa.settlement_fias_id::text 	as c_fias_municipality,
				sa.data_street_fias_id::text 	as c_fias_street,
				sa.data_house_fias_id::text 	as c_fias_building,
				coalesce(erp.n_geo_lat, sa.n_geo_lat)
										as n_latitude,
				coalesce(erp.n_geo_lon, sa.n_geo_lon)
										as n_latitude,
				_session_id 			as g_session_id											
			from imp.e_routes as r
				inner join core.cd_points as cp
					on 	cp.f_route 	= r.f_doc
				inner join dbo.ed_registr_pts as erp
					on 	erp.id 		= cp.f_registr_pts
				left join dbo.ss_address as sa
					on 	sa.id 		= erp.f_address
			where 	1=1
				and r.g_session_id = _session_id;

		end;


		-- результаты
		begin 

			insert into imp.e_results (
				f_maindivision 		 		,		-- 	код филиала
				f_docout					,		--	идентификатор документа	
				f_doc_detail				,		--	идентификатор строки задания	
				f_registr_pts 				, 
				f_registr_pts_mk			, 
				f_device_guid 				,
				f_device 					, 		-- 	идентификатор ПУ
				d_docout_date				,		--	дата документа	
				c_docout_number				,		--	номер документа (системный или номер бланка)	
				f_docout_type 				, 		-- 	
				c_docout_name				,		--	наименование документа	
				c_user_fio					,		--	фио исполнителя	
				c_note						,		--	поле "примечание" карточки акта	
				c_type_violation			,		--	тип нарушения	
				d_violation_date_before		,		--	срок устранения нарушения	
				c_note_violation			,		--	характеристика нарушения	
				d_violation_date_begin		,		--	нарушение с	
				d_violation_date_end		,		--	нарушение по	
				c_reason_fail				,		--	причина невыполнения	
				d_restrict_date				,		--	дата ограничения	
				c_restrict					,		--	тип ограничения	
				d_ranewal_date				,		--	дата возобновления
				f_check_reason 				, 		-- 	причина проверки
				c_voltage_a					,		-- 	напряжение фазное A
				c_voltage_b					,		-- 	напряжение фазное B
				c_voltage_c					,		-- 	напряжение фазное C
				c_power_disk				,		-- 	активная мощность по оборотам диска в силовой цепи
				c_power_meters				,		-- 	активная мощность по приборам в силовой цепи
				c_reactive_disk				,		-- 	реактивная мощность по оборотам диска в силовой цепи
				c_reactive_meters			,		-- 	реактивная мощность по приборам в силовой цепи
				c_user_tab_number			,		-- 	табельный номер пользователя, который составил акт
				g_session_id 				 		--	идентификатор сессии экспорта
			)
			select 
				p.f_maindivision 								as f_maindivision,
				cr.id 											as f_docout,
				cr.fn_point 									as f_doc_detail,
				p.f_registr_pts 								as f_registr_pts,
				cp.f_registr_pts 								as f_registr_pts_mk,
				ed.f_device_guid 								as f_device_guid,
				ed.f_device 									as f_device,
				cr.d_date::date									as d_docout_date,
				coalesce(cr.jb_data ->> 'c_act_number', concat(rt.c_short_name, '-', u.id::text,'-',ed.c_serial_number)) 
																as c_docout_number,
				coalesce(rt.c_code_out, rt.n_code::text, rt.id::text)	
																as f_docout_type,
				coalesce(rt.c_code_out, rt.n_code::text, rt.c_name)	
																as c_docout_name,
				concat(u.c_last_name || ' ', u.c_first_name || ' ', u.c_middle_name)
							 									as c_user_fio,
				cr.c_notice 									as c_note,
				coalesce(ev.c_code_out, ev.n_code::text)		as c_type_violation,
				(cr.jb_data ->> 'd_violation_date_end')::date	as d_violation_date_before,
				cr.jb_data ->> 'c_violation_notice' 			as c_note_violation,
				(cr.jb_data ->> 'd_violation_date_start')::date as d_violation_date_begin,
				(cr.jb_data ->> 'd_violation_date_end')::date 	as d_violation_date_end,
				coalesce(efr.id::text, cr.jb_data ->> 'c_failure', efr.c_name)
																as c_reason_fail,
				case when rt.c_const = 'AVOE' then cr.d_date::date end
						 										as d_restrict_date,
				coalesce(er.id::text, cr.jb_data ->> 'c_restriction', er.c_name)
											 					as c_restrict,
				case when rt.c_const = 'AVE' then cr.d_date::date end
						 										as d_ranewal_date,
				cp.f_type::text 								as f_check_reason,
				cr.jb_data ->> 'c_voltage_a'					as c_voltage_a 		,
				cr.jb_data ->> 'c_voltage_b'					as c_voltage_b		,
				cr.jb_data ->> 'c_voltage_c'					as c_voltage_c		,
				cr.jb_data ->> 'c_power_disk'					as c_power_disk		,
				cr.jb_data ->> 'c_power_meters'					as c_power_meters	,
				cr.jb_data ->> 'c_reactive_disk'				as c_reactive_disk	,
				cr.jb_data ->> 'c_reactive_meters'				as c_reactive_meters,
				u.c_tab_number 									as c_user_tab_number,
				_session_id 									as g_session_id
			from imp.e_points as p
				-- результат
				inner join core.cd_results as cr
					on 	cr.fn_point = p.f_doc_detail
				-- строки
				inner join core.cd_points as cp
					on 	cp.id 		= p.f_doc_detail
				-- исполнитель
				inner join core.pd_users as u
					on 	u.id 		= cr.fn_user
				-- тип документа 
				inner join core.cs_result_types as rt
					on 	rt.id 		= cr.fn_type
					--and rt.c_const 	= 'CMR'
				-- типы нарушений
				left join dbo.es_violations as ev
					on 	ev.id 		= (cr.jb_data ->> 'f_violation')::integer
				-- причины недопуска 
				left join dbo.es_failure_reason as efr
					on 	efr.id 		= (cr.jb_data ->> 'f_failure')::integer 
				-- тип ограничения
				left join dbo.es_restrictions as er
					on 	er.id 		= (cr.jb_data ->> 'f_restriction')::integer 
				-- последний прибор на дату 
				left join lateral (
					select 
						ed.f_registr_pts,
						ed.c_serial_number,
						nullif(ed.imp_text, '')		as f_device,
						ed.id 						as f_device_guid,
						row_number() over(partition by ed.f_registr_pts order by ed.d_setup_date desc, ed.d_close_date desc) as n_row
					from dbo.ed_devices as ed 
					where 1=1
						and ed.f_registr_pts 	= cp.f_registr_pts
						and (ed.d_setup_date is null or ed.d_setup_date < cr.d_date)
						and (ed.d_close_date is null or ed.d_close_date >= cr.d_date)
				) as ed 
					on 	1=1
					and ed.n_row 			= 1
			where 	1=1
				and cr.b_check
				and p.g_session_id 	= _session_id;

		end;

		
		-- приборы
		begin 

			insert into imp.e_devices(
				f_docout					,	--идентификатор документа	
				f_device					,	--код/идентификатор пу	
				c_serial_number				,	--заводской номер	
				d_close_date				,	--дата снятия  существующего пу	
				f_device_tn					,	--код/идентификатор тн	
				c_serial_number_tn			,	--заводской номер тн	
				d_close_date_tn				,	--дата снятия существующего тн	
				f_device_tt					,	--код/идентификатор тт	
				c_serial_number_tt			,	--заводской номер тт	
				d_close_date_tt				,	--дата снятия существующего тт	
				--f_device_new				,	--код/идентификатор нового пу	
				d_setup_date				,	--дата установки нового пу	
				c_serial_number_new			,	--заводской номер	
				f_device_type 				,
				c_device_type				,	--наименование модели	
				c_device_location_type		,	--место установки	
				b_phase3					,	--фазность трехфазный прибор 0 - нет 1 - да	
				f_time_zone					,	--тариф	
				f_energy_type 				,
				--f_scale						,	--шкала	
				n_device_mpi				,	--мпи (число лет)	
				d_release_date				,	--год выпуска	
				d_verification_date			,	--дата поверки пу	
				
				f_device_tn_new				,	--код/идентификатор нового тн	
				d_setup_date_tn				,	--дата установки нового тн	
				c_serial_number_tn_new		,	--заводской номер тн	
				f_device_type_tn 			,
				c_device_type_tn			,	--наименование модели тн	
				c_phase_tn_new				,	--фаза	
				n_device_mpi_tn				,	--мпи (число лет)	
				d_release_date_tn			,	--год выпуска	
				d_verification_date_tn		,	--дата поверки пу	
				n_tt1_tn					,	--номинальное напряжение первичной обмотки, в	
				n_tt2_tn					,	--номинальное напряжение вторичной обмотки, в	
				
				f_device_tt_new				,	--код/идентификатор тт	
				d_setup_date_tt				,	--дата установки тт (новый)	
				c_serial_number_tt_new		,	--заводской номер тт	
				f_device_type_tt	 		,
				c_device_type_tt			,	--наименование типа	
				c_phase_tt_new				,	--фаза	
				n_device_mpi_tt				,	--мпи (число лет)	
				d_release_date_tt			,	--год выпуска	
				d_verification_date_tt		,	--дата поверки пу	
				n_tt1_tt					,	--номинальный ток первичной обмотки, а	
				n_tt2_tt					,	--номинальный ток вторичной обмотки, а
				g_session_id 				 	--идентификатор сессии экспорта
			)
			select DISTINCT
				cr.id 												as f_docout,
				er.f_device 										as f_device,			
				coalesce(ed.c_serial_number, cp.jb_data ->> 'c_device_number')
												 					as c_serial_number,
				case when rt.c_const = 'AZPU' then cr.d_date else ed.d_close_date end
																 	as d_close_date,		-- будем считать что дата акта и есть дата снятия старого ПУ
				tn.f_device_tn										as f_device_tn, 		
				tn.c_serial_number_tn 								as c_serial_number_tn,
				tn.d_close_date_tn 									as d_close_date_tn,
				
				tt.f_device_tt										as f_device_tt, 		
				tt.c_serial_number_tt 								as c_serial_number_tt,
				tt.d_close_date_tt 									as d_close_date_tt,

				--case when rt.c_const in ('ADEPU', 'AZPU') then edn.id end
				--													as f_device_new,
				case when rt.c_const in ('AM', 'ADEPU', 'AZPU') then cr.d_date end
						 											as d_setup_date,		--будем считать что дата акта и есть дата установки нового ПУ
				cr.jb_data ->> 'c_device_number' 					as c_serial_number_new,
				edn.f_device_type 									as f_device_type,
				cr.jb_data ->> 'c_device_model' 					as c_device_type,
				--cr.jb_data ->> 'c_device_location' 					as c_device_location_type,
				edl.id 												as c_device_location_type,
				edt.b_phase3::int4									as b_phase3,
				(cr.jb_data ->> 'f_tariff_zone')::int4				as f_time_zone,
				null::text 											as f_energy_type,
				--cr.jb_data ->> 'c_tariff_zone'						as f_scale,
				edt.n_check_cycle 									as n_device_mpi,
				(cr.jb_data ->> 'n_year')::int4						as d_release_date,
				(cr.jb_data ->> 'd_check_date')::date				as d_verification_date,
				
				tn.f_device_tn_new									as f_device_tn_new				,
				tn.d_setup_date_tn									as d_setup_date_tn				,
				tn.c_serial_number_tn_new							as c_serial_number_tn_new		,
				tn.f_device_type_tn 								as f_device_type_tn	 			,
				tn.c_device_type_tn									as c_device_type_tn				,
				tn.c_phase_tn_new									as c_phase_tn_new				,
				tn.n_device_mpi_tn									as n_device_mpi_tn				,
				tn.d_release_date_tn								as d_release_date_tn			,
				tn.d_verification_date_tn							as d_verification_date_tn		,
				tn.n_tt1_tn											as n_tt1_tn						,
				tn.n_tt2_tn											as n_tt2_tn						,
				
				tt.f_device_tt_new									as f_device_tt_new				,
				tt.d_setup_date_tt									as d_setup_date_tt				,
				tt.c_serial_number_tt_new							as c_serial_number_tt_new		,
				tt.f_device_type_tt 								as f_device_type_tt	 			,
				tt.c_device_type_tt									as c_device_type_tt				,
				tt.c_phase_tt_new									as c_phase_tt_new				,
				tt.n_device_mpi_tt									as n_device_mpi_tt				,
				tt.d_release_date_tt								as d_release_date_tt			,
				tt.d_verification_date_tt							as d_verification_date_tt		,
				tt.n_tt1_tt											as n_tt1_tt						,
				tt.n_tt2_tt											as n_tt2_tt						,
				_session_id 										as g_session_id
			from imp.e_points as p
				-- точки
				inner join core.cd_points as cp 
					on 	cp.id 			= p.f_doc_detail
				-- результат
				inner join core.cd_results as cr
					on 	cr.fn_point 	= p.f_doc_detail
				inner join imp.e_results as er
					on 	er.g_session_id = p.g_session_id
					and er.f_doc_detail = p.f_doc_detail
					and er.f_docout 	= cr.id
				-- тип документа 
				inner join core.cs_result_types as rt 
					on 	rt.id 			= cr.fn_type
				-- трансформатор тока
				left join (
					select 
						tnew.fn_result, 			-- док
						tnew.fn_phase,
						tnew.id::text						as f_device_tt_new,
						tnew.d_date 						as d_setup_date_tt,
						tnew.c_number 						as c_serial_number_tt_new,
						edt.id 								as f_device_type_tt,
						edt.c_name 							as c_device_type_tt,
						ep.id::text							as c_phase_tt_new,
						edt.n_check_cycle 					as n_device_mpi_tt,
						tnew.n_year 						as d_release_date_tt,
						tnew.d_date_check 					as d_verification_date_tt,
						edt.n_tt1 							as n_tt1_tt,
						edt.n_tt2 							as n_tt2_tt,
						told.c_serial_number 				as c_serial_number_tt,
						told.d_replace_date 				as d_close_date_tt,
						coalesce(told.imp_text, told.id::text) 	as f_device_tt
					from dbo.ed_output_transformers as tnew
						inner join dbo.es_device_types as edt
							on 	edt.id 			= tnew.fn_device_type
						-- предыдущий трансформер
						left join dbo.ed_transformers as told
				 			on told.id 			= tnew.fn_transformer
				 		-- фаза
				 		left join dbo.es_phase as ep
				 			on 	ep.id 			= tnew.fn_phase
				 	where 	tnew.b_voltage 	= false 	-- трансформатор тока
				) as tt
					on 	tt.fn_result 	= cr.id
				-- трансформатор напряжения
				left join (
					select 
						tnew.fn_result, 			-- док
						tnew.fn_phase,
						tnew.id::text						as f_device_tn_new,
						tnew.d_date 						as d_setup_date_tn,
						tnew.c_number 						as c_serial_number_tn_new,
						edt.id 								as f_device_type_tn,
						edt.c_name 							as c_device_type_tn,
						ep.id::text							as c_phase_tn_new,
						edt.n_check_cycle 					as n_device_mpi_tn,
						tnew.n_year 						as d_release_date_tn,
						tnew.d_date_check 					as d_verification_date_tn,
						edt.n_tt1 							as n_tt1_tn,
						edt.n_tt2 							as n_tt2_tn,
						told.c_serial_number 				as c_serial_number_tn,
						told.d_replace_date 				as d_close_date_tn,
						coalesce(told.imp_text, told.id::text) 	as f_device_tn
					from dbo.ed_output_transformers as tnew
						inner join dbo.es_device_types as edt
							on 	edt.id 		= tnew.fn_device_type
						-- предыдущий трансформер
						left join dbo.ed_transformers as told
				 			on told.id 			= tnew.fn_transformer
				 		-- фаза
				 		left join dbo.es_phase as ep
				 			on 	ep.id 			= tnew.fn_phase
				 	where 	tnew.b_voltage 	= true 	-- трансформатор напряжения
				) as tn
					on 	tn.fn_result 	= cr.id
					and tn.fn_phase 	= tt.fn_phase
				-- тип устанавливаемого ПУ
				left join dbo.es_device_types as edt
					on 	edt.id 			= (cr.jb_data ->> 'f_device_model')::int4
				-- последний прибор, если вдруг не заполнено в результатах
				left join dbo.ed_devices as ed
					on 	ed.id 			= er.f_device_guid
				-- новый прибор
				left join dbo.ed_devices as edn
					on 	1=1
					and edn.f_registr_pts 	= cp.f_registr_pts
					and edn.d_setup_date 	= cr.d_date
				left join dbo.es_device_location as edl
					on 	edl.id 				= (cr.jb_data ->> 'f_device_location')::integer

			where 	1=1
				and p.g_session_id 	= _session_id
				and coalesce(edn.id, ed.id) is not null;
				--and rt.c_const 		in ('ADEPU', 'AZPU');
			
		end;
		

		-- показания
		begin 

			insert into imp.e_readings
			(
				id 							,
				f_doc_detail				,	--	идентификатор строки	
				f_device 					, 	-- 	ид ПУ из внешней УС
				f_device_new 				, 	-- 	ид ПУ из МК
				c_serial_number				,	--	заводской номер	
				f_energy_type				,	--	вид измерения	
				c_time_zone					,	--	тариф	
				--c_scale						,	--	шкала	
				d_date						,	--	дата показания	
				n_value						,	--	значение показания
				f_delivery_method 			,
				b_cross_null 				,
				f_docout 					,
				g_session_id 				 	--	идентификатор сессии экспорта
			)
			select 
				r.id 		 as id 			,
				max(f_doc_detail		)	as	f_doc_detail		,	
				max(f_device 			)	as	f_device 			, 	
				max(f_device_new 		) 	as 	f_device_new 		,
				max(c_serial_number		)	as	c_serial_number		,	
				max(f_energy_type		)	as	f_energy_type		,	
				max(c_time_zone			)	as	c_time_zone			,	
				max(d_date				)	as	d_date				,	
				max(n_value				)	as	n_value				,	
				max(f_delivery_method 	)	as	f_delivery_method 	,
				max(b_cross_null 		)	as	b_cross_null 		,
				max(f_docout 			)	as	f_docout 			,
				_session_id 							as g_session_id	
			from (
				select 
					imr.id 									as id 					,
					r.f_doc_detail 							as f_doc_detail 		,
					r.f_device 								as f_device				,
					imr.f_device							as f_device_new 		,
					coalesce(ed.c_serial_number, cr.jb_data ->> 'c_device_number')
															as c_serial_number		,
					coalesce(et.c_code_out, es.c_code_out, et.c_name)		
															as f_energy_type		,
					coalesce(es.c_code_out, tz.c_name)		as c_time_zone 			,
					--coalesce(es.c_code_out, es.c_name)		as c_scale				,
					emr.d_date::date						as d_date 				,
					emr.n_value								as n_value 				,
					2 										as f_delivery_method 	,
					0 										as b_cross_null			,
					r.f_docout 					
				from imp.e_results as r
					--показания
					inner join dbo.ed_output_meter_readings as emr 
						on 	emr.fn_point 	= r.f_doc_detail
					inner join dbo.ed_input_meter_readings as imr 
						on imr.id 			= emr.fn_meter_reading
					-- результат
					inner join core.cd_results as cr
						--on 	cr.fn_point 	= r.f_doc_detail
						on cr.id 			= r.f_docout
					-- тарифная зона
					left join dbo.es_tariff_zones as tz 
						on 	tz.id 			= imr.f_tariff_zone
					-- врем зона
					left join dbo.es_scales as es 
						on 	es.id 			= imr.f_scale
					-- вид энергии
					left join dbo.es_energy_types as et 
						on 	et.id 			= imr.f_energy_type
					-- последний прибор
					left join dbo.ed_devices as ed 
						on 	ed.id 			= r.f_device_guid
				where 	1=1
					and r.g_session_id 	= _session_id
					and abs(emr.n_value) > 0
			) as r
			group by 
				r.id;

		end;

		begin 

			insert into imp.e_seals (
				id 							, 	
				f_doc_detail				,	--	идентификатор строки	
				f_docout					,	--	идентификатор документа	
				f_seal						,	--	код/идентификатор пломбы	
				f_registr_pts 				,
				f_seal_mk 					,
				f_device					,	--	код/идентификатор пу	
				c_seal_number_prefix 		, 	-- 	Номер установленной пломбы (префикс)
				c_seal_number				,	--	№ пломбы состоит из префикса и номера	
				f_seal_type					,	--	тип пломбы	
				c_seal_location				,	--	место установки пломбы	
				d_seal_close_date			,	--	дата снятия пломбы	
				d_seal_setup_date			,	--	дата установки пломбы
				g_session_id 				
			)
			select 
				id 							,
				MAX(f_doc_detail		) AS f_doc_detail		,
				MAX(f_docout			) AS f_docout			,
				MAX(f_seal				) AS f_seal				,
				MAX(f_registr_pts 		) AS f_registr_pts 		,
				MAX(f_seal_mk 			) AS f_seal_mk 			,
				MAX(f_device			) AS f_device			,
				MAX(c_seal_number_prefix) AS c_seal_number_prefix,
				MAX(c_seal_number		) AS c_seal_number		,
				MAX(f_seal_type			) AS f_seal_type		,
				MAX(c_seal_location		) AS c_seal_location	,
				MAX(d_seal_close_date	) AS d_seal_close_date	,
				MAX(d_seal_setup_date	) AS d_seal_setup_date	,
				_session_id 	as g_session_id 
			from (
				select 
					coalesce(esn.id, es.id) 			as id,
					r.f_doc_detail 						as f_doc_detail				,
					r.f_docout		 					as f_docout					,
					es.imp_int::text					as f_seal					,
					r.f_registr_pts 					as f_registr_pts 			,
					esn.id::text 						as f_seal_mk 				,
					r.f_device 		 					as f_device					,
					esn.c_prefix 						as c_seal_number_prefix 	, 		-- сделать настраиваемо
					esn.c_number 					 	as c_seal_number			,
					coalesce(est.c_const, est.id::text, est.c_name)
							 							as f_seal_type				,
					coalesce(esp.c_const, espD.c_const, esp.id::text, esp.c_name)
							 							as c_seal_location			,
					esn.d_replace_date 					as d_seal_close_date		,
					ocs.d_date 							as d_seal_setup_date			
				from imp.e_results as r
					--пломбы
					inner join dbo.ed_output_conn_seals as ocs 
						on 	ocs.fn_point 	= r.f_doc_detail
					-- старая пломба
					left join dbo.ed_seals as es
					 	on 	es.id 			= ocs.fn_seal
					-- новая пломба
					left join dbo.ed_seals as esn
					 	on 	esn.id 			= ocs.fn_seal_new
					-- тип пломбы
					left join dbo.es_seal_types as est 
						on 	est.id 			= esn.f_type
					-- место установки пломбы
					left join dbo.es_seal_places as esp 
						on 	esp.id 			= esn.f_place
					-- место по-умолчанию
					left join dbo.es_seal_places as espD
						on 	espD.c_const 	= 'ZISU_PLOMB_20'
				where 	1=1
					and r.g_session_id 	= _session_id
					and coalesce(es.id, esn.id) is not null
			) as r
			group by r.id;	
		end;

		-- фотокарточки
		begin 

			insert into imp.e_photos (
				id 							,
				f_docout					,	--	идентификатор документа	
				f_device 					,
				c_photo						,	--	ссылка на фотографию	
				c_type_photo				,	--	тип фотографии	
				c_note_photo				,	--	комментарий к фотографии
				g_session_id 				
			)
			select 
				cf.id 							as id,
				r.f_docout 						as f_docout,
				r.f_device 						as f_device,
				concat(cs.c_value, '/file?id=', cf.id::text)
						 						as c_photo,
				coalesce(cat.n_code::text, cat.c_name)
												as c_type_photo,
				ca.c_notice 					as c_note_photo,
				_session_id 					as g_session_id
			from imp.e_results as r
				-- вложение
				inner join core.cd_attachments as ca
				 	on 	ca.fn_result 	= r.f_docout
				-- тип вложения
				inner join core.cs_attachment_types as cat
				 	on cat.id 			= ca.fn_type
				 -- файл
				inner join core.cd_files as cf 
					on 	cf.id 			= ca.fn_file
				inner join core.cd_settings as cs 
					on 	cs.c_key 		= 'ALL_URL'
			where 	1=1
				and r.g_session_id 	= _session_id
				;
		end;


		-- сообщение об успешности 
		update imp.i_integration_sessions
		set status 		= 'Success',
			finishdate 	= now()
		where sessionid = _session_id;

		-- обработка ошибок
		exception
				when others then				
					GET STACKED DIAGNOSTICS _message_text = MESSAGE_TEXT;
	end;

	

	if _message_text is not null then 
		
		update imp.i_integration_sessions
			set status 		= 'Fail',
				finishdate 	= now(),
				parameters 	= concat(parameters, '. Текст ошибки: ', _message_text)
		where sessionid = _session_id;

	end if;
	
END;

Function: dbo.cf_process_imp_buffers(_session_id uuid)

Returns: integer

Language: PLPGSQL

Обработка буферов импорта

DECLARE
	_f_division 	int;
	_f_subdivision 	int;
	_rec 			record;
	_count_subscr 	int = 0;		-- кол-во вставленных ЛС
	_count_tu 		int = 0;		-- кол-во вставленных ТУ
	_count_pu 		int = 0;		-- кол-во вставленных ПУ
	_count_tr 		int = 0;		-- кол-во вставленных Трансформаторов
	_count_seals 	int = 0;		-- кол-во вставленных Пломб
	_count_readings int = 0;		-- кол-во вставленных Показаний
	_count_address 	int = 0;		-- кол-во адресов
	_startTime 		timestamptz;	-- время начала 
  	_endTime 		timestamptz;
  	_delta 			double precision;
  	_message_text	text;
BEGIN
	-- Филиал - Общий ПЭС - РЭС
	create temp table t_div (
		f_maindivision text, 
		f_maindivision_code text, 
		f_division text,
		f_division_code text,
		f_subdivision text, 
		f_subdivision_code text
	) on commit drop;
	insert into t_div (
		f_maindivision, f_maindivision_code, f_division, f_division_code, f_subdivision, f_subdivision_code
	)
	select 
		MAX(f_maindivision), f_maindivision_code, MAX(f_division), f_division_code, MAX(f_subdivision), f_subndivision_code 
	from (
	select 
		f_maindivision, f_maindivision_code, f_division, f_division_code, f_subdivision, f_subndivision_code 
	from imp.i_tu_ul itu
	where 	1=1
		and (	itu.g_session_id 		= _session_id
			or 	_session_id				is null)
		and itu.f_subndivision_code is not NULL
		and itu.f_subdivision 		is not NULL
		
	union 
	select 
		f_maindivision, f_maindivision_code, f_division, f_division_code, f_subdivision, f_subndivision_code 
	from imp.i_tu_fl itu
	where 	1=1
		and (	itu.g_session_id 		= _session_id
			or 	_session_id				is null)
		and itu.f_subndivision_code is not NULL
		and itu.f_subdivision 		is not NULL
	) as d
	--where f_subndivision_code = '4400R022'
	group by f_maindivision_code, f_division_code, f_subndivision_code

		;

	-- логирование
	insert into imp.i_integration_sessions(
		sessionId 	,
		startTime 	,
		status 		,
		parameters
	)
	select 
		_session_id 			as sessionId,
		now() 				as startTime,
		'Операция запущена' as status,
		'Перенос НСИ из ВБ в таблицы.'		
							as parameters
	on conflict on CONSTRAINT i_integration_sessions_pkey 
	do update 
		set 
			parameters		= concat(imp.i_integration_sessions.parameters, ' ', excluded.parameters)
	;


	-- витрины для буферов
	-- ТУ
	create temp table t_tu(
		id uuid primary key,
		f_div int,
		f_maindivision text,
		f_maindivision_code text,
		f_division text,
		f_division_code text,
		f_subdiv int,
		f_subdivision text,
		f_subndivision_code text,
		f_partners text,
		c_name_consumer text,
		c_code text,
		f_check_date int4,
		c_telephone text,
		b_person bool,
		b_problem_person int4,
		f_registr_pts text,
		c_registr_pts text,
		c_substation text,
		c_line_substation text,
		c_tp text,
		c_line_tp text,
		c_line_tp_1 text,
		c_line_segment text,
		c_status_registr_pts text,
		d_close_date date,
		c_status_consume text,
		b_technical_metering int4,
		c_status text,
		c_status_value text,
		c_predictr text,
		d_restriction_date date NULL,
		c_restriction_method text NULL,
		c_network_pts_code text NULL,
		n_max_cap integer NULL,
		b_sub bool not null default false,
		b_transit bool not null default false,
		row_num int
	) on commit drop;
	-- КА
	create temp table if not exists t_subscr (
	    id uuid,
	    f_division int,
	    f_subdivision int,
	    f_registr_pts_text text,
	    f_registr_pts uuid,
	    f_partners text,
	    c_name1 text,
	    c_name2 text ,
	    c_name3 text ,
	    c_telephone text ,
	    c_code text ,
	    b_person bool ,
	    f_check_date int,
	    dense_rnk int,
	    f_subscr uuid
	) on commit drop;
	-- ПУ
	create temp table t_pu(
	    id uuid,
	    f_device text,
		f_registr_pts uuid,
		f_registr_pts_text text,
	    c_serial_number text,
	    c_device_type text,
	    b_phase3 bool,
	    f_device_location_type text,
	    f_time_zone text,
	    f_energy_type text,
	    c_digits numeric(5,2),
		d_replace_before text,
		c_askue text,
	    b_askue bool,
		d_setup_date date,
		d_close_date date,
		f_device_type int,
		row_num int
	) on commit drop;
-- трансформаторы
	create temp table t_tr(
		id uuid,
		f_maindivision_code text,
		f_registr_pts uuid,
		f_registr_pts_text text,
		f_device_t text,
		b_voltage bool,
		c_serial_number_t text,
		d_replace_before date,
		c_device_type_t text,
		c_phase text,
		n_tt1_t numeric(9,3),
		n_tt2_t numeric(9,3),
		d_setup_date_t date,
		d_close_date_t date,
		f_device_type int,
		row_num int 
	) on commit drop;
	-- пломюы
	create temp table t_seals(
		id uuid,
		f_registr_pts_text text,
		f_seal text,
		c_seal_number text,
		c_seal_prefix text,
		f_seal_type text,
		f_seal_location text,
		f_registr_pts uuid,
		f_type int,
		f_place int
	) on commit drop;
	-- показания
	create temp table t_readings(
		id uuid,
		f_registr_pts uuid,
		f_registr_pts_text text,
		f_energy_type text,
		f_time_zone text,
		f_scale text,
		d_date date,
		n_value numeric(19,6),
		f_delivery_methods text
	) on commit drop;
	
		-- определяем типы ПУ и соханяем при необхолимости новые
	create temp table if not exists t_pu_type (
		id 					uuid default uuid_generate_v4(),
		f_device_categories int,
		c_device_type 		text,
		b_phase3 			bool,
		f_tariff_zone 		int,
		n_tariff 			int,
		n_digits 			numeric(5, 2),
		type_id 			int
	) on commit drop;

	create temp table if not exists t_address (
		id uuid,
	    dns_rnk int,
	    row_num int,
		f_registr_pts text,
		f_kladr text,
		c_name text,
		c_index text,
		c_region text,
		code_fias_region text,
		c_raion text,
		data_area_fias_id text,
		c_сity_name text,
		data_city_fias_id text, 
		c_settlement_name text,
		settlement_fias_id text,
		c_street_name text,
		data_street_fias_id text,
		c_house_name text,
		data_house_fias_id text,
		c_block_name text,
		c_flat_name text,
		n_fias_level int,
		n_geo_lat numeric(19, 6),
		n_geo_lon numeric(19, 6),
		qc_geo int,
		f_address uuid,
		f_conn_points 	text,
		c_name_obj 		text
	) on commit drop;

	for _rec in 
		select 
			d.f_maindivision_code, d.f_maindivision, sd.id as f_main_id,
			sd1.id as f_div_id,
			d.f_division_code, d.f_division,
			d.f_subdivision_code, d.f_subdivision, ss.id as f_sub_id
		from t_div as d
			left join core.sd_divisions sd 
				on 	sd.c_dep_code 	= d.f_maindivision_code
			left join core.sd_divisions sd1 
				on 	sd1.f_division 	= sd.id
				and (	sd1.c_dep_code = d.f_division_code
					or  d.f_division_code is null)
			left join core.sd_subdivisions ss 
				on 	ss.c_dep_code 	= d.f_subdivision_code
			
	loop
		-- id отделения
		if _rec.f_main_id is not null 
		then
			if _rec.f_div_id is not null
			then
				_f_division = _rec.f_div_id;
			else
				insert into core.sd_divisions (f_division, c_name, c_dep_code)
				values(_rec.f_main_id, coalesce(_rec.f_division, 'Общий'), _rec.f_division_code)
				returning id into _f_division;
			end if;
		else
			if not exists (select 1 from core.sd_divisions where c_dep_code = _rec.f_maindivision_code)
			then 
				-- филиал
				insert into core.sd_divisions (c_name, c_dep_code)
				values(_rec.f_maindivision, _rec.f_maindivision_code)
				returning id into _f_division;
				-- общий ПЭС
				insert into core.sd_divisions (f_division, c_name, c_dep_code)
				values(_f_division, coalesce(_rec.f_division, 'Общий'), _rec.f_division_code)
				returning id into _f_division;
			end if;
		end if;
		-- id участка
		if _rec.f_sub_id is not null 
		then
			_f_subdivision = _rec.f_sub_id;
		else
			insert into core.sd_subdivisions (f_division, c_name, c_dep_code)
			values(_f_division, _rec.f_subdivision, _rec.f_subdivision_code)
			returning id into _f_subdivision;
		end if;


		-- теперь по каждому РЭС обрабатываем буферные таблицы
		begin
			raise notice 'Зона: %, %, %, %, %, %', _f_division, _rec.f_maindivision_code, _rec.f_maindivision, _f_subdivision, _rec.f_subdivision_code, _rec.f_subdivision;
			--- /*1. ТУ */ ---
			_starttime := clock_timestamp();
			insert into t_tu(
				id,
				f_div,
				f_maindivision,
				f_maindivision_code,
				f_division,
				f_division_code,
				f_subdiv,
				f_subdivision,
				f_subndivision_code,
				f_partners,
				c_name_consumer,
				c_code,
				f_check_date,
				c_telephone,
				b_person,
				b_problem_person,
				f_registr_pts,
				c_registr_pts,
				c_substation,
				c_line_substation,
				c_tp,
				c_line_tp,
				c_line_tp_1,
				c_line_segment,
				c_status_registr_pts,
				d_close_date,
				c_status_consume,
				b_technical_metering,
				c_status,
				c_status_value,
				c_predictr,
				d_restriction_date,
				c_restriction_method,
				c_network_pts_code,
				n_max_cap,
				b_sub,
				b_transit
			)
			select
				uuid_generate_v4(),
				_f_division,
				ul.f_maindivision,
				ul.f_maindivision_code,
				ul.f_division,
				ul.f_division_code,
				_f_subdivision,
				ul.f_subdivision,
				ul.f_subndivision_code,
				ul.f_partners,
				ul.c_name_consumer,
				ul.c_code,
				ul.f_check_date,
				ul.c_telephone,
				false,
				ul.b_problem_person,
				ul.f_registr_pts,
				ul.c_registr_pts,
				ul.c_substation,
				ul.c_line_substation,
				ul.c_tp,
				ul.c_line_tp,
				ul.c_line_tp_1,
				ul.c_line_segment,
				ul.c_status_registr_pts,
				ul.d_close_date,
				ul.c_status_consume,
				ul.b_technical_metering,
				ul.c_status,
				ul.c_status_value,
				ul.c_predictr,
				ul.d_restriction_date,
				ul.c_restriction_method,
				ul.c_network_pts_code,
				ul.n_max_cap,
				coalesce(ul.b_sub, False),
				coalesce(ul.b_transit, False)
			from imp.i_tu_ul ul
			where 	ul.f_maindivision_code 	= _rec.f_maindivision_code
				and ul.f_subndivision_code 	= _rec.f_subdivision_code
				and (	ul.g_session_id 		= _session_id
					or 	_session_id				is null)
			;

			insert into t_tu(
				id,
				f_div,
				f_maindivision,
				f_maindivision_code,
				f_division,
				f_division_code,
				f_subdiv,
				f_subdivision,
				f_subndivision_code,
				f_partners,
				c_name_consumer,
				c_code,
				c_telephone,
				b_person,
				b_problem_person,
				f_registr_pts,
				c_registr_pts,
				c_substation,
				c_line_substation,
				c_tp,
				c_line_tp,
				c_line_tp_1,
				c_line_segment,
				c_status_registr_pts,
				d_close_date,
				c_status_consume,
				b_technical_metering,
				c_status,
				c_status_value,
				c_predictr,
				d_restriction_date,
				c_restriction_method,
				c_network_pts_code,
				n_max_cap,
				b_sub,
				b_transit
			)
			select
				uuid_generate_v4(),
				_f_division,
				fl.f_maindivision,
				fl.f_maindivision_code,
				fl.f_division,
				fl.f_division_code,
				_f_subdivision,
				fl.f_subdivision,
				fl.f_subndivision_code,
				fl.f_partners,
				fl.c_name_consumer,
				fl.c_code,
				fl.c_telephone,
				true,
				fl.b_problem_person,
				fl.f_registr_pts,
				fl.c_registr_pts,
				fl.c_substation,
				fl.c_line_substation,
				fl.c_tp,
				fl.c_line_tp,
				fl.c_line_tp_1,
				fl.c_line_segment,
				fl.c_status_registr_pts,
				fl.d_close_date,
				fl.c_status_consume,
				fl.b_technical_metering,
				fl.c_status,
				fl.c_status_value,
				fl.c_predictr,
				fl.d_restriction_date,
				fl.c_restriction_method,
				fl.c_network_pts_code,
				fl.n_max_cap,
				coalesce(fl.b_sub, False),
				coalesce(fl.b_transit, False)
			from imp.i_tu_fl fl
			where 	fl.f_maindivision_code 	= _rec.f_maindivision_code
				and fl.f_subndivision_code 	= _rec.f_subdivision_code
				and (	fl.g_session_id			= _session_id
					or 	_session_id				is null);

			update t_tu as t0
			set row_num = t.row_num
			from (
				select t.id, row_number() over (partition by t.f_registr_pts order by t.id) as row_num
				from t_tu as t
				) as t
			where 	t0.id = t.id;

			delete from t_tu where row_num > 1;

			update t_tu as t
			set id = erp.id
			from  dbo.ed_registr_pts erp
			where  	erp.f_division 		= _f_division
				and erp.f_subdivision  	= _f_subdivision
				and LPAD(erp.imp_text, 36, '0')		= LPAD(t.f_registr_pts, 36, '0');


			-- справочник статусов 
			update t_tu as t0
			set c_status_consume = (
									select esc.id
									from dbo.es_status_consume as esc
									where esc.n_code = case when t0.c_status_consume ~ '^[0-9\.]+$' = true then t0.c_status_consume::float::integer end
									order by esc.id desc
									limit 1
								)
				
			where c_status_consume is not null;

			-- справочник статусов 
			update t_tu as t0
			set c_status_registr_pts = (
									select esc.id
									from dbo.es_registr_pts_status as esc
									where esc.id = case when t0.c_status_registr_pts ~ '^[0-9\.]+$' = true then t0.c_status_registr_pts::float::integer end
										or esc.c_name = t0.c_status_registr_pts
									order by esc.id desc
									limit 1
								)
				
			where c_status_registr_pts is not null;
			

			--- /*2. КА */ ---
			insert into t_subscr (
				id,
			    f_division,
			    f_subdivision,
			    f_registr_pts_text,
			    f_registr_pts,
			    f_partners,
			    c_name1,
			    c_name2 ,
			    c_name3 ,
			    c_telephone ,
			    c_code ,
			    b_person ,
			    f_check_date,
			    dense_rnk
			   )
			select 
				coalesce(erp.f_subscr, uuid_generate_v4()) as id,
				_f_division as f_division,
				_f_subdivision as f_subdivision,
				s.f_registr_pts as f_registr_pts_text,
				s.id as f_registr_pts,
				s.f_partners,
				case when s.b_person then split_part(s.c_name_consumer, ' ', 1) else s.c_name_consumer end c_name1,
				case when s.b_person then split_part(s.c_name_consumer, ' ', 2) end c_name2,
				case when s.b_person then split_part(s.c_name_consumer, ' ', 3) end c_name3,
				s.c_telephone, 
				s.c_code,
				s.b_person,
				s.f_check_date,
				dense_rank () over (order by c_code, c_name_consumer)
			from t_tu as s
				left join dbo.ed_registr_pts as erp
					on 	erp.id 		= s.id;
			

			--- /*3. ПУ */ ---
			insert into t_pu(
				id,
			    f_device,
				f_registr_pts_text,
			    c_serial_number,
			    c_device_type,
			    b_phase3,
			    f_device_location_type,
			    f_time_zone,
			    f_energy_type,
			    c_digits,
				d_replace_before,
				c_askue,
			    b_askue,
				d_setup_date,
				d_close_date,
				row_num
			)
			select
				coalesce(ed.id, uuid_generate_v4()) as id,
			    p.f_device,
				p.f_registr_pts as f_registr_pts_text,
			    p.c_serial_number as c_serial_number,
			    p.c_device_type,
			    case p.b_phase3 when 3 then true else false end b_phase3,
			    p.c_device_location_type,
			    p.f_time_zone_1_1,
			    p.f_energy_type_1,
			    trunc(case when p.c_digits = 10 then 9.0 when ceil(log(nullif(p.c_digits, 0))) >= 1 then p.c_digits / (power(10, ceil(log(nullif(p.c_digits, 0)))-1)) else p.c_digits end, 1) as c_digits,
				p.d_replace_before,
				p.c_askue,
			    p.b_askue::bool,
				p.d_setup_date,
				p.d_close_date,
				row_number() over(partition by p.f_registr_pts, p.f_device, p.f_energy_type_1, p.f_time_zone_1_1) AS row_num
			from imp.i_pu p 
				inner join t_tu as t 
					on 	t.f_div 		= _f_division 
					and t.f_subdiv 		= _f_subdivision 
					and t.f_registr_pts 		= p.f_registr_pts
					and t.f_maindivision_code 	= p.f_maindivision_code
				left join dbo.ed_devices ed
					on 	LPAD(ed.imp_text, 36, '0') 	= LPAD(p.f_device::text, 36, '0')
					and ed.f_registr_pts 			= t.id
			where 	p.g_session_id		= g_session_id
				or 	_session_id			is null;
			
			delete from t_pu where row_num > 1;

			-- Привязка ПУ к ТУ
			update t_pu p0
			set f_registr_pts = t.id
			from t_tu t
			where 	p0.f_registr_pts_text 	= t.f_registr_pts;
			
			-- по каждому виду энергии ожидается отдельная строка, поэтому итоговый результат надо группировать без вида энергии
			-- так же надо отобрать уникальные тарифы в разрезе ПУ для определения типа ПУ (тарифность, временные зоны)
			-- СТРУКТУРА может измениться, нужно будет актуализировать

			insert into t_pu_type (
				f_device_categories,
				c_device_type,
				b_phase3,
				f_tariff_zone,
				n_tariff,
				n_digits)
			select 
				distinct 1 as f_device_categories,
				t.c_device_type, 
				t.b_phase3 , 
				t.n_tariff as f_tariff_zone,
				t.n_tariff as n_tariff,
				t.c_digits as n_digits
			from (
				select id, 
					count(*) over (partition by f_registr_pts, f_device, f_energy_type) as n_tariff,
					c_device_type,
					c_digits,
					b_phase3
				from t_pu t
			) as t;

			update t_pu_type set f_tariff_zone = 3 where f_tariff_zone > 3;

			-- Сопоставление с существующими справочниками
			update t_pu_type t0
			set type_id = edt.id
			from t_pu_type t
				inner join dbo.es_device_types edt 
					on 	coalesce(edt.c_name, '-') 	= coalesce(c_device_type, '-')
					and coalesce(edt.n_digits, -1) 	= coalesce(t.n_digits, -1)
					and edt.b_phase3 = t.b_phase3
					and edt.f_tariff_zone = t.f_tariff_zone
					and not edt.b_disabled
					and edt.f_device_categories = 1
			where t0.id = t.id;
			
			--Добавление новых записей и привязка
			with t_new_type as (
				insert into dbo.es_device_types(
					f_device_categories, 
					c_name, 
					b_phase3, 
					f_tariff_zone, 
					n_tariff, 
					n_digits, 
					b_disabled)
				select 
					1,
					pt.c_device_type,
					pt.b_phase3,
					pt.f_tariff_zone, 
					pt.n_tariff,
					pt.n_digits,
					false
				from t_pu_type as pt
				where type_id is null
				returning id, c_name, n_digits, b_phase3, f_tariff_zone
			)
			update t_pu_type t
			set type_id = n.id
			from t_new_type n
			where t.type_id is null
				and coalesce(n.c_name, '-') = coalesce(c_device_type, '-')
				and coalesce(n.n_digits, -1) = coalesce(t.n_digits, -1)
				and coalesce(n.b_phase3, false) = coalesce(t.b_phase3, false)
				and n.f_tariff_zone = t.f_tariff_zone;
			
			-- простановка типов ПУ в витрине
			update t_pu p
			set f_device_type = pt.type_id
			from (
					select id, 
						count(*) over (partition by f_device, f_energy_type) as n_tariff,
						c_device_type,
						c_digits,
						b_phase3
					from t_pu t
				) as pp
				inner join t_pu_type pt
					on coalesce(pt.c_device_type, '-') = coalesce(pp.c_device_type, '-')
					and coalesce(pt.n_digits, -1) = coalesce(pp.c_digits, -1)
					and coalesce(pt.b_phase3, false) = coalesce(pp.b_phase3, false)
					and pt.f_tariff_zone = pp.n_tariff
				
			where pp.id = p.id;
			
				
			delete from t_pu
			where id in 
			(
				select id
				from 
				(
					select t.id, row_number() over(partition by f_registr_pts, f_device_type, c_serial_number , d_setup_date order by id ) as n_row
					from t_pu as t
				) as t
				where n_row > 1
			);

			delete from t_pu
			where id in 
			(
				select t.id
				from 
				(
					select t.id, row_number() over(partition by t.id order by t.d_setup_date desc) as n_row
					from t_pu as t
				) as t
				where t.n_row > 1
			);


			--- /*4. Трансформаторы */ ---
			insert into t_tr(
				id,
				f_device_t,
				f_registr_pts,
				f_registr_pts_text,
				b_voltage,
				c_serial_number_t,
				d_replace_before,
				c_device_type_t,
				c_phase,
				n_tt1_t,
				n_tt2_t,
				d_setup_date_t,
				d_close_date_t,
				row_num
			)
			select 
				coalesce(et.id, uuid_generate_v4()) as id,
				itt.f_device_tt as f_device_t,
				null::uuid as f_registr_pts,
				itt.f_registr_pts as f_registr_pts_text,
				false as b_voltage,
				itt.c_serial_number_tt as c_serial_number_t,
				itt.d_replace_before,
				itt.c_device_type_tt as c_device_type_text,
				itt.c_phase,
				itt.n_tt1_tt as n_tt1_t,
				itt.n_tt2_tt as n_tt2_t,
				itt.d_setup_date_tt as d_setup_date_t,
				itt.d_close_date_tt as d_close_date_t,
				row_number() over(partition by itt.f_registr_pts, coalesce(et.id::text, itt.f_device_tt) order by itt.id) as row_num
			from imp.i_tt itt
				inner join t_tu as t 
					on 	t.f_div 		= _f_division 
					and t.f_subdiv 		= _f_subdivision 
					and t.f_registr_pts = itt.f_registr_pts 
					and t.f_maindivision_code = itt.f_maindivision_code
				left join dbo.ed_transformers as et 
					on 	LPAD(et.imp_text, 36, '0') 	= LPAD(itt.f_device_tt, 36, '0')
					and et.f_registr_pts = t.id
			where 	1=1
				and length(trim(itt.c_serial_number_tt)) > 0
				and (	itt.g_session_id			= _session_id
					or 	_session_id				is null)
			union all
			select 
				coalesce(et.id, uuid_generate_v4()) as id,
				itn.f_device_tn as f_device_t,
				null::uuid as f_registr_pts,
				itn.f_registr_pts as f_registr_pts_text,
				true as b_voltage,
				itn.c_serial_number_tn as c_serial_number_t,
				itn.d_replace_before,
				itn.c_device_type_tn as c_device_type_text,
				itn.c_phase,
				itn.n_tt1_tn as n_tt1_t,
				itn.n_tt2_tn as n_tt2_t,
				itn.d_setup_date_tn as d_setup_date_t,
				itn.d_close_date_tn as d_close_date_t,
				row_number() over(partition by itn.f_registr_pts, coalesce(et.id::text, itn.f_device_tn) order by itn.id) as row_num
			from imp.i_tn itn
				inner join t_tu as t 
					on 	t.f_div 		= _f_division 
					and t.f_subdiv 		= _f_subdivision 
					and t.f_registr_pts = itn.f_registr_pts
					and t.f_maindivision_code = itn.f_maindivision_code
				left join dbo.ed_transformers as et 
					on 	LPAD(et.imp_text, 36, '0') 	= LPAD(itn.f_device_tn, 36, '0')
					and et.f_registr_pts = t.id
			where 	1=1
				and length(trim(itn.c_serial_number_tn)) > 0
				and (	itn.g_session_id		= _session_id
					or 	_session_id				is null);

			delete from t_tr where row_num > 1;

			-- привязка к ТУ
			update t_tr tr
			set f_registr_pts = t.id
			from t_tu t 
			where t.f_registr_pts = tr.f_registr_pts_text;
		
			-- Существующие типы трансформаторов
			update t_tr t
			set f_device_type = edt.id
			from dbo.es_device_types edt 
			where edt.c_name = t.c_device_type_t 
				and (edt.n_tt1 = t.n_tt1_t or edt.n_tt1 is null and t.n_tt1_t is null)
				and (edt.n_tt2 = t.n_tt2_t or edt.n_tt2 is null and t.n_tt2_t is null);
			
			-- Определение новых типов транформаторов (5 - ТТ, 6 - ТН)
			with t_tr_types as (
				insert into dbo.es_device_types (f_device_categories, c_name, n_tt1, n_tt2, b_disabled)
				select distinct case t.b_voltage when false then 5 else 6 end as f_device_categories,  c_device_type_t, n_tt1_t, n_tt2_t, false
				from t_tr t
				where not exists (select 1 from dbo.es_device_types edt where edt.c_name = t.c_device_type_t and edt.n_tt1 = t.n_tt1_t and edt.n_tt2 = t.n_tt2_t)
				returning id, f_device_categories, c_name, n_tt1, n_tt2
			)
			update t_tr t
			set f_device_type = trt.id
			from t_tr_types trt
			where 	t.f_device_type is null
				and (trt.c_name = t.c_device_type_t or trt.c_name is null and t.c_device_type_t is null)
				and (trt.n_tt1 = t.n_tt1_t or trt.n_tt1 is null and t.n_tt1_t is null)
				and (trt.n_tt2 = t.n_tt2_t or trt.n_tt2 is null and t.n_tt2_t is null)
				and trt.f_device_categories = case t.b_voltage when false then 5 else 6 end ;
			
			
			--- /*5. Пломбы */ ---
			-- могут приходить в одной строке несколько пломб, разделенных черезх ; 
			-- сохранение одиночных пломб + доп. обработка строк с перечисленными пломбами в одной строке (резделенных через ;)
			
			
			-- т.к. пломбы, типы и расположение могут перечисляться через ; , то раскладываем каждый элемент с номером пломбы, типом и расположением на отдельную строчку
			insert into t_seals(
				id,
				f_registr_pts_text,
				c_seal_number,
				f_seal_type,
				f_seal_location
			)
			select	
					case when a.nr = 1 then es.id else uuid_generate_v4() end as new_id,
					es.f_registr_pts 	as f_registr_pts_text,
					trim(a.elem) c_seal_number,
					coalesce(trim(b.elem) 	, split_part(es.f_seal_type 	 , ';', 1)) as f_seal_type, 		-- если типов перечислено меньше, чем номеров пломб, то берем по-умолчанию первое значение
					coalesce(trim(c.elem) 	, split_part(es.f_seal_location	 , ';', 1)) as f_seal_location 	 	-- если местоположений перечислено меньше, чем номеров пломб, то берем по-умолчанию первое значение
					--row_number() over(partition by es.f_registr_pts, es.c_seal_number, es.c_seal_prefix, es.f_seal_type, es.f_seal_location order by es.id) AS dns_rnk
			from imp.i_seal es
				inner join t_tu as t 
					on 	t.f_div 		= _f_division 
					and t.f_subdiv 		= _f_subdivision 
					and t.f_registr_pts = es.f_registr_pts
					and t.f_maindivision_code = es.f_maindivision_code
				left join lateral unnest(string_to_array(es.c_seal_number, ';')) with ordinality as a(elem, nr) 
					on 	true 
				left join lateral unnest(string_to_array(es.f_seal_type, ';')) with ordinality as b(elem, nr)  
					on	b.nr	= a.nr
				left join lateral unnest(string_to_array(es.f_seal_location, ';')) with ordinality as c(elem, nr)
					on 	c.nr	= a.nr
			where length(c_seal_number) > 0
				and (	es.g_session_id		= _session_id
					or 	_session_id				is null);

			-- только для ЦиП
			-- типы пломб
			--/*
			with cte as (
				select distinct f_seal_type  as c_type from t_seals where f_seal_type is not NULL
			)
			insert into dbo.es_seal_types (c_name, b_default, b_disabled)
			select c_type, false, false
			from cte cd
			where not exists (
				select 1 
				from dbo.es_seal_types st 
				where 	st.c_name = cd.c_type 
					OR 	st.n_code = case when cd.c_type ~ '^[0-9\.]+$' = true then cd.c_type::float::integer end 

				);
			--*/
		
			
			-- привязка типов пломб		
			update t_seals es0
			set f_type = (
							select t.id
							from dbo.es_seal_types t
							where 	(
									t.n_code = case when es0.f_seal_type ~ '^[0-9\.]+$' = true then es0.f_seal_type::float::integer end
								or 	t.c_const = es0.f_seal_type
								or 	t.c_name = es0.f_seal_type)
								and not t.b_disabled 
							order by t.id desc
							limit 1
							)
			where 	es0.f_seal_type is not null;

			-- только для ЦиП пока
			-- типы расположения пломб
			--/*
			with cte as (
				select distinct f_seal_location  as c_place from t_seals where f_seal_location is not NULL
			)
			insert into dbo.es_seal_places (c_name, b_default, b_disabled)
			select c_place, false, false
			from cte cd
			where not exists (
				select 1 
				from dbo.es_seal_places st 
				where 	st.c_name = cd.c_place 
					or 	st.n_code = case when cd.c_place ~ '^[0-9\.]+$' = true then cd.c_place::float::integer end );
			--*/

			-- привязка расположения пломб		
			update t_seals es0
			set f_place = (
							select t.id
							from dbo.es_seal_places t
							where 	
									(t.n_code = case when es0.f_seal_location ~ '^[0-9\.]+$' = true then es0.f_seal_location::float::integer end
								or 	t.c_const = es0.f_seal_location
								or 	t.c_name = es0.f_seal_location)
								and not t.b_disabled 
							order by t.id desc
							limit 1
							)
			where 	es0.f_seal_location is not null;
			
			-- привязка к ТУ
			update t_seals t
			set f_registr_pts = tu.id
			from t_tu tu
			where tu.f_registr_pts = f_registr_pts_text ;
			
			-- привязка к существующим пломбам
			update t_seals t
			set id = ess.id
			from dbo.ed_seals as ess
				left join dbo.es_seal_types as est
					on 	est.b_default
				left join dbo.es_seal_places as esp
					on 	esp.b_default
			where 1=1
				and	ess.f_registr_pts 	= t.f_registr_pts
				and ess.c_number 	 	= t.c_seal_number
				and coalesce(ess.f_type, est.id) 		= coalesce(t.f_type, est.id)
				and coalesce(ess.f_place, esp.id) 		= coalesce(t.f_place, esp.id);

			delete from t_seals
			where id in 
			(
				select id
				from 
				(
					select t.id, row_number() over(partition by t.id) as n_row
					from t_seals as t
				) as t
				where n_row > 1
			);



			--- /*6. Показания */ ---
			insert into t_readings(
				id,
				f_registr_pts_text,
				f_energy_type,
				f_time_zone,
				f_scale,
				d_date,
				n_value,
				f_delivery_methods
			)
			select
				uuid_generate_v4(),
				ir.f_registr_pts as f_registr_pts_text,
				ir.f_energy_type,
				ir.f_time_zone,
				ir.f_scale,
				ir.d_date,
				ir.n_value,
				ir.f_delivery_methods
			from imp.i_readings ir 
				inner join t_tu as t 
					on 	t.f_div 		= _f_division
					and t.f_subdiv 		= _f_subdivision
					and t.f_registr_pts = ir.f_registr_pts
					and t.f_maindivision_code = ir.f_maindivision_code
			where 	1=1
				and (	ir.g_session_id		= _session_id
					or 	_session_id				is null);

			-- контрольные показания
			insert into t_readings(
				id,
				f_registr_pts_text,
				f_energy_type,
				f_time_zone,
				f_scale,
				d_date,
				n_value,
				f_delivery_methods
			)
			select
				uuid_generate_v4(),
				ir.f_registr_pts as f_registr_pts_text,
				ir.f_energy_type,
				ir.f_time_zone,
				ir.f_scale,
				ir.d_date2,
				ir.n_value2,
				2
			from imp.i_readings ir 
				inner join t_tu as t 
					on 	t.f_div 		= _f_division
					and t.f_subdiv 		= _f_subdivision
					and t.f_registr_pts = ir.f_registr_pts 
					and t.f_maindivision_code = ir.f_maindivision_code
			where 	1=1
				and (	ir.g_session_id		= _session_id
					or 	_session_id				is null)
				and ir.d_date2 is not null
				and ir.n_value2 is not null;

			-- TODO: переделать, дичь какая-то
			update t_readings t
			set f_scale = coalesce(es.id, esC.id, esS.id, esD.id)
			from t_readings tt 
				-- по названию
				left join dbo.es_scales as es 
					on lower(trim(tt.f_time_zone)) 	= lower(trim(es.c_name))
				-- по коду
				left join dbo.es_scales as esC 
					on esC.id = case when tt.f_time_zone ~ '^[0-9\.]+$' = true then tt.f_time_zone::float::integer end
				-- по коду САП
				left join dbo.es_scales as esS
					on esS.c_code_out 	= tt.f_time_zone
				inner join dbo.es_scales as esD
				 	on 	esD.b_default 	= true
			where tt.id = t.id;

			update t_readings t
			set f_time_zone = coalesce(etz.id, 1)
			from t_readings tt 
				left join dbo.es_tariff_zones as etz 
					on etz.id 	= case when tt.f_time_zone ~ '^[0-9\.]+$' = true then tt.f_time_zone::float::integer else 1 end
			where tt.id = t.id;

			update t_readings t
			set f_energy_type = coalesce(eet.id, eetC.id, eetD.id)
			from t_readings tt 
				-- по названию
				left join dbo.es_energy_types as eet 
					on 	eet.c_name = tt.f_energy_type
				-- по константе
				left join dbo.es_energy_types as eetC
					on 	eetC.c_const = tt.f_energy_type
				inner join dbo.es_energy_types as eetD
					on 	eetD.b_default = true
			where tt.id = t.id;

			update t_readings t
			set f_delivery_methods = coalesce(edm.id, edmm.id, edmD.id)
			from t_readings tt 
				left join dbo.es_delivery_methods as edm
					on 	lower(tt.f_delivery_methods) like '%' || lower(edm.c_name) || '%'
				left join dbo.es_delivery_methods as edmm
					on 	edmm.id 	= case when tt.f_delivery_methods ~ '^[0-9\.]+$' = true then tt.f_delivery_methods::float::integer end
				inner join dbo.es_delivery_methods as edmD
					on 	edmD.b_default = true
			where tt.id = t.id;
			
			update t_readings r 
			set f_registr_pts = t.id
			from t_tu t 
			where t.f_registr_pts = r.f_registr_pts_text;
		
			update t_readings r 
			set id = imr.id
			from dbo.ed_input_meter_readings AS imr
			where 1=1
				and imr.f_registr_pts 		= r.f_registr_pts
				and imr.d_date_prev 		= r.d_date
				and imr.f_scale::text 		= r.f_scale
				and imr.f_energy_type::text = r.f_energy_type;

			delete from t_readings
			where id in 
			(
				select id
				from 
				(
					select t.id, row_number() over(partition by t.id) as n_row
					from t_readings as t
				) as t
				where n_row > 1
			);

			-- типы энергий
			-- типы методов доставки
			-- шкалы?

			-- адреса
			begin 
				
				-- Отбор адресов и генерация уидентификаторов для уникальных строк
				insert into t_address(
					id,
					f_address,
				    row_num,
					f_registr_pts,
					f_kladr,
					c_name,
					c_index,
					--c_region,
					c_raion,
					c_сity_name,
					c_settlement_name,
					c_street_name,
					c_house_name,
					c_block_name,
					c_flat_name,
					n_geo_lat,
					n_geo_lon,
					f_conn_points,
					c_name_obj
				)
				select
					uuid_generate_v4() as id,
					erp.f_address as f_address,
					row_number() over (partition by iau.c_address, iau.c_building_corp , iau.c_premise_number order by iau.f_registr_pts) as row_num,
					iau.f_registr_pts,
					coalesce(nullif(trim(iau.f_kladr), ''), iau.f_conn_points, iau.f_registr_pts) as f_kladr,
					coalesce(nullif(trim(iau.c_address), ''), iau.c_premise_name) as c_name,
					iau.c_index,
					iau.c_province,
					--iau.f_region,
					iau.c_town,
					iau.c_municipality,
					iau.c_street,
					iau.c_building_num,
					iau.c_building_corp,
					iau.c_premise_number,
					iau.c_latitude,
					iau.c_longitude,
					iau.f_conn_points,
					iau.c_name_obj
				from imp.i_addr_ul iau 
					inner join t_tu as t 
						on 	t.f_div 		= _f_division
						and t.f_subdiv 		= _f_subdivision
						and t.f_registr_pts = iau.f_registr_pts
						and t.f_maindivision_code = iau.f_maindivision_code
					left join dbo.ed_registr_pts as erp
						on erp.id 			= t.id
				where 	1=1
					--and length(c_address) > 0
					and (iau.g_session_id = _session_id or _session_id is null);

				insert into t_address(
					id,
					f_address,
				    row_num,
					f_registr_pts,
					f_kladr,
					c_name,
					c_index,
					--c_region,
					c_raion,
					c_сity_name,
					c_settlement_name,
					c_street_name,
					c_house_name,
					c_block_name,
					c_flat_name,
					n_geo_lat,
					n_geo_lon,
					f_conn_points,
					c_name_obj
				)
				select
					uuid_generate_v4() as id,
					erp.f_address as f_address,
					row_number() over (partition by iau.c_address, iau.c_building_corp , iau.c_premise_number order by iau.f_registr_pts) as row_num,
					iau.f_registr_pts,
					coalesce(nullif(trim(iau.f_kladr), ''), iau.f_conn_points, iau.f_registr_pts) as f_kladr,
					coalesce(nullif(trim(iau.c_address), ''), iau.c_premise_name) as c_name,
					iau.c_index,
					iau.c_province,
					--iau.f_region,
					iau.c_town,
					iau.c_municipality,
					iau.c_street,
					iau.c_building_num,
					iau.c_building_corp,
					iau.c_premise_number,
					iau.c_latitude,
					iau.c_longitude,
					iau.f_conn_points,
					iau.c_name_obj
				from imp.i_addr_fl as iau
					inner join t_tu as t 
						on 	t.f_div 		= _f_division
						and t.f_subdiv 		= _f_subdivision
						and t.f_registr_pts = iau.f_registr_pts
						and t.f_maindivision_code = iau.f_maindivision_code
					left join dbo.ed_registr_pts as erp
						on erp.id 			= t.id
				where 	1=1
					--and length(c_address) > 0
					and (	iau.g_session_id = _session_id 
						or 	_session_id is null);

				delete from t_address where coalesce(c_name, '') = '';



				-- ранжирование
				update t_address as t0
				set dns_rnk = tt.dns_rnk
				from t_address as t 
					inner join 
					(
						select 
							t.id,
							dense_rank() over (order by t.c_name, t.c_block_name , t.c_flat_name, f_kladr) as dns_rnk	
						from t_address as t
					) as tt 
						on 	tt.id = t.id
				where t.id = t0.id
					;

				with f_addr_uniq as (
					select dns_rnk, uuid_generate_v4() as f_address -- уникальный адрес
					from (
						select distinct 
							dns_rnk
						from t_address t
						where  t.f_address is null
						) as t
				)
				update t_address ta
				set f_address = t.f_address
				from f_addr_uniq t
				where ta.dns_rnk = t.dns_rnk
					and ta.f_address is null;
				
				--delete from t_address where row_num > 1;

			end;

		
			--- /*ФИНАЛ. Вставка/апдейт в реальные таблицы */ ---
			-- 1. select * from t_subscr	-- КА
			-- 2. select * from t_tu		-- ТУ
			-- 3. select * from t_pu		-- ПУ
			-- 4. select * from t_tr		-- Трансформаторы
			-- 5. select * from t_seals		-- Пломбы
			-- 6. select * from t_readings	-- Показания
			
			_count_subscr 	:= _count_subscr 	+ (SELECT COUNT(*) from t_subscr);
			_count_tu 		:= _count_tu 		+ (SELECT COUNT(*) from t_tu);
			_count_pu 		:= _count_pu		+ (SELECT COUNT(*) from t_pu);
			_count_tr 		:= _count_tr		+ (SELECT COUNT(*) from t_tr);
			_count_seals 	:= _count_seals		+ (SELECT COUNT(*) from t_seals);
			_count_readings := _count_readings	+ (SELECT COUNT(*) from t_readings);
			_count_address	:= _count_address	+ (SELECT COUNT(*) from t_address);

			-- 2. select * from t_tu		-- ТУ
			-- 3. select * from t_pu		-- ПУ
			-- 4. select * from t_tr		-- Трансформаторы
			-- 5. select * from t_seals		-- Пломбы
			-- 6. select * from t_readings	-- Показания
			
			
		
		

		
		-- вставка данных в реальные таблицы
		perform dbo.cf_process_imp_insert();
		
				-- обработка ошибок
		exception
			when others then				
				GET STACKED DIAGNOSTICS _message_text = MESSAGE_TEXT;


		end;

		

		_endTime := clock_timestamp();
  		_delta := 1000 * ( extract(epoch from _endTime) - extract(epoch from _startTime) );
  		RAISE NOTICE 'время=%', _delta;

		-- и по завершению очищаем
		truncate table t_tu;
		truncate table t_subscr;
		truncate table t_pu;
		truncate table t_pu_type;
		truncate table t_tr;
		truncate table t_seals;
		truncate table t_readings;
		truncate table t_address;
		
	
	end loop;

	if _message_text is not null then 
		
		update imp.i_integration_sessions
			set status 		= concat(status || ',', 'TransferFail'),
				parameters 	= concat(parameters, '. Текст ошибки: ', _message_text)
		where sessionid = _session_id;

		RAISE NOTICE '%', _message_text;

	end if;

	raise notice 'подготовлено ЛС %, подготовлено ТУ %, подготовлено ПУ %, подготовлено трансформаторов %, подготовлено пломб %, подготовлено показаний %, подготовлено адресов %', _count_subscr, _count_tu, _count_pu, _count_tr, _count_seals, _count_readings, _count_address;

	return 0;	-- ОК
	
END;

Function: dbo.cf_process_imp_insert()

Returns: integer

Language: PLPGSQL

Вставка результатов обработки буферов импорта


DECLARE

	_inserted_subscr 	int = 0;		-- кол-во вставленных ЛС
	_inserted_tu 		int = 0;		-- кол-во вставленных ТУ
	_inserted_pu 		int = 0;		-- кол-во вставленных ПУ
	_inserted_tr 		int = 0;		-- кол-во вставленных Трансформаторов
	_inserted_seals 	int = 0;		-- кол-во вставленных Пломб
	_inserted_readings	int = 0;		-- кол-во вставленных Показаний
	_inserted_address 	int = 0;		-- кол-во адресов

BEGIN
		
		INSERT INTO dbo.sd_subscr
		(	id, 
			f_division, 
			f_subdivision, 
			c_code, 
			c_name1, 
			c_name2, 
			c_name3, 
			c_telephone, 
			b_problem_person, 
			b_person, 
			n_check_date,
			f_partners
			)
		select 
			ts.id,
	    	ts.f_division,
	    	ts.f_subdivision,
	    	max(ts.c_code),
	    	max(ts.c_name1), 
			max(ts.c_name2), 
			max(ts.c_name3), 
			max(ts.c_telephone), 
			false as b_problem_person,
			max(ts.b_person::int4)::bool,
			max(ts.f_check_date),
			max(ts.f_partners)
		from t_subscr as ts
		group by 
			ts.id,
	    	ts.f_division,
	    	ts.f_subdivision
		
		on conflict on CONSTRAINT sd_subscr_pkey
		do update 
			set 
				c_code		= excluded.c_code,
	    		c_name1		= excluded.c_name1, 
				c_name2		= excluded.c_name2, 
				c_name3		= excluded.c_name3, 
				c_telephone = excluded.c_telephone, 
				b_problem_person = false,
				b_person 	= excluded.b_person,
				n_check_date= excluded.n_check_date,
				f_partners  = excluded.f_partners
		;

		GET DIAGNOSTICS _inserted_subscr = ROW_COUNT;

		INSERT INTO dbo.ed_registr_pts
		(
			id, 
			f_division, 
			f_subdivision, 
			b_disabled, 
			c_registr_pts, 
			f_status_consume, 
			b_technical_metering, 
			c_substation, 
			c_line_substation, 
			--c_rp, 
			--c_line_rp, 
			c_tp, 
			c_line_tp, 
			c_line_segment, 
			--f_violation, 
			--d_violation_date, 
			--d_date_before, 
			f_subscr, 
			--f_address, 
			--f_subscr_int, 
			--f_device_int, 
			--imp_int, 
			c_line_tp_1, 
			--c_line_segment_1, 
			imp_text, 
			d_close_date, 
			c_status_registr_pts, 
			f_registr_pts_status,
			c_status, 
			c_predictr,
			d_restriction_date,
			c_restriction_method,
			c_network_pts_code,
			n_max_cap,
			b_sub,
			b_transit
		)
		SELECT 
			tt.id,
			tt.f_div,
			tt.f_subdiv,
			false as b_disabled,
			tt.c_registr_pts,
			tt.c_status_consume::integer as f_status_consume,
			tt.b_technical_metering::bool,
			tt.c_substation,
			tt.c_line_substation,
			tt.c_tp,
			tt.c_line_tp,
			tt.c_line_segment,
			ts.id as f_subscr,
			tt.c_line_tp_1,
			tt.f_registr_pts,
			tt.d_close_date,
			tt.c_status_registr_pts,
			case when tt.c_status_registr_pts ~ '^[0-9\.]+$' = true then tt.c_status_registr_pts::float::integer end as f_registr_pts_status,
			tt.c_status,
			tt.c_predictr,
			tt.d_restriction_date,
			tt.c_restriction_method,
			tt.c_network_pts_code,
			tt.n_max_cap,
			tt.b_sub,
			tt.b_transit
		FROM t_tu as tt
			inner join t_subscr AS ts
				on ts.f_registr_pts = tt.id
		
		on conflict on CONSTRAINT ed_registr_pts_pkey
		do update 
			set 
				c_registr_pts 			= excluded.c_registr_pts,
				f_status_consume 		= excluded.f_status_consume,
				b_technical_metering 	= excluded.b_technical_metering,
				c_substation 			= excluded.c_substation,
				c_line_substation 		= excluded.c_line_substation,
				c_tp 					= excluded.c_tp,
				c_line_tp 				= excluded.c_line_tp,
				c_line_segment 			= excluded.c_line_segment,
				c_line_tp_1 			= excluded.c_line_tp_1,
				d_close_date 			= excluded.d_close_date,
				c_status_registr_pts 	= excluded.c_status_registr_pts,
				f_registr_pts_status 	= excluded.f_registr_pts_status,
				c_status 				= excluded.c_status,
				c_predictr 				= excluded.c_predictr,
				d_restriction_date 		= excluded.d_restriction_date,
				c_restriction_method 	= excluded.c_restriction_method,
				c_network_pts_code 		= excluded.c_network_pts_code,
				n_max_cap 				= excluded.n_max_cap,
				b_sub 					= excluded.b_sub,
				b_transit				= excluded.b_transit
		;

		GET DIAGNOSTICS _inserted_tu = ROW_COUNT;

		INSERT INTO dbo.ed_devices
		(	
			id, 
			--link, 
			f_device_type, 
			c_serial_number, 
			--n_rate, 
			--n_manufacture_year, 
			d_setup_date, 
			--d_valid_date, 
			--f_device_location, 
			--f_owner_type, 
			--n_owner_type, 
			c_device_location, 
			--imp_int, 
			f_registr_pts, 
			imp_text, 
			b_askue, 
			d_close_date
		)
		select distinct
			tp.id,
	    	tp.f_device_type,
	    	tp.c_serial_number,
	    	tp.d_setup_date,
	    	tp.f_device_location_type,
	    	tp.f_registr_pts,
	    	tp.f_device,
	    	tp.b_askue,
	    	tp.d_close_date
		from t_pu as tp
		
		on conflict on CONSTRAINT imp_ed_devices_pkey
		do update 
			set 
				f_device_type 		= excluded.f_device_type,
	    		c_serial_number 	= excluded.c_serial_number,
	    		d_setup_date 		= excluded.d_setup_date,
	    		c_device_location 	= excluded.c_device_location,
	    		b_askue 			= excluded.b_askue,
	    		d_close_date 		= excluded.d_close_date
		;

	    GET DIAGNOSTICS _inserted_pu = ROW_COUNT;

	    update dbo.ed_devices 
		set 
			d_close_date = now()
		where id in (
				select 
					ed.id
				from dbo.ed_devices ed 
					-- по точке учета есть прибор
					inner join (select f_registr_pts from t_pu group by f_registr_pts) as tt
						on 	tt.f_registr_pts 		= ed.f_registr_pts
					-- все приборы которые не вставляются сейчас
					left join t_pu as t 
						on 	t.f_registr_pts 		= ed.f_registr_pts
						and t.id 					= ed.id
				where 	ed.d_close_date 	is NULL
					and t.id 				is NULL
			);

		INSERT INTO dbo.ed_transformers
		(
			id, 
			f_registr_pts, 
			b_voltage, 
			c_serial_number, 
			d_replace_before, 
			c_phase, 
			--imp_int, 
			--n_manufacture_year, 
			--d_check_date, 
			d_replace_date, 
			imp_text, 
			f_device_type
		)
		SELECT distinct
			tt.id,
			tt.f_registr_pts,
			tt.b_voltage,
			tt.c_serial_number_t,
			tt.d_replace_before,
			tt.c_phase,
			tt.d_close_date_t,
			tt.f_device_t,
			tt.f_device_type
		from t_tr as tt
		
		on conflict on CONSTRAINT ed_transformers_pkey
		do update 
			set 
				b_voltage 		= excluded.b_voltage,
				c_serial_number = excluded.c_serial_number,
				d_replace_before= excluded.d_replace_before,
				c_phase 		= excluded.c_phase,
				d_replace_date 	= excluded.d_replace_date,
				f_device_type 	= excluded.f_device_type
		;

		GET DIAGNOSTICS _inserted_tr = ROW_COUNT;

		INSERT INTO dbo.ed_seals
		(
			id, 
			c_number, 
			f_status,
			--f_user, 
			f_registr_pts, 
			c_prefix, 
			--imp_int, 
			--d_replace_date, 
			--b_draft, 
			--n_order, 
			--jb_history, 
			f_type, 
			f_place
		)
		select
			ts.id,
			ts.c_seal_number,
			est.id as f_status,
			ts.f_registr_pts,
			ts.c_seal_prefix,
			--ts.f_seal,
			ts.f_type,
			ts.f_place
		from t_seals AS ts
			inner join dbo.es_seal_status as est 
				on 	est.c_const 	= 'REG'
		
		on conflict on constraint ed_seals_pkey
		do update 
			set 
				c_prefix 		= excluded.c_prefix,
				f_place 		= excluded.f_place
		;

		GET DIAGNOSTICS _inserted_seals = ROW_COUNT;

		-- показания
		insert into dbo.ed_input_meter_readings
		(
			id, 
			n_value_prev, 
			d_date_prev, 
			--n_digit, 
			f_scale, 
			f_registr_pts, 
			f_tariff_zone, 
			f_energy_type, 
			f_delivery_method
		)
		SELECT 
			tr.id,
			tr.n_value,
			tr.d_date,
			case when tr.f_scale ~ '^[0-9\.]+$' = true then tr.f_scale::integer else 2 end,
			tr.f_registr_pts,
			case when tr.f_time_zone   ~ '^[0-9\.]+$' = true then tr.f_time_zone::integer else 1 end,
			case when tr.f_energy_type ~ '^[0-9\.]+$' = true then tr.f_energy_type::integer else 2 end,
			case when tr.f_delivery_methods ~ '^[0-9\.]+$' = true then tr.f_delivery_methods::integer else 1 end
		from t_readings AS tr
		on conflict on constraint ed_input_meter_readings_pkey
		do update 
			set 
				n_value_prev 		= excluded.n_value_prev,
				f_delivery_method 	= excluded.f_delivery_method;
		
		GET DIAGNOSTICS _inserted_readings = ROW_COUNT;

		--модификация старых показаний 
		update dbo.ed_input_meter_readings as emr0
		set jb_sources = json_build_object(	'f_delivery_method'			, emrSubscr.f_delivery_method, 
											'c_delivery_method_name' 	, emrSubscr.c_delivery_method_name, 
											'n_value' 					, emrSubscr.n_value, 
											'd_date' 					, emrSubscr.d_date, 
											'f_scale' 					, emrSubscr.f_scale, 
											'c_scale' 					, emrSubscr.c_scale
										)
		from t_tu as t
			inner join 
			(	-- последнее контрольное показание
				select 
					emr.id,
					emr.f_registr_pts,
					emr.f_energy_type,
					emr.f_scale,
					row_number () over (partition by emr.f_registr_pts, emr.f_energy_type, emr.f_scale order by emr.d_date_prev desc, emr.id) as n_row
				from dbo.ed_input_meter_readings as emr
					inner join t_tu as tt 
						on 	tt.id 		= emr.f_registr_pts
					inner join dbo.es_delivery_methods as edm
						on 	edm.id 		= emr.f_delivery_method
						and edm.c_const = 'EDM_Check' 	-- контрольное показание
				where emr.d_replace_date is null
			) as emrCheck
				on 	emrCheck.f_registr_pts = t.id
			-- последнее потребительское показание
			inner join 
			(
				select 
					emr.id,
					emr.f_registr_pts,
					emr.f_energy_type,
					edm.id 				as f_delivery_method,
					edm.c_name 			as c_delivery_method_name,
					emr.n_value_prev 	as n_value,
					emr.d_date_prev 	as d_date,
					emr.f_scale 		as f_scale,
					es.c_name 			as c_scale,
					row_number () over (partition by emr.f_registr_pts, emr.f_energy_type, emr.f_scale order by emr.d_date_prev desc, emr.id) as n_row
				from dbo.ed_input_meter_readings as emr
					inner join t_tu as tt 
						on 	tt.id 		= emr.f_registr_pts
					inner join dbo.es_scales as es
						on 	es.id 		= emr.f_scale
					left join dbo.es_delivery_methods as edm
						on 	edm.id 		= emr.f_delivery_method
				where 	1=1
					and coalesce(edm.c_const, 'EDM_Subscr') = 'EDM_Subscr' 	-- потребительское показание
			) as emrSubscr
				on 	emrSubscr.f_registr_pts 	= emrCheck.f_registr_pts
				and emrSubscr.f_energy_type 	= emrCheck.f_energy_type
				and emrSubscr.f_scale 			= emrCheck.f_scale
		where 1=1
			and emrSubscr.n_row 			= 1
			and emrCheck.n_row 				= 1
			and emrCheck.id 				= emr0.id;
		

		-- все непоследние показания перевести в замененные
		update dbo.ed_input_meter_readings as emr0
		set  d_replace_date = coalesce(emr.d_date_prev, now()::date)
		from t_tu as t
			inner join 
			(	-- последнее контрольное показание
				select 
					emr.id, emr.f_registr_pts, emr.d_replace_date,
					lag(emr.d_date_prev) over(
											partition by 
													emr.f_registr_pts, 
													emr.f_energy_type, 
													emr.f_scale 
											order by emr.d_date_prev desc
					) as d_date_prev,	-- дата следующего показания
					row_number () over (	partition by 
													emr.f_registr_pts, 
													emr.f_energy_type, 
													emr.f_scale 
											order by coalesce(edm.id, 1) desc, 
													emr.d_date_prev desc,
													emr.id
					) as n_row -- вычисление последнего показания
				from dbo.ed_input_meter_readings as emr
					inner join t_tu as tt 
						on 	tt.id 		= emr.f_registr_pts
					left join dbo.es_delivery_methods as edm
						on 	edm.id 		= emr.f_delivery_method
			) as emr
				on 	emr.f_registr_pts = t.id
		where 	emr.n_row 			> 1		-- все кроме последнего
			and emr.d_replace_date 	is null -- с незаполненной датой замены
			and emr.id 				= emr0.id
			;


		-- адреса
		insert into dbo.ss_address (
			id,
			c_name,
			c_index,
			c_region,
			c_raion,
			c_city_name,
			c_settlement_name,
			c_street_name,
			c_house_name,
			c_block_name,
			c_flat_name,
			n_geo_lat,
			n_geo_lon,
			imp_text,
			f_conn_points,
			c_name_obj
		)
		select distinct
			f_address,
			c_name,
			c_index,
			c_region,
			c_raion,
			c_сity_name,
			c_settlement_name,
			c_street_name,
			c_house_name,
			c_block_name,
			c_flat_name,
			n_geo_lat,
			n_geo_lon,
			f_kladr,
			f_conn_points,
			c_name_obj
		from (
			select 
				row_number() over(partition by ta.f_address) as n_row,
				* 
			from t_address AS ta
			)as ta
		where ta.n_row = 1
		on conflict on constraint ss_address_pkey
		do update 
			set 
				c_index				= COALESCE(NULLIF(dbo.ss_address.c_index			, ''), excluded.c_index				)	,
				c_region			= COALESCE(NULLIF(dbo.ss_address.c_region			, ''), excluded.c_region			)	,
				c_raion				= COALESCE(NULLIF(dbo.ss_address.c_raion			, ''), excluded.c_raion				)	,
				c_city_name			= COALESCE(NULLIF(dbo.ss_address.c_city_name		, ''), excluded.c_city_name			)	,
				c_settlement_name	= COALESCE(NULLIF(dbo.ss_address.c_settlement_name	, ''), excluded.c_settlement_name	)	,
				c_street_name		= COALESCE(NULLIF(dbo.ss_address.c_street_name		, ''), excluded.c_street_name		)	,
				c_house_name		= COALESCE(NULLIF(dbo.ss_address.c_house_name		, ''), excluded.c_house_name		)	,
				c_block_name		= COALESCE(NULLIF(dbo.ss_address.c_block_name		, ''), excluded.c_block_name		)	,
				c_flat_name			= COALESCE(NULLIF(dbo.ss_address.c_flat_name		, ''), excluded.c_flat_name			)	,
				n_geo_lat			= COALESCE(NULLIF(dbo.ss_address.n_geo_lat			, 0 ), excluded.n_geo_lat			)	,
				n_geo_lon			= COALESCE(NULLIF(dbo.ss_address.n_geo_lon			, 0 ), excluded.n_geo_lon			)	,
				f_conn_points		= COALESCE(NULLIF(dbo.ss_address.f_conn_points		, ''), excluded.f_conn_points		)	,
				c_name_obj			= COALESCE(NULLIF(dbo.ss_address.c_name_obj			, ''), excluded.c_name_obj			)	,
				b_dadata 			= false
			where dbo.ss_address.c_name != excluded.c_name;

		GET DIAGNOSTICS _inserted_address = ROW_COUNT;

		-- указание на адрес в ТУ
		update dbo.ed_registr_pts rp
		set f_address = ta.f_address
		from t_tu as rpp
			inner join t_address as ta
				on 	rpp.f_registr_pts = ta.f_registr_pts
		where rpp.id = rp.id
			and (rp.f_address <> ta.f_address or rp.f_address is null);
			
		raise notice 'вставлено ЛС %, вставлено ТУ %, вставлено ПУ %, вставлено трансформаторов %, вставлено пломб %, вставлено показаний %, вставлено адресов %', _inserted_subscr, _inserted_tu, _inserted_pu, _inserted_tr, _inserted_seals, _inserted_readings, _inserted_address;

	return 0;	-- ОК
	
END;

Function: dbo.cft_ed_blank_update()

Returns: trigger

Language: PLPGSQL

Триггер. Обновление истории бланков

BEGIN
    IF (TG_OP = 'UPDATE') THEN
		UPDATE dbo.ed_blanks as b
		set jb_history = dbo.sf_update_jb_history(jb_history, json_build_object('f_user_to', b.f_user_to,
																				'd_date_to', now(),
																				'f_status', b.f_status)) 
		where b.id = NEW.id;
    END IF;

    RETURN NEW;
END

Function: dbo.cft_ed_seal_update()

Returns: trigger

Language: PLPGSQL

Триггер. Обновление истории пломбы

BEGIN
    IF (TG_OP = 'UPDATE' or TG_OP = 'INSERT') THEN
		UPDATE dbo.ed_seals as s
		set jb_history = dbo.sf_update_jb_history(s.jb_history, json_build_object('f_user_to', s.f_user_to,
																				'f_user_from', s.f_user_from,
																				'd_date_to', now(),
																				'f_status', s.f_status))
		where s.id = NEW.id;
    END IF;

    RETURN NEW;
END

Function: dbo.rpt_arm_cd_route_stat(_f_route uuid)

Returns: SET OF record

Language: PLPGSQL

Получение статистики по маршруту

/**
* @param {uuid} _f_route - иден. маршрута
*
* @example
* [{ "action": "rpt_arm_cd_route_stat", "method": "Select", "data": [{ "params": [_f_route] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_n_all_points bigint; -- общее количество точек
	_n_done_points bigint; -- количество пройденных точек
BEGIN
	select DISTINCT count(fn_point) into _n_done_points from core.cd_user_points as p where p.fn_route = _f_route;
	select count(*) into _n_all_points from core.cd_points as p where p.f_route = _f_route;

	RETURN QUERY select 
		u.id,
		u.c_login,
		u.c_first_name,
		u.c_last_name,
		u.c_middle_name,
		uir.b_main,
		_n_all_points as n_all_points,
		(select DISTINCT count(fn_point) from core.cd_user_points as p where p.fn_route = _f_route and p.fn_user = u.id) as n_done_points,
		_n_all_points - _n_done_points as n_need_points
	from core.cd_userinroutes as uir
	inner join core.pd_users as u ON u.id = uir.f_user
	where uir.f_route = _f_route
	order by uir.b_main DESC;
END

Function: dbo.sf_generate_meter_reading(_f_result uuid)

Returns: integer

Language: PLPGSQL

Создание показаний для акта замены ПУ

/**
* Выполняется только после установки предыдущих показаний в d_replace_date
*
* @params {uuid} _f_result - результат с актом замены ПУ
*
* @returns {integer} 0 - запись создана
*
* @example
* [{ "action": "sf_generate_meter_reading", "method": "Query", "data": [{ "params": [_f_result] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_n_count_scale integer; -- количество шкал по тарифу
	_c_result_type text; -- тип создаваемого результата
	_f_registr_pts uuid; -- точка учета
	_meters json; -- показания
BEGIN
	-- нужно определить количество шкал для обработки
	select tz.n_count_scale, rt.c_const, p.f_registr_pts into _n_count_scale, _c_result_type, _f_registr_pts 
	from core.cd_results as r
	inner join core.cd_points as p ON p.id = r.fn_point
	inner join core.cs_result_types as rt ON rt.id = r.fn_type
	inner join dbo.es_tariff_zones as tz ON tz.id = (r.jb_data #>> '{f_tariff_zone}')::integer
	where r.id = _f_result;
	
	IF _c_result_type = 'AZPU' OR _c_result_type = 'ADEPU' THEN
		IF _n_count_scale = 1 THEN -- Сутки
		
			select array_to_json(array_agg(row_to_json(t))) into _meters
			from (
				select (r.jb_data #>> '{n_scale1}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_Day') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
			) as t;
			
		ELSIF _n_count_scale = 2 THEN -- День, Ночь
		
			select array_to_json(array_agg(row_to_json(t))) into _meters
			from (
				select (r.jb_data #>> '{n_scale1}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_DayTime') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
				UNION ALL
				select (r.jb_data #>> '{n_scale2}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_Nigth') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
			) as t;
			
		ELSIF _n_count_scale = 3 THEN -- Ночь, Пик, Полупик
		
			select array_to_json(array_agg(row_to_json(t))) into _meters
			from (
				select (r.jb_data #>> '{n_scale1}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_Nigth') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
				UNION ALL
				select (r.jb_data #>> '{n_scale2}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_Peak') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
				UNION ALL
				select (r.jb_data #>> '{n_scale3}')::numeric as n_scale, r.d_date, dt.n_digits, (select id from dbo.es_scales where c_const = 'TFZ_SemiPeak') as f_scale, _f_registr_pts as f_registr_pts, (r.jb_data #>> '{f_tariff_zone}')::integer as f_tariff_zone, 1 as f_energy_type, 2 as f_delivery_method
				from core.cd_results as r
				inner join core.cs_result_types as rt ON rt.id = r.fn_type
				inner join dbo.es_device_types as dt ON dt.id = (r.jb_data #>> '{f_device_model}')::integer
				where r.id = _f_result
			) as t;
			
		ELSE
			RETURN 2; -- не удалось определить количество шкал
		END IF;
		
		--raise notice '%', _meters;
		
		-- добавляем показания
		INSERT INTO dbo.ed_input_meter_readings(n_value_prev, d_date_prev, n_digit, f_scale, f_registr_pts, f_tariff_zone, f_energy_type, f_delivery_method)
		select (t.value #>> '{n_scale}')::numeric, (t.value #>> '{d_date}')::timestamp with time zone, (t.value #>> '{n_digits}')::numeric, (t.value #>> '{f_scale}')::integer, (t.value #>> '{f_registr_pts}')::uuid, (t.value #>> '{f_tariff_zone}')::integer, (t.value #>> '{f_energy_type}')::integer, (t.value #>> '{f_delivery_method}')::integer
		from json_array_elements(_meters::json) as t;
		
	ELSE
		RETURN 1; -- результат не является актом замены ПУ
	END IF;
	
	RETURN 0;
END

Function: dbo.sf_generate_point_info(_f_registr_pts uuid)

Returns: text

Language: PLPGSQL

Генерация информации для точки учета

/**
* @params {uuid} _f_registr_pts - идентификатор точки учета
*
* @returns {jsonb}
*
* @example
* [{ "action": "sf_generate_point_info", "method": "Query", "data": [{ "params": [_f_registr_pts] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_c_seals_info text;
	_c_transformers_info text;
	_c_meter_readings text;
BEGIN
	IF (select count(*) from dbo.ed_registr_pts as rp where rp.id = _f_registr_pts) = 1 THEN
		
		select string_agg(concat(
			'<div><b>Тип</b>: ', st.c_name, '<br />', 
			'<b>Номер</b>: ', coalesce(s.c_number, concat(s.c_prefix, s.n_number::text)), '<br />', 
			'<b>Место установки</b>: ', s.c_location, '</div>'), '' order by s.c_type, s.c_location) into _c_seals_info 
		from dbo.ed_seals as s
		left join dbo.es_seal_types as st ON s.f_type = st.id
		where s.f_registr_pts = _f_registr_pts and s.d_replace_date is null;
		
		select string_agg(concat(
			'<div><b>Дата</b>: ', to_char((imp.jb_sources->>'d_date')::date, 'DD.MM.YYYY'), '<br />', 
			'<b>Источник</b>: ', imp.jb_sources->>'c_delivery_method_name', '<br />', 
			'<b>Шкала</b>: ', imp.jb_sources->>'c_scale', '<br />', 
			'<b>Показание</b>: ', (imp.jb_sources->>'n_value')::numeric , '</div>'), '' order by imp.f_scale) into _c_meter_readings 
		from dbo.ed_input_meter_readings as imp
		where imp.f_registr_pts = _f_registr_pts and imp.d_replace_date is null and imp.jb_sources is not null;
		
		select string_agg(concat(
			'<div><b>Тип трансформатора</b>: ', CASE WHEN t.b_voltage THEN 'напряжение' ELSE 'ток' END, '<br />', 
			'<b>Номер</b>: ', t.c_serial_number, '<br />', 
			'<b>Тип</b>: ', dt.c_name, '<br />', 
			'<b>Год выпуска</b>: ', t.n_manufacture_year::text, '<br />', 
			'<b>Коэффициент трансформации</b>: ', dt.n_rate::text, '<br />', 
			'<b>Фаза</b>: ', t.c_phase, '<br />', 
			'<b>Дата поверки</b>: ', to_char(t.d_check_date, 'DD.MM.YYYY'), '<br />', 
			'<b>Дата след. поверки</b>: ', to_char(t.d_replace_before, 'DD.MM.YYYY'), '<br />', 
			'<b>Межповерочный интервал</b>: ', dt.n_check_cycle::text, '</div>'), '' order by t.b_voltage, t.c_phase) into _c_transformers_info 
		from dbo.ed_transformers as t
		inner join dbo.es_device_types as dt ON dt.id = t.f_device_type
		where t.f_registr_pts = _f_registr_pts and t.d_replace_date is null;
		
		RETURN concat('<p style="text-align: center">Показания</p>', CASE WHEN _c_meter_readings is null THEN '<div>информация отсутствует</div>' ELSE _c_meter_readings END, '<p style="text-align: center">Пломбы</p>', CASE WHEN _c_seals_info is null THEN '<div>информация отсутствует</div>' ELSE _c_seals_info END, '<p style="text-align: center">Трансформаторы</p>', CASE WHEN _c_transformers_info is null THEN '<div>информация отсутствует</div>' ELSE _c_transformers_info END);
	ELSE
		RETURN '';
	END IF;
END

Function: dbo.sf_generate_point_jb_data(_f_registr_pts uuid)

Returns: jsonb

Language: PLPGSQL

Генерация JSON информации для точки учета

/**
* @params {uuid} _f_registr_pts - идентификатор точки учета
*
* @returns {jsonb}
*
* @example
* [{ "action": "sf_generate_point_data", "method": "Query", "data": [{ "params": [_f_registr_pts] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_jb_data jsonb;
BEGIN
	IF (select count(*) from dbo.ed_registr_pts as rp where rp.id = _f_registr_pts) = 1 THEN
		select json_build_object(
							'c_address', ad.c_name, -- Адрес
							'b_person', s.b_person, -- true - Фил. лицо
							'b_technical_metering', rp.b_technical_metering, -- Признак технического учета
							'c_device_model', dt.c_name, -- Модель ПУ
							'c_device_number', d.c_serial_number, -- № ПУ
							'c_owner', CASE WHEN s.b_person THEN concat(s.c_name1, ' ', s.c_name2, ' ', s.c_name3) ELSE s.c_name1 END, -- ФИО
							'c_device_interval', '',
							'n_longitude', ad.n_geo_lon,
							'n_latitude', ad.n_geo_lat,
							'c_subscr', s.c_code,
							'c_telephone', s.c_telephone,
							'c_path', case when rp.c_substation is null then '' else concat(rp.c_substation, '/', rp.c_line_substation, '/', rp.c_rp, '/', rp.c_line_rp, '/', rp.c_tp, '/', rp.c_line_tp, '/', rp.c_line_segment) end
							)::jsonb into _jb_data
		from dbo.ed_registr_pts as rp
		left join dbo.sd_subscr as s ON s.id = rp.f_subscr
		left join dbo.ss_address as ad ON ad.id = rp.f_address
		left join dbo.ed_devices as d ON d.f_registr_pts = rp.id
		left join dbo.es_device_types as dt ON dt.id = d.f_device_type
		where d.d_close_date is null and rp.id = _f_registr_pts;	
		
		RETURN _jb_data;
	ELSE
		RETURN null::jsonb;
	END IF;
END

Function: dbo.sf_transfer_output_data()

Returns: integer

Language: PLPGSQL

Обработка выходных данных

/**
* @returns {integer}
* 0 - ОК
*
* @example
* [{ "action": "sf_transfer_output_data", "method": "Query", "data": [{ "params": [] }], "type": "rpc", "tid": 0}]
*/
BEGIN

	-- обработка показаний (просили закомментировать - Аня К.)
	/*IF (select count(*) from dbo.ed_output_meter_readings where b_export = false) > 0 THEN
		-- нужно перенести новые показаний в input
		INSERT INTO dbo.ed_input_meter_readings(id, n_value_prev, d_date_prev, n_digit, f_scale, dx_created, f_registr_pts, f_tariff_zone, f_energy_type, f_delivery_method, d_replace_date)
		select t.id, t.n_value, t.d_date, t.n_digit, t.f_scale, t.dx_created, t.f_registr_pts, t.f_tariff_zone, t.f_energy_type, t.f_delivery_method, t.d_replace_date::timestamp with time zone
		from (select omr.id, omr.n_value, omr.d_date, imr.n_digit, imr.f_scale, now() as dx_created, imr.f_registr_pts, imr.f_tariff_zone, imr.f_energy_type, imr.f_delivery_method, null as d_replace_date,
			row_number() over(partition by imr.id, imr.f_registr_pts order by omr.d_date desc) as n_row
			from dbo.ed_output_meter_readings as omr
			inner join dbo.ed_input_meter_readings as imr ON omr.fn_meter_reading = imr.id
			where omr.b_export = false) as t
		where t.n_row = 1;
		
		-- устанавливаем признак замены показания
		update dbo.ed_input_meter_readings as imr
		set d_replace_date = t1.d_date
		from (
			select t.id, t.d_date from (select imr.id, omr.d_date,
				row_number() over(partition by imr.id, imr.f_registr_pts order by omr.d_date desc) as n_row 
				from dbo.ed_output_meter_readings as omr
				inner join dbo.ed_input_meter_readings as imr ON omr.fn_meter_reading = imr.id
				where omr.b_export = false) as t
			where t.n_row = 1
		) as t1
		where imr.id = t1.id;
		
		-- указываем, что данные обработали
		update dbo.ed_output_meter_readings
		set b_export = true
		where b_export = false;
	END IF;*/

	-- обработка пломб
	IF (select count(*) from dbo.ed_output_conn_seals where b_export = false) > 0 OR 
	(select count(*) from dbo.ed_seals as s where s.d_replace_date is null and s.f_status = 4) > 0 THEN
		-- нужно обновить информацию по пломбам, которые ранее были выданы и использованы
		update dbo.ed_seals as s
		set f_registr_pts = t1.f_registr_pts,
		c_type = t1.c_type,
		c_location = t1.c_location,
		f_type = t1.f_type,
		f_place = t1.f_place,
		f_output_conn_seal = t1.f_output_conn_seal
		from (
			select ocs.fn_seal_new, p.f_registr_pts, st.c_name as c_type, st.id as f_type, sp.c_name as c_location, sp.id as f_place, ocs.id as f_output_conn_seal
			from dbo.ed_output_conn_seals as ocs
			inner join dbo.es_seal_types as st ON st.id = ocs.fn_type
			inner join dbo.es_seal_places as sp ON sp.id = ocs.fn_place
			inner join dbo.ed_seals as es ON es.id = ocs.fn_seal_new
			inner join core.cd_points as p ON p.id = ocs.fn_point
			where ocs.b_export = false
		) as t1
		where s.id = t1.fn_seal_new;
		
		-- отключаем пломбы, которые были заменены
		update dbo.ed_seals as s
		set d_replace_date = t1.d_date
		from (
			select es.id, ocs.d_date 
			from dbo.ed_output_conn_seals as ocs
			inner join dbo.ed_seals as es ON es.id = ocs.fn_seal
			where ocs.b_export = false
		) as t1
		where s.id = t1.id;
		
		-- отключаем пломбы, которые были снята
		update dbo.ed_seals as s
		set d_replace_date = now()
		where s.d_replace_date is null and s.f_status = 4;
		
		-- указываем, что данные обработали
		update dbo.ed_output_conn_seals
		set b_export = true
		where b_export = false;
	END IF;

	/*-- обработка трансформаторов
	IF (select count(*) from dbo.ed_output_transformers where b_export = false) > 0 THEN
		-- находим созданные трансформаторы и добавляем их общий список
		INSERT INTO dbo.ed_transformers(id, f_registr_pts, b_voltage, c_serial_number, d_replace_before, f_device_type, c_phase, imp_int, n_manufacture_year, d_check_date, d_replace_date, imp_text, n_rate)
		select ot.id, p.f_registr_pts, ot.b_voltage, ot.c_number, ot.d_date + (dt.n_check_cycle || ' year')::interval, dt.id, ph.c_name, null, ot.n_year, ot.d_date_check, null, null, ot.n_rate
		FROM dbo.ed_output_transformers as ot
		inner join dbo.es_phase as ph ON ph.id = ot.fn_phase
		inner join core.cd_points as p ON p.id = ot.fn_point
		inner join dbo.es_device_types as dt ON dt.id = ot.fn_device_type
		where ot.b_export = false;
		
		-- отключаем трансформаторы, которые были заменены
		update dbo.ed_transformers as t
		set d_replace_date = t1.d_date
		from (
			select tr.id, ot.d_date from dbo.ed_output_transformers as ot
			inner join dbo.ed_transformers as tr ON tr.id = ot.fn_transformer
			where ot.b_export = false
		) as t1
		where t.id = t1.id;
		
		-- указываем, что данные обработали
		update dbo.ed_output_transformers
		set b_export = true
		where b_export = false;
	END IF;
	
	-- обновление номера телефона
	IF (select count(*) from core.cd_user_points where b_export = false) > 0 THEN
		-- обновляем номера
		update dbo.sd_subscr as s
		set c_telephone = t1.c_telephone,
		jb_history = dbo.sf_update_jb_history(CASE WHEN jb_history is null THEN '[]'::json ELSE jb_history END, json_build_object('c_telephone', s.c_telephone,
													   'fn_user_point', t1.fn_user_point,
													   'dx_created', now()))
		from (
			select up.c_telephone, rp.f_subscr, up.id as fn_user_point 
			from core.cd_user_points as up
			inner join core.cd_points as p ON p.id = up.fn_point
			inner join dbo.ed_registr_pts as rp ON rp.id = p.f_registr_pts
			inner join dbo.sd_subscr as s ON s.id = rp.f_subscr
			where up.b_export = false and (up.c_telephone != s.c_telephone or s.c_telephone is null)
		) as t1
		where s.id = t1.f_subscr;
		
		-- проверяем есть ли задания по замене ПУ и отключаем старое ПУ
		update dbo.ed_devices as d
		set d_close_date = now()::date
		from (
			select p.f_registr_pts, r.jb_data from core.cd_user_points as up
			inner join core.cd_points as p ON p.id = up.fn_point
			inner join core.cd_results as r ON r.fn_user_point = up.id
			inner join core.cs_result_types as rt ON rt.id = r.fn_type
			where up.b_export = false and (rt.c_const = 'AZPU' or rt.c_const = 'ADEPU')
		) as t
		where d.f_registr_pts = t.f_registr_pts and d.d_close_date is null;
		
		-- устанавливаем новый ПУ
		insert into dbo.ed_devices(f_device_type, c_serial_number, n_rate, n_manufacture_year, d_setup_date, d_valid_date, f_device_location, f_registr_pts)
		select (r.jb_data #>> '{f_device_model}')::integer, (r.jb_data #>> '{c_device_number}'), (r.jb_data #>> '{n_rate}')::numeric, (r.jb_data #>> '{n_year}')::integer, up.d_date::date, (r.jb_data #>> '{d_check_date}')::date, (r.jb_data #>> '{f_device_location}')::integer, p.f_registr_pts
		from core.cd_user_points as up
		inner join core.cd_points as p ON p.id = up.fn_point
		inner join core.cd_results as r ON r.fn_user_point = up.id
		inner join core.cs_result_types as rt ON rt.id = r.fn_type
		where up.b_export = false and (rt.c_const = 'AZPU' or rt.c_const = 'ADEPU');
		
		-- отключаем старые показания
		update dbo.ed_input_meter_readings as imr
		set d_replace_date = t.d_date
		from (
			select p.f_registr_pts, up.d_date
			from core.cd_user_points as up
			inner join core.cd_points as p ON p.id = up.fn_point
			inner join core.cd_results as r ON r.fn_user_point = up.id
			inner join core.cs_result_types as rt ON rt.id = r.fn_type
			where up.b_export = false and (rt.c_const = 'AZPU' or rt.c_const = 'ADEPU')
		) as t
		where imr.f_registr_pts = t.f_registr_pts and imr.d_replace_date is null;
		
		-- создаем показания
		perform dbo.sf_generate_meter_reading(r.id) 
		from core.cd_user_points as up
		inner join core.cd_results as r ON r.fn_user_point = up.id
		inner join core.cs_result_types as rt ON rt.id = r.fn_type
		where up.b_export = false and (rt.c_const = 'AZPU' or rt.c_const = 'ADEPU');
		
		-- указываем, что данные обработали
		update core.cd_user_points
		set b_export = true
		where b_export = false;
	END IF;*/
	
	RETURN 0;
END

Function: dbo.sf_update_jb_history(items json, old_json json)

Returns: json

Language: PLV8

Обновление истории для специального поля jb_history

	items.push(old_json);
	return items;

Function: dbo.sf_update_point_data(_f_point uuid)

Returns: integer

Language: PLPGSQL

Обновление JSON и общей информации у точки маршрута

/**
* @params {uuid} _f_point - идентификатор точки маршрута
*
* @returns
* 0 - OK
* 1 - нет точки маршрута
*
* @example
* [{ "action": "sf_update_point_jb_data", "method": "Query", "data": [{ "params": [_f_point] }], "type": "rpc", "tid": 0}]
*/
DECLARE
	_f_registr_pts uuid;
BEGIN
	IF (select count(*) from core.cd_points as p where p.id = _f_point) = 1 THEN
		select p.f_registr_pts into _f_registr_pts from core.cd_points as p where p.id = _f_point;
	
		update core.cd_points as p
		set jb_data = dbo.sf_generate_point_jb_data(_f_registr_pts),
		c_info = dbo.sf_generate_point_info(_f_registr_pts)
		where p.id = _f_point;
		
		RETURN 0;
	ELSE
		RETURN 1; -- нет точки маршрута
	END IF;
END

Function: dbo.uuid_or_null(str text)

Returns: uuid

Language: PLPGSQL

Преобразует текст в uuid, при неудаче вернет null

BEGIN
  RETURN str::uuid;
EXCEPTION WHEN invalid_text_representation THEN
  RETURN NULL;
END;

Schema rpt

Схема отчетов


Function: rpt.cf_doned_work(_d_date_start date, _d_date_end date, _f_main_division text, _f_division text, _f_subdivisions text, _c_substation text, _c_line_substation text, _c_tp text)

Returns: SET OF record

Language: PLPGSQL

Отчет по выполненным работам

/**
* @params {date} _d_date_start - дата начала периода
* @params {date} _d_date_end - дата окончания периода
* @params {text} _f_main_division - филиал, можно передать -1, тогда выборка будет по всем
* @params {text} _f_division - отделение, можно передать -1, тогда выборка будет по всем в рамках филиала
* @params {text} _f_subdivisions - список участоков через запятую, например 55,56. Можно передать -1, тогда все участки в рамках отделения
* @params {text} _c_substation - Наименование ПС
* @params {text} _c_line_substation - Наименование фидера 6-10 кВ
* @params {text} _c_tp - Наименование ТП 6-10/0,4 кВ
*
* @example
* [{ "action": "cf_doned_work", "method": "Select", "data": [{ "params": [_d_date_start, _d_date_end, _f_main_division, _f_division, _f_subdivisions] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_d_period_start date;
	_d_period_end date;
BEGIN
	select _d_date_start, _d_date_end into _d_period_start, _d_period_end;

	RETURN QUERY
	with results as (
		select 
			main_div.id as f_main_division,
			div.id as f_division,
			rp.f_subdivision as f_subdivision,
			main_div.c_name as c_main_division, -- Филиал
			div.c_name as c_division, -- Отделение
			sub_div.c_name as c_subdivision, -- Участок
			r.c_number as c_route_number, -- номер маршрута
			-- Исполнители маршрута
			(select string_agg(concat(u.c_last_name, ' ', u.c_first_name, ' ', u.c_middle_name), ', ') from core.cd_userinroutes as uir inner join core.pd_users as u ON uir.f_user = u.id where uir.f_route = r.id and uir.b_main) as c_main_users, -- исполнитель
			(select string_agg(concat(u.c_last_name, ' ', u.c_first_name, ' ', u.c_middle_name), ', ') from core.cd_userinroutes as uir inner join core.pd_users as u ON uir.f_user = u.id where uir.f_route = r.id and uir.b_main = false) as c_second_users, -- соисполнитель
			rrt.c_name as c_result_type, -- тип акта
			rr.d_date as d_result_date, -- дата акта
			case when s.b_person then concat(s.c_name1, ' ', s.c_name2, ' ', s.c_name3) else s.c_name1 end as c_owner, -- Наименование абонента
			ad.c_name as c_address, -- адрес
			rp.imp_text as c_registr_pts_code, -- код ТУ
			d.c_serial_number as n_device_code, -- Номер ПУ
			sc.c_name as c_scale_name, -- Тариф
			round(omr.n_value, ((coalesce(dt.n_digits, 9.2) % floor(coalesce(dt.n_digits, 9.2))) * 10)::integer)::text as c_value_current, -- Текущие показаний
			concat(u.c_last_name, ' ', u.c_first_name, ' ', u.c_middle_name) as c_doned_user_name, -- Выполнил
			rr.fn_user_point, 
			rr.fn_type,
			p.n_order,
			rp.c_substation as c_substation,
			rp.c_line_substation as c_line_substation, 
			rp.c_tp as c_tp --,
			--row_number() over(partition by rr.fn_point order by rr.d_date desc) as n_row нужно выводить все - 486785
		from core.cd_results as rr
		inner join core.pd_users as u ON u.id = rr.fn_user
		inner join core.cs_result_types as rrt ON rrt.id = rr.fn_type
		inner join core.cd_points as p ON rr.fn_point = p.id
		inner join core.cd_routes as r ON p.f_route = r.id
		left join dbo.ed_output_meter_readings as omr ON omr.fn_result = rr.id
		left join dbo.ed_input_meter_readings as imp ON imp.id = omr.fn_meter_reading
		inner join dbo.ed_devices as d ON d.f_registr_pts = p.f_registr_pts
		inner join dbo.es_device_types as dt ON d.f_device_type = dt.id
		inner join dbo.ed_registr_pts as rp ON p.f_registr_pts = rp.id
		inner join core.sd_subdivisions as sub_div ON rp.f_subdivision = sub_div.id
		inner join core.sd_divisions as div ON rp.f_division = div.id
		left join core.sd_divisions as main_div ON div.f_division = main_div.id
		inner join dbo.sd_subscr as s ON rp.f_subscr = s.id
		inner join dbo.ss_address as ad ON rp.f_address = ad.id
		left join dbo.es_scales as sc on imp.f_scale = sc.id
		where omr.d_date between _d_date_start and _d_date_end + interval '1 day'
	) select
		row_number() over(order by max(t.n_order) desc) AS n_num, -- номер п/п
		to_char(_d_period_start, 'dd.MM.YYYY') as d_period_start,
		to_char(_d_period_end, 'dd.MM.YYYY') as d_period_end,
		max(t.f_main_division) as f_maindivision,
		max(t.f_division) as f_division,
		max(t.f_subdivision) as f_subdivision,
		max(t.c_main_division) as c_main_division,
		max(t.c_division) as c_division,
		max(t.c_subdivision) as c_subdivision,
		max(t.c_route_number) as c_route_number,
		max(t.c_main_users) as c_main_users,
		max(t.c_second_users) as c_second_users,
		max(t.c_result_type) as c_result_type,
		max(t.d_result_date) as d_result_date,
		max(t.c_owner) as c_owner,
		max(t.c_address) as c_address,
		max(t.c_registr_pts_code) as c_registr_pts_code,
		max(t.n_device_code) as n_device_code,
		string_agg(t.c_scale_name, ', ') as c_scale_name,
		string_agg(t.c_value_current, ', ') as c_value_current,
		max(t.c_doned_user_name) as c_doned_user_name,
		max(t.c_substation) as c_substation,
		max(t.c_line_substation) as c_line_substation,
		max(t.c_tp) as c_tp
	from (select * from results as rr
			where rr.d_result_date between _d_date_start and _d_date_end + interval '1 day'
			and (case when _f_main_division is null or _f_main_division = '' or _f_main_division = '-1' then 1=1 else _f_main_division::integer = rr.f_main_division end) 
			and (case when _f_division is null or _f_division = '' or _f_division = '-1' then 1=1 else _f_division::integer = rr.f_division end) 
			and (case when _f_subdivisions is null or _f_subdivisions = '' or _f_subdivisions = '-1' then 1=1 else rr.f_subdivision in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) end) 

			and (case when _c_substation is null or _c_substation = '' or _c_substation = '-1' then 1=1 else rr.c_substation ilike '%'||_c_substation||'%' end) 
			and (case when _c_line_substation is null or _c_line_substation = '' or _c_line_substation = '-1' then 1=1 else rr.c_line_substation ilike '%'||_c_line_substation||'%' end) 
			and (case when _c_tp is null or _c_tp = '' or _c_tp = '-1' then 1=1 else rr.c_tp ilike '%'||_c_tp||'%' end) 
	) as t
	--where t.n_row = 1 (486785 убрал в рамках вот этого река - нужно выводить все)
	group by t.fn_user_point, t.fn_type
	order by max(t.n_order) desc;
END

Function: rpt.cf_ed_blanks_act(_d_date_start date, _d_date_end date, _f_maindivisions text, _f_divisions text, _f_subdivisions text, _f_user_to text, _f_statuses text)

Returns: SET OF record

Language: PLPGSQL

Журнал регистрации бланков актов проверки состояния схемы измерений э/э и работы/замены/допуска в эксплуатацию приборов учета


BEGIN

	

	RETURN QUERY 
	/*with items as (
		select -- тут делаем сортировки по истории
			row_number() over(partition by s.id order by s.d_date_to asc) as n_row,
			s.id, -- иден. пломбы
			ss.c_const as c_status_const, -- иден. типа пломбы
			s.f_user_to as f_user_to, -- кому выдан
			s.f_user_from as f_user_from, -- кем выдан
			coalesce(s.d_date_to, s.dx_created) as d_date_to, -- дата выдачи
			s.f_status as f_status -- статус
		from (select -- отсюда получаем информацию об истории
			s.id,s.dx_created,
			(json_array_elements(s.jb_history)->>'f_user_to')::integer as f_user_to,
			(json_array_elements(s.jb_history)->>'f_user_from')::integer as f_user_from,
			(json_array_elements(s.jb_history)->>'d_date_to')::timestamp with time zone as d_date_to,
			(json_array_elements(s.jb_history)->>'f_status')::integer as f_status
		from dbo.ed_blanks as s
		where s.f_status is not null) as s
		inner join dbo.es_blank_status as ss ON s.f_status = ss.id
		where 1=1
	)*/
	select
		s.id, -- иден. пломбы
		1::bigint as n_row, -- позиция
		ssd.id as f_subdivision, -- иден. участок
		ssd.c_name as c_subdivision, -- участок
		concat(coalesce(s.c_prefix, ''), s.n_number) as c_blank_number, -- Номер пломбировочного материала
		s.dx_created as d_date_create, -- дата создания пломбы
		concat(um.c_last_name || ' ', LEFT(um.c_first_name, 1) || '. ', LEFT(um.c_middle_name, 1) || '.') as c_user_mol, -- Фамилия и инициалы МОЛ
		s.d_date_to, -- Дата выдачи бланка акта 
		concat(ut.c_last_name || ' ', LEFT(ut.c_first_name, 1) || '. ', LEFT(ut.c_middle_name, 1) || '.') as c_user_to, -- кто получил
		ut.c_post as c_post_to, -- Должность получателя пломбировочного материала
		concat(uf.c_last_name || ' ', LEFT(uf.c_first_name, 1) || '. ', LEFT(uf.c_middle_name, 1) || '.') as c_user_from, -- кто выдал
		uf.c_post as c_post_from, -- Должность ответственного за ведение и хранение журнала
		case when ss.c_const in ('SETUP','TRASH') then to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as d_date_setup_trash, -- Дата составления (возврата) акта (бланка)
		concat( case when sub.b_person then concat(sub.c_name1, ' ', sub.c_name2, ' ', sub.c_name3) else sub.c_name1 end,		-- Наименование потребителя
				' ', sa.c_name,																									-- Адрес
				' ', sa.c_name_obj 																								-- Наименование объекта 
			)	as c_owner, -- потребитель
		coalesce(s.c_document_trash, rt.c_name) as c_document_number, -- Дата акта (документ о списании пломбировочного материала)
		case when s.c_document_trash is null or s.c_document_trash = '' then to_char(r.d_date, 'dd.MM.YYYY'::text) else to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as c_document_date -- Номер акта (документ о списании пломбировочного материала)
	from dbo.ed_blanks as s
	inner join dbo.es_blank_status as ss ON s.f_status = ss.id
	left join core.sd_subdivisions as ssd ON ssd.id = s.f_subdivision
	left join core.sd_divisions as sd ON sd.id = ssd.f_division
	left join core.sd_divisions as sdd ON sdd.id = sd.f_division
	left join core.cd_results as r ON s .fn_result = r.id
	inner join core.cs_result_types as rt ON rt.id = s.f_result_type
	left join core.cd_points as cp on cp.id = r.fn_point
	left join dbo.ed_registr_pts as rp ON rp.id = cp.f_registr_pts
	left join dbo.sd_subscr as sub ON sub.id = rp.f_subscr
	left join dbo.ss_address as sa ON sa.id = rp.f_address
	left join core.pd_users as uf ON s.f_user_from = uf.id
	left join core.pd_users as ut ON s.f_user_to = ut.id
	left join core.pd_users as um ON s.f_user_mol = um.id
	where s.d_date_to between _d_date_start and _d_date_end + interval '1 day'
	and ss.c_const in ('REG', 'SEND', 'SETUP', 'TRASH')
	and rt.c_const in ('AIP', 'AZPU', 'ADEPU')
	and case 	
			when 	_f_maindivisions is null 
				or 	_f_maindivisions = '' 
				or 	_f_maindivisions = '-1' 
					then 1=1 
			else sdd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_maindivisions)) as t) 
		end
	and case 	
			when 	_f_divisions is null 
				or 	_f_divisions = '' 
				or 	_f_divisions = '-1' 
					then 1=1 
			else sd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_divisions)) as t) 
		end
	and case 
			when 	_f_subdivisions is null 
				or 	_f_subdivisions = '' 
				or 	_f_subdivisions = '-1' 
					then 1=1 
			else ssd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) 
		end
	and (case when _f_user_to is null or _f_user_to = '' or _f_user_to = '-1' then 1=1 else s.f_user_to in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_user_to)) as t) end)
	and (case when _f_statuses is null or _f_statuses = '' or _f_statuses = '-1' then 1=1 else ss.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_statuses)) as t) end) 
	order by s.d_date_to, s.id;
END

Function: rpt.cf_ed_blanks_unaccounted(_d_date_start date, _d_date_end date, _f_maindivisions text, _f_divisions text, _f_subdivisions text, _f_user_to text, _f_statuses text)

Returns: SET OF record

Language: PLPGSQL

Журнал регистрации актов о неучтенном потреблении э/э


BEGIN

	

	RETURN QUERY 
	/*with items as (
		select -- тут делаем сортировки по истории
			row_number() over(partition by s.id order by s.d_date_to asc) as n_row,
			s.id, -- иден. пломбы
			ss.c_const as c_status_const, -- иден. типа пломбы
			s.f_user_to as f_user_to, -- кому выдан
			s.f_user_from as f_user_from, -- кем выдан
			coalesce(s.d_date_to, s.dx_created) as d_date_to, -- дата выдачи
			s.f_status as f_status -- статус
		from (select -- отсюда получаем информацию об истории
			s.id,s.dx_created,
			(json_array_elements(s.jb_history)->>'f_user_to')::integer as f_user_to,
			(json_array_elements(s.jb_history)->>'f_user_from')::integer as f_user_from,
			(json_array_elements(s.jb_history)->>'d_date_to')::timestamp with time zone as d_date_to,
			(json_array_elements(s.jb_history)->>'f_status')::integer as f_status
		from dbo.ed_blanks as s
		where s.f_status is not null) as s
		inner join dbo.es_blank_status as ss ON s.f_status = ss.id
		where 1=1
		)
	*/
	select
		s.id, -- иден. пломбы
		1::bigint as n_row, -- позиция
		ssd.id as f_subdivision, -- иден. участок
		ssd.c_name as c_subdivision, -- участок
		concat(coalesce(s.c_prefix, ''), s.n_number) as c_blank_number, -- Номер пломбировочного материала
		s.dx_created as d_date_create, -- дата создания пломбы
		concat(um.c_last_name || ' ', LEFT(um.c_first_name, 1) || '. ', LEFT(um.c_middle_name, 1) || '.') as c_user_mol, -- Фамилия и инициалы МОЛ
		s.d_date_to, -- Дата выдачи бланка акта 
		concat(ut.c_last_name || ' ', LEFT(ut.c_first_name, 1) || '. ', LEFT(ut.c_middle_name, 1) || '.') as c_user_to, -- кто получил
		ut.c_post as c_post_to, -- Должность получателя пломбировочного материала
		concat(uf.c_last_name || ' ', LEFT(uf.c_first_name, 1) || '. ', LEFT(uf.c_middle_name, 1) || '.') as c_user_from, -- кто выдал
		uf.c_post as c_post_from, -- Должность ответственного за ведение и хранение журнала
		case when ss.c_const in ('SETUP','TRASH') then to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as d_date_setup_trash, -- Дата составления (возврата) акта (бланка)
		case when rt.c_const = 'ABUP' then concat( case when sub.b_person then concat(sub.c_name1, ' ', sub.c_name2, ' ', sub.c_name3) else sub.c_name1 end,
						' ', sa.c_name)
			 when rt.c_const = 'ABDP' then concat(r.jb_data->>'c_address', ' ', r.jb_data->>'c_consumer')	
		end as c_owner, -- потребитель
		case when rt.c_const = 'ABUP' then 'безучетное потребление'
			 when rt.c_const = 'ABDP' then 'бездоговорное потреблене'
		end as c_status,
		coalesce(s.c_document_trash, rt.c_name) as c_document_number, -- Дата акта (документ о списании пломбировочного материала)
		case when s.c_document_trash is null or s.c_document_trash = '' then to_char(r.d_date, 'dd.MM.YYYY'::text) else to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as c_document_date -- Номер акта (документ о списании пломбировочного материала)
		--concat((case when s.c_document_trash is null or s.c_document_trash = '' then to_char(r.d_date, 'dd.MM.YYYY'::text) else to_char(i.d_date_to, 'dd.MM.YYYY'::text) end), ' ', coalesce(s.c_document_trash, rt.c_name)) as c_document -- наименование документа
	from dbo.ed_blanks as s
	inner join dbo.es_blank_status as ss ON s.f_status = ss.id
	left join core.sd_subdivisions as ssd ON ssd.id = s.f_subdivision
	left join core.sd_divisions as sd ON sd.id = ssd.f_division
	left join core.sd_divisions as sdd ON sdd.id = sd.f_division
	left join core.cd_results as r ON s .fn_result = r.id
	inner join core.cs_result_types as rt ON rt.id = s.f_result_type
	left join core.cd_points as cp on cp.id = r.fn_point
	left join dbo.ed_registr_pts as rp ON rp.id = cp.f_registr_pts
	left join dbo.sd_subscr as sub ON sub.id = rp.f_subscr
	left join dbo.ss_address as sa ON sa.id = rp.f_address
	left join core.pd_users as uf ON s.f_user_from = uf.id
	left join core.pd_users as ut ON s.f_user_to = ut.id
	left join core.pd_users as um ON s.f_user_mol = um.id
	where s.d_date_to between _d_date_start and _d_date_end + interval '1 day'
	and ss.c_const in ('REG', 'SEND', 'SETUP', 'TRASH')
	and rt.c_const in ('ABUP', 'ABDP')
	and case 	
			when 	_f_maindivisions is null 
				or 	_f_maindivisions = '' 
				or 	_f_maindivisions = '-1' 
					then 1=1 
			else sdd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_maindivisions)) as t) 
		end
	and case 	
			when 	_f_divisions is null 
				or 	_f_divisions = '' 
				or 	_f_divisions = '-1' 
					then 1=1 
			else sd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_divisions)) as t) 
		end
	and case 
			when 	_f_subdivisions is null 
				or 	_f_subdivisions = '' 
				or 	_f_subdivisions = '-1' 
					then 1=1 
			else ssd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) 
		end
	and (case when _f_user_to is null or _f_user_to = '' or _f_user_to = '-1' then 1=1 else s.f_user_to in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_user_to)) as t) end)
	and (case when _f_statuses is null or _f_statuses = '' or _f_statuses = '-1' then 1=1 else ss.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_statuses)) as t) end) 
	order by s.d_date_to, s.id;
END

Function: rpt.cf_ed_meters_to_supplier(_d_date_start date, _d_date_end date, _f_maindivisions text, _f_divisions text, _f_subdivisions text, _subject text)

Returns: SET OF record

Language: PLPGSQL

Отчет "Реестр показаний для ГП"

/**
* @params {date} _d_date_start - дата начала периода
* @params {date} _d_date_end - дата окончания периода
* @params {text} _f_subdivisions - список участок
* @params {text} _f_user_to - иден. пользователя
* @params {text} _f_statuses - список статусов
*
* @example
* [{ "action": "cf_ed_seals", "method": "Select", "data": [{ "params": [_d_date_start, _d_date_end, _f_main_division, _f_division, _f_subdivisions, _f_user] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_CMR 		int4;
	_ATO 		int4;
	_CREATED 	int4;
	_METER 		int4;
BEGIN
	
	select c.id 	into _CMR 		from core.cs_result_types as c 		where c.c_const = 'CMR';
	select c.id 	into _ATO 		from core.cs_result_types as c 		where c.c_const = 'ATO';
	select c.id 	into _CREATED	from core.cs_route_statuses as c 	where c.c_const = 'CREATED';
	select c.id 	into _METER 	from core.cs_attachment_types as c	where c.c_const = 'METER';

	RETURN QUERY 
	select 
		omr.id,
		sdd.id 					as f_maindivision 	,		-- Филиал
 		sdd.c_name 				as c_maindivision 	, 		-- Филиал
 		sd.id 					as f_division 		,		-- ПЭС
 		sd.c_name 				as c_division 		,		-- ПЭС
 		ssd.id 					as f_subdivision 	,	 	-- РЭС
 		ssd.c_name 				as c_subdivision 	, 		-- РЭС
 		case when ss.b_person then concat(ss.c_name1, ' ', ss.c_name2, ' ', ss.c_name3) else ss.c_name1 end 
 								as c_owner 			, 		-- Наименование потребителя/ФИО потребителя
 		ss.c_code 				as c_code 			, 		-- Номер договора энергоснабжения/номер лицевого счета
 		erp.imp_text 			as c_registr_pts_code, 		-- Код ТУ
 		erp.c_registr_pts		as c_registr_pts_name, 		-- Наименование ТУ
 		coalesce(sa.c_city_name, sa.c_settlement_name)	
 							 	as c_settlement 	, 		-- Населенный пункт 
 		sa.c_street_name 		as c_street 		, 		-- Улица
 		sa.c_house_name 		as c_house  		, 		-- Дом
		sa.c_flat_name 			as c_flat_name 		, 		-- Квартира
		ed.c_serial_number 		as c_serial_number 	, 		-- Заводской №ПУ
		edt.c_name 				as c_device_type 	, 		-- Тип ПУ
		coalesce(ed.n_rate, 1)  as n_rate 			, 		-- Расчетный коэффициент
		ed.f_device 			as f_device  		, 		-- Единица оборудования
		concat(r.c_number, ' от ' || to_char(r.d_date, 'dd.MM.YYYY'::text)) 
								as c_doc_number 	, 		-- Номер и дата документа 
		es.c_name 				as c_time_zone 		, 		-- Тариф
		emr.n_value_prev 		as n_value_prev 	,  		-- Предыдущие контрольные показания
		emr.d_date_prev 		as d_date_prev 		,		-- Дата предыдущих контрольных показаний
		concat(puResult.c_last_name || ' ', puResult.c_first_name || ' ', puResult.c_middle_name)
								as c_result_user,			-- ФИО сотрудника снявшего показание
		concat(puRoute.c_last_name || ' ', puRoute.c_first_name || ' ', puRoute.c_middle_name) 
								as c_route_user 	,		-- ФИО сотрудника сформировавшего задание
		omr.n_value 			as n_value 			, 		-- Текущие контрольные показания
		omr.d_date 				as d_date 			, 		-- Дата текущих показаний
		null::timestamptz		as d_export_date	, 		-- Дата загрузки в расчетную систему
		true 					as b_attachment_exist,		-- Наличие приложения
		ca.c_photo_links		as c_photo_links  	,		-- Ссылки на фотографии
		ca.f_files 				as f_files 					-- идентификаторы файлов фотографий
	from core.cd_results as cr
		-- точка 
		inner join core.cd_points as cp
			on cp.id 		= cr.fn_point
		-- маршрут 
		inner join core.cd_routes as r
			on r.id 		= cp.f_route
		-- точка учета
		inner join dbo.ed_registr_pts as erp
			on erp.id 		= cp.f_registr_pts
		-- ЛС
		inner join dbo.sd_subscr as ss
			on 	ss.id 		= erp.f_subscr
		-- РЭС 
		inner join core.sd_subdivisions as ssd 
			on 	ssd.id 		= erp.f_subdivision
		-- ПЭС
		inner join core.sd_divisions as sd
			on sd.id 		= erp.f_division
		-- Филиал
		inner join core.sd_divisions as sdd
			on 	sdd.id 		= sd.f_division
		-- Адрес
		inner join dbo.ss_address as sa
			on 	sa.id 		= erp.f_address
		-- Снятое показание
		inner join dbo.ed_output_meter_readings as omr
			on 	omr.fn_point 		= cp.id 
			and omr.fn_user_point 	= cr.fn_user_point
			and omr.fn_result 		= cr.id
		-- предыдущее показание 
		inner join dbo.ed_input_meter_readings as emr
			on 	emr.id 		= omr.fn_meter_reading
		inner join dbo.es_scales as es
			on 	es.id 		= emr.f_scale
		-- последний прибор на дату 
		left join lateral(
			select 
				ed.f_registr_pts,
				ed.c_serial_number,
				ed.f_device_type,
				ed.n_rate,
				nullif(ed.imp_text, '')		as f_device,
				ed.id 						as f_device_guid,
				row_number() over(partition by ed.f_registr_pts order by ed.d_setup_date desc, ed.d_close_date desc) as n_row
			from dbo.ed_devices as ed 
			where 1=1
				and ed.f_registr_pts 	= cp.f_registr_pts
				and (ed.d_setup_date is null or ed.d_setup_date < cr.d_date)
				and (ed.d_close_date is null or ed.d_close_date >= cr.d_date)
		) as ed 
			on 	1=1
			and ed.n_row 			= 1
		-- тип прибора учета
		left join dbo.es_device_types as edt
			on edt.id 				= ed.f_device_type
		-- сотрудник снявший показание 
		left join core.pd_users as puResult
			on 	puResult.id = cr.fn_user
		-- сотрудник создавший маршрут
		left join (
			select crh.fn_route, crh.fn_user,
				row_number() over(partition by crh.fn_route order by crh.d_date asc, crh.id)  as n_row
			from core.cd_route_history as crh
			where crh.fn_status = _CREATED
		) as crh
			on 	crh.fn_route 	= r.id
			and crh.n_row 		= 1
		left join core.pd_users as puRoute
			on 	puRoute.id 	= crh.fn_user

		-- сылки на фотографии
		left join (
			select 
				ca.fn_result,
				string_agg(cf.id::text,';') as f_files,
				string_agg(concat(cs.c_value, '/file?id=', cf.id::text), ';') as c_photo_links
			from core.cd_attachments as ca
				 -- файл
				inner join core.cd_files as cf 
					on 	cf.id 			= ca.fn_file
				inner join core.cd_settings as cs 
					on 	cs.c_key 		= 'ALL_URL'
			where ca.fn_type 	= _METER
			group by ca.fn_result
		) as ca
			on 	ca.fn_result 	= cr.id
	where 	cr.fn_type 	in (_CMR, _ATO)
		and cr.d_date::date 	between _d_date_start and _d_date_end
		and case 	
				when 	_f_maindivisions is null 
					or 	_f_maindivisions = '' 
					or 	_f_maindivisions = '-1' 
						then 1=1 
				else sdd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_maindivisions)) as t) 
			end
		and case 	
				when 	_f_divisions is null 
					or 	_f_divisions = '' 
					or 	_f_divisions = '-1' 
						then 1=1 
				else sd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_divisions)) as t) 
			end
		and case 	
				when 	_f_subdivisions is null 
					or 	_f_subdivisions = '' 
					or 	_f_subdivisions = '-1' 
						then 1=1 
				else erp.f_subdivision in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) 
			end
		and case 
				when 	_subject 	= 'fl'
					then ss.b_person
				when 	_subject 	= 'ul'
					then not ss.b_person
				else true
			end	;

	

END

Function: rpt.cf_ed_seals(_d_date_start date, _d_date_end date, _f_maindivisions text, _f_divisions text, _f_subdivisions text, _f_user_to text, _f_statuses text)

Returns: SET OF record

Language: PLPGSQL

Журнал регистрации выдачи пломбировочного материала

/**
* @params {date} _d_date_start - дата начала периода
* @params {date} _d_date_end - дата окончания периода
* @params {text} _f_subdivisions - список участок
* @params {text} _f_user_to - иден. пользователя
* @params {text} _f_statuses - список статусов
*
* @example
* [{ "action": "cf_ed_seals", "method": "Select", "data": [{ "params": [_d_date_start, _d_date_end, _f_main_division, _f_division, _f_subdivisions, _f_user] }], "type": "rpc", "tid": 0 }]
*/
BEGIN
	RETURN QUERY 
	/*
	with items as (
		select -- тут делаем сортировки по истории
			row_number() over(partition by s.id order by s.d_date_to asc) as n_row,
			s.id, -- иден. пломбы
			ss.c_const as c_status_const, -- иден. типа пломбы
			s.f_user_to as f_user_to, -- кому выдан
			s.f_user_from as f_user_from, -- кем выдан
			s.dx_created as d_date_create, -- дата создания
			coalesce(s.d_date_to, s.dx_created) as d_date_to, -- дата выдачи
			s.f_status as f_status -- статус
		from (select -- отсюда получаем информацию об истории
			s.id,s.dx_created,
			(json_array_elements(s.jb_history)->>'f_user_to')::integer as f_user_to,
			(json_array_elements(s.jb_history)->>'f_user_from')::integer as f_user_from,
			(json_array_elements(s.jb_history)->>'d_date_to')::timestamp with time zone as d_date_to,
			(json_array_elements(s.jb_history)->>'f_status')::integer as f_status
		from dbo.ed_seals as s
		where s.f_status is not null) as s
		inner join dbo.es_seal_status as ss ON s.f_status = ss.id
		where 1=1
		)
	*/
	select
		s.id, -- иден. пломбы
		1::bigint as n_row, -- позиция
		ssd.id as f_subdivision, -- иден. участок
		ssd.c_name as c_subdivision, -- участок
		st.c_name as c_seal_type, -- Тип (наименование) пломбировочного материала
		concat(coalesce(s.c_prefix, ''), s.c_number) as c_seal_number, -- Номер пломбировочного материала
		concat(um.c_last_name || ' ', LEFT(um.c_first_name, 1) || '. ', LEFT(um.c_middle_name, 1) || '.') as c_user_mol, -- Фамилия и инициалы МОЛ
		ss.c_name as c_status_name, -- название статуса
		ss.c_const as c_status_const, -- иден. типа пломбы
		s.dx_created::timestamptz as d_date_create, -- дата создания пломбы
		s.d_date_to::timestamptz, -- дата выдачи/установка/снятия
		concat(ut.c_last_name || ' ', LEFT(ut.c_first_name, 1) || '. ', LEFT(ut.c_middle_name, 1) || '.') as c_user_to, -- кто получил
		ut.c_post as c_post_to, -- Должность получателя пломбировочного материала
		concat(uf.c_last_name || ' ', LEFT(uf.c_first_name, 1) || '. ', LEFT(uf.c_middle_name, 1) || '.') as c_user_from, -- кто выдал
		uf.c_post as c_post_from, -- Должность ответственного за ведение и хранение журнала
		case when ss.c_const in ('SETUP','TRASH') then to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as d_date_setup_trash, -- Дата установки (возврата) пломбировочного материала
		rp.id as f_registr_pts, -- иден. точки учета
		case when sub.b_person then concat(sub.c_name1, ' ', sub.c_name2, ' ', sub.c_name3) else sub.c_name1 end as c_owner, -- потребитель
		r.id as f_result, -- иден. документа
		coalesce(s.c_document_trash, rt.c_name) as c_document_number, -- Дата акта (документ о списании пломбировочного материала)
		case when s.c_document_trash is null or s.c_document_trash = '' then to_char(r.d_date, 'dd.MM.YYYY'::text) else to_char(s.d_date_to, 'dd.MM.YYYY'::text) end as c_document_date -- Номер акта (документ о списании пломбировочного материала)
		--concat((case when s.c_document_trash is null or s.c_document_trash = '' then to_char(r.d_date, 'dd.MM.YYYY'::text) else to_char(i.d_date_to, 'dd.MM.YYYY'::text) end), ' ', coalesce(s.c_document_trash, rt.c_name)) as c_document -- наименование документа
	from dbo.ed_seals as s
	inner join dbo.es_seal_status as ss ON s.f_status = ss.id
	left join core.sd_subdivisions as ssd ON ssd.id = s.f_subdivision
	left join core.sd_divisions as sd ON sd.id = ssd.f_division
	left join core.sd_divisions as sdd ON sdd.id = sd.f_division
	left join dbo.ed_output_conn_seals as ocs ON s.id = ocs.fn_seal_new
	left join core.cd_results as r ON ocs.fn_result = r.id
	left join core.cs_result_types as rt ON rt.id = r.fn_type
	left join dbo.ed_registr_pts as rp ON rp.id = s.f_registr_pts
	left join dbo.sd_subscr as sub ON sub.id = rp.f_subscr
	left join dbo.es_seal_places as sp ON s.f_place = sp.id
	left join dbo.es_seal_types as st ON s.f_type = st.id
	left join core.pd_users as uf ON s.f_user_from = uf.id
	left join core.pd_users as ut ON s.f_user_to = ut.id
	left join core.pd_users as um ON s.f_user_mol = um.id
	where s.d_date_to between _d_date_start and _d_date_end + interval '1 day'
	and case 	
			when 	_f_maindivisions is null 
				or 	_f_maindivisions = '' 
				or 	_f_maindivisions = '-1' 
					then 1=1 
			else sdd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_maindivisions)) as t) 
		end
	and case 	
			when 	_f_divisions is null 
				or 	_f_divisions = '' 
				or 	_f_divisions = '-1' 
					then 1=1 
			else sd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_divisions)) as t) 
		end
	and case 
			when 	_f_subdivisions is null 
				or 	_f_subdivisions = '' 
				or 	_f_subdivisions = '-1' 
					then 1=1 
			else ssd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) 
		end
	and (case when _f_user_to is null or _f_user_to = '' or _f_user_to = '-1' then 1=1 else s.f_user_to in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_user_to)) as t) end)
	and (case when _f_statuses is null or _f_statuses = '' or _f_statuses = '-1' then 1=1 else ss.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_statuses)) as t) end) 
	order by s.d_date_to, s.id;
END

Function: rpt.cf_meters(_d_date_start date, _d_date_end date, _f_main_division text, _f_division text, _f_subdivisions text)

Returns: SET OF record

Language: PLPGSQL

Выгрузка показаний по ЮЛ за период

/**
* @params {date} _d_date_start - дата начала периода
* @params {date} _d_date_end - дата окончания периода
* @params {text} _f_main_division - филиал
* @params {text} _f_division - отделение
* @params {text} _f_subdivisions - список участок
*
* @example
* [{ "action": "cf_meters", "method": "Select", "data": [{ "params": [_d_date_start, _d_date_end, _f_main_division, _f_division, _f_subdivisions] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_d_period_start date;
	_d_period_end date;
BEGIN
	select _d_date_start, _d_date_end into _d_period_start, _d_period_end;

	RETURN QUERY select 
		row_number() over(order by max(p.n_order) desc) AS n_num, -- номер п/п
		to_char(_d_period_start, 'dd.MM.YYYY') as d_period_start,
		to_char(_d_period_end, 'dd.MM.YYYY') as d_period_end,
		max(main_div.id) as f_maindivision,
		max(div.id) as f_division,
		max(rp.f_subdivision) as f_subdivision,
		max(sub_div.c_dep_code) as c_dep_code, -- Код участка(РЭС)
		max(s.f_partners) as f_partners, -- Код/идентификатор абонента
		max(s.c_name1) as c_owner, -- Наименование абонента
		max(ad.f_conn_points) as f_conn_points, -- Код/идентификатор объекта учета ЮЛ
		max(ad.c_name_obj) as c_name_obj, -- Наименование объекта
		max(s.c_code) as c_subscr, -- Код абонента
		max(rp.imp_text) as c_registr_pts_code, -- код ТУ
		max(d.link) as c_device_code, -- Код/идентификатор ПУ
		max(d.c_serial_number) as c_device_number, -- Заводской номер
		max(dt.c_name) as c_device_model, -- Наименование модели
		string_agg(sc.c_name, ', ') as c_scale_name, -- Тариф
		string_agg(to_char(imp.d_date_prev, 'dd.MM.YYYY'), ', ') as c_date_prev, -- Дата показания
		string_agg(round(imp.n_value_prev, ((dt.n_digits % floor(dt.n_digits)) * 10)::integer)::text, ', ') as c_value_prev, -- Значение показания
		string_agg(to_char(omr.d_date, 'dd.MM.YYYY'), ', ') as c_date_current, -- Дата  текущих показаний
		string_agg(round(omr.n_value, ((dt.n_digits % floor(dt.n_digits)) * 10)::integer)::text, ', ') as c_value_current -- Текущие показаний
	from dbo.ed_output_meter_readings as omr
	inner join dbo.ed_input_meter_readings as imp ON imp.id = omr.fn_meter_reading
	inner join core.cd_points as p ON omr.fn_point = p.id
	inner join core.cd_results as rr ON rr.id = omr.fn_result
	inner join dbo.ed_devices as d ON d.f_registr_pts = p.f_registr_pts
	inner join dbo.es_device_types as dt ON d.f_device_type = dt.id
	inner join dbo.ed_registr_pts as rp ON p.f_registr_pts = rp.id
	inner join core.sd_subdivisions as sub_div ON rp.f_subdivision = sub_div.id
	inner join core.sd_divisions as div ON rp.f_division = div.id
	left join core.sd_divisions as main_div ON div.f_division = main_div.id
	inner join dbo.sd_subscr as s ON rp.f_subscr = s.id
	inner join dbo.ss_address as ad ON rp.f_address = ad.id
	inner join dbo.es_scales as sc on imp.f_scale = sc.id
	where s.b_person = false and omr.d_date between _d_date_start and _d_date_end + interval '1 day'
	and (case when _f_main_division is null or _f_main_division = '' or _f_main_division = '-1' then 1=1 else _f_main_division::integer = main_div.id end) 
	and (case when _f_division is null or _f_division = '' or _f_division = '-1' then 1=1 else _f_division::integer = div.id end) 
	and (case when _f_subdivisions is null or _f_subdivisions = '' or _f_subdivisions = '-1' then 1=1 else rp.f_subdivision in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) end) 
	group by p.id
	order by p.n_order desc;
END

Function: rpt.cf_meters_by_person(_d_date_start date, _d_date_end date, _f_main_division text, _f_division text, _f_subdivisions text)

Returns: SET OF record

Language: PLPGSQL

Выгрузка показаний по ФЛ за период

/**
* @params {date} _d_date_start - дата начала периода
* @params {date} _d_date_end - дата окончания периода
* @params {integer} _f_main_division - филиал
* @params {integer} _f_division - отделение
* @params {text} _f_subdivisions - список участок
*
* @example
* [{ "action": "cf_meters_by_person", "method": "Select", "data": [{ "params": [_d_date_start, _d_date_end, _f_main_division, _f_division, _f_subdivisions] }], "type": "rpc", "tid": 0 }]
*/
DECLARE
	_d_period_start date;
	_d_period_end date;
BEGIN
	select _d_date_start, _d_date_end into _d_period_start, _d_period_end;

	RETURN QUERY select
		row_number() over(order by t.n_order desc) AS n_num, -- номер п/п
		* 
	from (select 		
		to_char(_d_period_start, 'dd.MM.YYYY') as d_period_start,
		to_char(_d_period_end, 'dd.MM.YYYY') as d_period_end,
		main_div.id as f_maindivision,
		div.id as f_division,
		rp.f_subdivision as f_subdivision,
		s.c_code as c_subscr, -- № л/сч (ККС)
		rp.imp_text as c_document_code, -- Код Договора
		d.link as c_sap_code, --Код ЕО SAP
		concat(coalesce(ad.c_region || ', ', ''), coalesce(ad.c_raion || ', ', ''), 
				coalesce(ad.c_city_name || ', ', ''), coalesce(ad.c_settlement_name, '')) as c_area_name, -- Нас. пункт
		ad.c_street_name as c_street_name, -- Улица
		ad.c_house_name as c_house_number, -- № дома
		ad.c_flat_name as c_appartament_number, -- № квартиры
		concat(s.c_name1, ' ', s.c_name2, ' ', s.c_name3) as c_owner, -- ФИО потребителя
		d.c_serial_number as c_device_number, -- Заводской № счетчика
		dt.c_name as c_device_model, -- Тип счетчика
		dt.n_digits as n_digits, -- Разрядность
		sc.c_name as c_scale_name, -- Вид тарифа
		to_char(imp.d_date_prev, 'dd.MM.YYYY') as c_date_prev, -- Дата предыдущих контрольных показаний
		REPLACE(round(imp.n_value_prev, ((dt.n_digits % floor(dt.n_digits)) * 10)::integer)::text, '.', ',') as c_value_prev, -- Предыдущие контролные показания
		to_char(omr.d_date, 'dd.MM.YYYY') as c_date_current, -- Фактическая дата снятия показаний
		REPLACE(round(omr.n_value, ((dt.n_digits % floor(dt.n_digits)) * 10)::integer)::text, '.', ',') as c_value_current, -- Показания прибора учета на дату снятия
		nullif(rr.c_notice,'') as c_notice, -- Примечание
		row_number() over(partition by rr.fn_point, imp.id order by rr.d_date desc) as n_row,
		rr.fn_user,
		p.n_order
	from dbo.ed_output_meter_readings as omr
	inner join dbo.ed_input_meter_readings as imp ON imp.id = omr.fn_meter_reading
	inner join core.cd_points as p ON omr.fn_point = p.id
	inner join core.cd_results as rr ON rr.id = omr.fn_result
	inner join dbo.ed_devices as d ON d.f_registr_pts = p.f_registr_pts
	inner join dbo.es_device_types as dt ON d.f_device_type = dt.id
	inner join dbo.ed_registr_pts as rp ON p.f_registr_pts = rp.id
	inner join core.sd_divisions as div ON rp.f_division = div.id
	left join core.sd_divisions as main_div ON div.f_division = main_div.id
	inner join dbo.sd_subscr as s ON rp.f_subscr = s.id
	inner join dbo.ss_address as ad ON rp.f_address = ad.id
	inner join dbo.es_scales as sc on imp.f_scale = sc.id
	where s.b_person and 
		  omr.d_date between _d_date_start and _d_date_end + interval '1 day'
	and (case when _f_main_division is null or _f_main_division = '' or _f_main_division = '-1' then 1=1 else _f_main_division::integer = main_div.id end) 
	and (case when _f_division is null or _f_division = '' or _f_division = '-1' then 1=1 else _f_division::integer = div.id end) 
	and (case when _f_subdivisions is null or _f_subdivisions = '' or _f_subdivisions = '-1' then 1=1 else rp.f_subdivision in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) end) 
	--group by p.id
		 ) as t
	where t.n_row = 1
	order by t.n_order desc;
END

Function: rpt.cf_route_statistics(_d_date_start date, _d_date_end date, _f_maindivisions text, _f_divisions text, _f_subdivisions text, _c_substation text, _c_line_substation text, _c_tp text, _f_user text, _f_route_types text)

Returns: SET OF record

Language: PLPGSQL

Отчет "Статистика отработки маршрутов"


DECLARE
	_METER_REDINGS 		int4;		-- Снятие показаний
	_CHECK 				int4;		-- Проверка
	_LIMIT 				int4;		-- Ограничение
	_RENEW 				int4;		-- Возобновление
	_SETUP 				int4; 		-- Установка
	_REPLACE 			int4; 		-- Замена

	_CMR 				int4; 		-- Акт снятия контрольного показания
	_OOV 				int4; 		-- Отказ от выполнения
	_AIP 				int4; 		-- Акт инструментальной проверки
	_AVE 				int4; 		-- Акт возобновления энергоснабжения
	_AVOE 				int4; 		-- Акт о введении ограничения режима потребления
	_ABUP 				int4; 		-- Акт о безучетном потреблении

BEGIN
	
	select c.id 	into _METER_REDINGS from core.cs_point_types as c 		where c.c_const = 'METER_REDINGS';
	select c.id 	into _CHECK 		from core.cs_point_types as c 		where c.c_const = 'CHECK';
	select c.id 	into _LIMIT 		from core.cs_point_types as c 		where c.c_const = 'LIMIT';
	select c.id 	into _RENEW 		from core.cs_point_types as c 		where c.c_const = 'RENEW';
	select c.id 	into _SETUP 		from core.cs_point_types as c 		where c.c_const = 'SETUP';
	select c.id 	into _REPLACE 		from core.cs_point_types as c 		where c.c_const = 'REPLACE';
	
	select c.id 	into _CMR 			from core.cs_result_types as c 		where c.c_const = 'CMR' ;
	select c.id 	into _OOV 			from core.cs_result_types as c 		where c.c_const = 'OOV' ;
	select c.id 	into _AIP 			from core.cs_result_types as c 		where c.c_const = 'AIP' ;
	select c.id 	into _AVE 			from core.cs_result_types as c 		where c.c_const = 'AVE' ;
	select c.id 	into _AVOE 			from core.cs_result_types as c 		where c.c_const = 'AVOE';
	select c.id 	into _ABUP			from core.cs_result_types as c 		where c.c_const = 'ABUP';

	RETURN QUERY 
	-- отделения
	with subdivisions as (
		select 
			sdd.id 		as f_maindivision 				,	
 			sdd.c_name 	as c_maindivision 				, 	
 			sd.id 		as f_division 					,	
 			sd.c_name 	as c_division 					,	
 			ssd.id 		as f_subdivision 				, 	
 			ssd.c_name 	as c_subdivision 					
		from core.sd_subdivisions as ssd
			-- отделение
			inner join core.sd_divisions as sd
				on 	sd.id 		= ssd.f_division
			-- филиал
			inner join core.sd_divisions as sdd 
				on 	sdd.id 		= sd.f_division
		where 	1=1
			and case 	
					when 	_f_maindivisions is null or _f_maindivisions = '' or _f_maindivisions = '-1' then true
					else 	sdd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_maindivisions)) as t) 
				end
			and case 	
					when 	_f_divisions is null or _f_divisions = '' or _f_divisions = '-1' then true
					else 	sd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_divisions)) as t) 
				end
			and case 
					when 	_f_subdivisions is null or _f_subdivisions = '' or _f_subdivisions = '-1' then true 
					else 	ssd.id in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_subdivisions)) as t) 
				end
	),
	-- маршруты
	routes as (
		select 
			cr.id as f_route,
			cur.c_inspectors,
			case when crs.c_const = 'TRANSFERRED' then true else false end as b_plan
		from core.cd_routes as cr 
			inner join core.cd_userinroutes as uir 
				on 	uir.f_route 	= cr.id
			-- только определенные статусы маршрутов
			inner join core.cs_route_statuses as crs
				on 	crs.id 			= cr.f_status
				and crs.c_const 	in ('TRANSFERRED', 'RECEIVED', 'PROCCESS', 'DONED', 'NOT_CONFIRMED', 'CONFIRMED', 'EXPIRED', 'CANCEL', 'EXPORT')
			-- вся бригада
			inner join (
				select 
					cur.f_route,
					string_agg(concat(pu.c_last_name, ' ', left(pu.c_first_name,1) || '.', left(pu.c_middle_name, 1) || '.'), ',') as c_inspectors
				from core.cd_userinroutes as cur
					inner join core.pd_users as pu
						on 	pu.id 		= cur.f_user
				group by cur.f_route
			) as cur
				on 	cur.f_route 	= cr.id
		where 	1=1
			and case 
					when 	_f_user is null or _f_user = '' or _f_user = '-1' then true
					else 	uir.f_user in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_user)) as t) end
			and cr.d_date_start >= _d_date_start 
			and _d_date_end 	<= (CASE WHEN cr.b_extended THEN cr.d_extended ELSE cr.d_date_end END)
		group by cr.id, cur.c_inspectors, case when crs.c_const = 'TRANSFERRED' then true else false end
	),
	-- точки учета
	registr_pts as (
		select 
			cp.id 				as f_point,
			cp.f_route 			as f_route,
			cp.f_registr_pts 	as f_registr_pts,
			cp.f_type 			as f_type,
			ssd.f_maindivision 				,	
 			ssd.c_maindivision 				, 	
 			ssd.f_division 					,	
	 		ssd.c_division 					,	
	 		ssd.f_subdivision 				, 	
	 		ssd.c_subdivision 				,
	 		erp.c_substation 				,
 			erp.c_line_substation 			,
 			erp.c_tp 						 		
		from routes as r
			-- точки
			inner join core.cd_points as cp
				on 	cp.f_route 		= r.f_route
				and cp.f_type 		in (_METER_REDINGS, _CHECK,	_LIMIT, _RENEW, _SETUP, _REPLACE)	-- только определенные виды работ 
			-- учетные показатели
			inner join dbo.ed_registr_pts as erp
				on 	erp.id 			= cp.f_registr_pts
			-- фильтр по участкам
			inner join subdivisions as ssd 
				on 	ssd.f_subdivision	= erp.f_subdivision
				and ssd.f_division 		= erp.f_division
		where 	1=1
			-- фильтр по типам работ
			and case 
					when 	nullif(trim(_f_route_types), '') is null or _f_route_types = '-1' then true
					else 	cp.f_type in (select t.value::integer from json_array_elements_text(rpt.sf_rpt_csv_to_json(_f_route_types)) as t) end
			-- фильтр по подстанции
			and case 
					when 	nullif(trim(_c_substation), '') is null or _c_substation = '-1' then true 
					else 	lower(erp.c_substation) 	like '%'|| lower(trim(_c_substation)) ||'%'
				end
			-- фильтр по фидеру 6-10кВ
			and case 
					when 	nullif(trim(_c_line_substation), '') is null or _c_line_substation = '-1' then true
					else 	lower(erp.c_line_substation) like '%' || lower(trim(_c_line_substation)) || '%'
				end
			-- фильтр по ТП
			and case 
					when 	nullif(trim(_c_tp), '') is null or _c_tp = '-1' then true
					else 	lower(erp.c_tp) like '%' || lower(trim(_c_tp)) || '%'
				end
	),
	results as (
		select 
			erp.f_point,
			--наличие актов определенного типа по строке задания
			max(case when cr.fn_type = _CMR		then 1 else 0 end)		AS n_cmr,
			max(case when cr.fn_type = _OOV		then 1 else 0 end)		AS n_oov,
			max(case when cr.fn_type = _AIP		then 1 else 0 end)		AS n_aip,
			max(case when cr.fn_type = _AVE		then 1 else 0 end)		AS n_ave,
			max(case when cr.fn_type = _AVOE	then 1 else 0 end)		AS n_avoe,
			max(case when cr.fn_type = _ABUP	then 1 else 0 end)		AS n_abup
		from registr_pts as erp
			inner join core.cd_results as cr
				on 	cr.fn_point 	= erp.f_point
		group by erp.f_point
	)
	-- итоговый вывод
	select 
		to_char(_d_date_start, 	'dd.MM.YYYY'::text) as d_date_start,
		to_char(_d_date_end, 	'dd.MM.YYYY'::text) as d_date_end,
		erp.f_maindivision 				,	
 		erp.c_maindivision 				, 	
 		erp.f_division 					,	
 		erp.c_division 					,	
 		erp.f_subdivision 				, 	
 		erp.c_subdivision 				, 
		r.c_inspectors 					,
		erp.c_substation 				,
 		erp.c_line_substation 			,
 		erp.c_tp 						,
		-- Снятие показаний
		count(case when erp.f_type = _METER_REDINGS and r.b_plan					then erp.f_registr_pts end) as n_meter_redings_plan,
		count(case when erp.f_type = _METER_REDINGS and cr.n_cmr = 1 				then erp.f_registr_pts end) as n_meter_redings_cmr,
		count(case when erp.f_type = _METER_REDINGS and cr.n_oov = 1 				then erp.f_registr_pts end) as n_meter_redings_oov,
		count(case when erp.f_type = _METER_REDINGS and cr.f_point is not null 		then erp.f_registr_pts end) as n_meter_redings_done,
		-- Проверки
		count(case when erp.f_type = _CHECK and r.b_plan							then erp.f_registr_pts end) as n_check_plan,
		count(case when erp.f_type = _CHECK and cr.n_aip = 1 						then erp.f_registr_pts end) as n_check_aip,
		count(case when erp.f_type = _CHECK and cr.n_abup = 1 						then erp.f_registr_pts end) as n_check_abup,
		count(case when erp.f_type = _CHECK and cr.n_oov = 1 						then erp.f_registr_pts end) as n_check_oov,
		count(case when erp.f_type = _CHECK and cr.f_point is not null 				then erp.f_registr_pts end) as n_check_done,
		-- Допуск в эксплуатацию
 		count(case when erp.f_type =_SETUP				 and r.b_plan				then erp.f_registr_pts end)	n_permission_setup_plan		,
		count(case when erp.f_type = _REPLACE			 and r.b_plan				then erp.f_registr_pts end)	n_permission_replace_plan		,
		count(case when erp.f_type = _REPLACE			 and cr.n_aip = 1 			then erp.f_registr_pts end)	n_permission_aip	,
		count(case when erp.f_type = _REPLACE			 and cr.n_abup = 1 			then erp.f_registr_pts end)	n_permission_abup	,
		count(case when erp.f_type in (_SETUP, _REPLACE) and cr.n_oov = 1			then erp.f_registr_pts end)	n_permission_oov	,
		count(case when erp.f_type in (_SETUP, _REPLACE) and cr.f_point is not null	then erp.f_registr_pts end)	n_permission_done	,
		-- Ограничение и возобновление 
		count(case when erp.f_type =_LIMIT				and r.b_plan				then erp.f_registr_pts end)	n_limit_limit_plan,
		count(case when erp.f_type =_RENEW				and r.b_plan				then erp.f_registr_pts end)	n_limit_renew_plan,
		count(case when erp.f_type =_LIMIT				and cr.n_avoe = 1			then erp.f_registr_pts end)	n_limit_limit,
		count(case when erp.f_type =_RENEW				and cr.n_ave = 1			then erp.f_registr_pts end)	n_limit_renew,
		count(case when erp.f_type =_LIMIT				and cr.n_oov = 1			then erp.f_registr_pts end)	n_limit_oov,
		count(case when erp.f_type in (_LIMIT, _RENEW)	and cr.f_point is not null	then erp.f_registr_pts end)	n_limit_done
	from registr_pts as erp 
		inner join routes as r
			on 	r.f_route 		= erp.f_route
		-- результаты работ
		left join results as cr
			on 	cr.f_point		= erp.f_point
	group by 
		erp.f_maindivision 				,	
 		erp.c_maindivision 				, 	
 		erp.f_division 					,	
 		erp.c_division 					,	
 		erp.f_subdivision 				, 	
 		erp.c_subdivision 				, 
 		erp.c_substation 				,
 		erp.c_line_substation 			,
 		erp.c_tp 						,
		r.c_inspectors 							
	;

END

Function: rpt.sf_rpt_csv_to_json(_csv text)

Returns: json

Language: PLV8

Преобразование csv в json

/**
* @params {text} _csv - входная csv строка
* @returns {json} JSON
*/
try {
		var data = _csv.split(',');
		return JSON.stringify(data);
	} catch(e) { 
		return JSON.stringify([]);
	}

Generated by PostgreSQL Autodoc

W3C HTML 4.01 Strict