diff --git a/app/panels/rrp_conf_editor/custom_dialog.js b/app/panels/rrp_conf_editor/custom_dialog.js
new file mode 100644
index 0000000..ec21389
--- /dev/null
+++ b/app/panels/rrp_conf_editor/custom_dialog.js
@@ -0,0 +1,155 @@
+/*
+ Кастомный Dialog
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Dialog, DialogTitle, IconButton, Icon, DialogContent, Typography, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
+import { CustomFormControl } from "./custom_form_control"; //Кастомные строки ввода
+import { Statuses, STYLES } from "./layouts"; //Статусы и стили диалогового окна
+
+//-----------
+//Тело модуля
+//-----------
+
+const CustomDialog = props => {
+ const {
+ formOpen,
+ closeForm,
+ curStatus,
+ curCode,
+ curName,
+ curColCode,
+ curRowCode,
+ btnOkClick,
+ codeOnChange,
+ nameOnChange,
+ dictColumnClick,
+ dictRowClick
+ } = props;
+
+ //Формирование заголовка диалогового окна
+ const formTitle = () => {
+ switch (curStatus) {
+ case Statuses.CREATE:
+ return "Добавление раздела";
+ case Statuses.EDIT:
+ return "Исправление раздела";
+ case Statuses.DELETE:
+ return "Удаление раздела";
+ case Statuses.COLUMNROW_CREATE:
+ return "Добавление показателя раздела";
+ case Statuses.COLUMNROW_EDIT:
+ return "Исправление показателя раздела";
+ case Statuses.COLUMNROW_DELETE:
+ return "Удаление показателя раздела";
+ }
+ };
+
+ //Отрисовка диалогового окна
+ const renderSwitch = () => {
+ var btnText = "";
+ switch (curStatus) {
+ case Statuses.CREATE:
+ case Statuses.COLUMNROW_CREATE:
+ btnText = "Добавить";
+ break;
+ case Statuses.EDIT:
+ case Statuses.COLUMNROW_EDIT:
+ btnText = "Исправить";
+ break;
+ case Statuses.DELETE:
+ case Statuses.COLUMNROW_DELETE:
+ btnText = "Удалить";
+ break;
+ }
+ return (
+
+ );
+ };
+
+ return (
+
+ );
+};
+
+CustomDialog.propTypes = {
+ formOpen: PropTypes.bool.isRequired,
+ closeForm: PropTypes.func.isRequired,
+ curStatus: PropTypes.oneOf(Object.values(Statuses).filter(x => typeof x === "number")),
+ curCode: PropTypes.string,
+ curName: PropTypes.string,
+ curColCode: PropTypes.string,
+ curRowCode: PropTypes.string,
+ btnOkClick: PropTypes.func.isRequired,
+ codeOnChange: PropTypes.func.isRequired,
+ nameOnChange: PropTypes.func.isRequired,
+ dictColumnClick: PropTypes.func.isRequired,
+ dictRowClick: PropTypes.func.isRequired
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { CustomDialog };
diff --git a/app/panels/rrp_conf_editor/custom_form_control.js b/app/panels/rrp_conf_editor/custom_form_control.js
new file mode 100644
index 0000000..2e9cc01
--- /dev/null
+++ b/app/panels/rrp_conf_editor/custom_form_control.js
@@ -0,0 +1,58 @@
+/*
+ Кастомный FormControl
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box, FormControl, InputLabel, OutlinedInput, InputAdornment, IconButton, Icon } from "@mui/material"; //Интерфейсные компоненты
+import { STYLES } from "./layouts"; //Стили диалогового окна
+
+//-----------
+//Тело модуля
+//-----------
+
+const CustomFormControl = props => {
+ const { elementCode, elementValue, labelText, changeFunc, withDictionary, ...other } = props;
+
+ return (
+
+
+ {labelText}
+ changeFunc(e.target.value) : null}
+ aria-describedby={`${elementCode}-outlined-helper-text`}
+ label={labelText}
+ endAdornment={
+ withDictionary ? (
+
+
+ list
+
+
+ ) : null
+ }
+ />
+
+
+ );
+};
+
+CustomFormControl.propTypes = {
+ elementCode: PropTypes.string.isRequired,
+ elementValue: PropTypes.string,
+ labelText: PropTypes.string.isRequired,
+ changeFunc: PropTypes.func.isRequired,
+ withDictionary: PropTypes.bool
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { CustomFormControl };
diff --git a/app/panels/rrp_conf_editor/custom_tab_panel.js b/app/panels/rrp_conf_editor/custom_tab_panel.js
new file mode 100644
index 0000000..083db8e
--- /dev/null
+++ b/app/panels/rrp_conf_editor/custom_tab_panel.js
@@ -0,0 +1,41 @@
+/*
+ Кастомный Tab
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box, Typography } from "@mui/material"; //Интерфейсные компоненты
+
+//-----------
+//Тело модуля
+//-----------
+
+const CustomTabPanel = props => {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && (
+
+ {children}
+
+ )}
+
+ );
+};
+
+CustomTabPanel.propTypes = {
+ children: PropTypes.node,
+ index: PropTypes.number.isRequired,
+ value: PropTypes.number.isRequired
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { CustomTabPanel };
diff --git a/app/panels/rrp_conf_editor/index.js b/app/panels/rrp_conf_editor/index.js
new file mode 100644
index 0000000..f1804e9
--- /dev/null
+++ b/app/panels/rrp_conf_editor/index.js
@@ -0,0 +1,16 @@
+/*
+ Парус 8 - Панели мониторинга - Редактор настройки регламентированного отчёта
+ Панель мониторинга: Точка входа
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import { RrpConfEditor } from "./rrp_conf_editor"; //Корневая панель выполнения работ
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export const RootClass = RrpConfEditor;
\ No newline at end of file
diff --git a/app/panels/rrp_conf_editor/layouts.js b/app/panels/rrp_conf_editor/layouts.js
new file mode 100644
index 0000000..7e968df
--- /dev/null
+++ b/app/panels/rrp_conf_editor/layouts.js
@@ -0,0 +1,46 @@
+/*
+ Парус 8 -
+ Дополнительная разметка и вёрстка клиентских элементов
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import { Stack, IconButton, Icon, Typography } from "@mui/material"; //Интерфейсные компоненты
+
+//---------
+//Константы
+//---------
+
+export const STYLES = {
+ DIALOG_WINDOW_WIDTH: { width: 400 },
+ PADDING_DIALOG_BUTTONS_RIGHT: { paddingRight: "32px" }
+};
+
+//Статусы диалогового окна
+export const Statuses = { CREATE: 0, EDIT: 1, DELETE: 2, COLUMNROW_CREATE: 3, COLUMNROW_EDIT: 4, COLUMNROW_DELETE: 5 };
+
+//-----------
+//Тело модуля
+//-----------
+
+//Генерация представления ячейки c данными
+export const dataCellRender = ({ row, columnDef }, editCR, deleteCR) => {
+ let data = row[columnDef.name];
+ columnDef.name != "SROW_NAME" && data != undefined && columnDef.visible == true
+ ? (data = (
+
+ {row[columnDef.name]}
+ editCR(row["NRN_" + columnDef.name.substring(5)], row[columnDef.name])}>
+ edit
+
+ deleteCR(row["NRN_" + columnDef.name.substring(5)], row[columnDef.name])}>
+ delete
+
+
+ ))
+ : null;
+ return { data };
+};
diff --git a/app/panels/rrp_conf_editor/rrp_conf_editor.js b/app/panels/rrp_conf_editor/rrp_conf_editor.js
new file mode 100644
index 0000000..3cdc7db
--- /dev/null
+++ b/app/panels/rrp_conf_editor/rrp_conf_editor.js
@@ -0,0 +1,481 @@
+/*
+ Парус 8 - Редактор настройки регламентированного отчёта
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useCallback, useContext, useState, useEffect } from "react"; //Классы React
+import { Box, Tab, Tabs, IconButton, Icon, Stack, Button } from "@mui/material"; //Интерфейсные компоненты
+import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
+import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
+import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
+import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
+import { CustomTabPanel } from "./custom_tab_panel"; //Кастомный Tab
+import { ApplicationСtx } from "../../context/application"; //Контекст приложения
+import { Statuses, dataCellRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
+import { CustomDialog } from "./custom_dialog"; //Кастомное диалоговое окно
+
+//-----------
+//Тело модуля
+//-----------
+
+//Редактор настройки регламентированного отчёта
+const RrpConfEditor = () => {
+ const dataGrid = {
+ rn: 0,
+ code: "",
+ name: "",
+ dataLoaded: false,
+ columnsDef: [],
+ groups: [],
+ rows: [],
+ reload: false
+ };
+
+ //Собственное состояние
+ const [rrpDoc, setRrpDoc] = useState({
+ docLoaded: false,
+ sections: [],
+ reload: true
+ });
+
+ //Состояние массива данных разделов
+ const [dataGrids] = useState([]);
+
+ //Состояние раздела
+ const [tabValue, setTabValue] = useState("");
+
+ //Состояние открытия диалогового окна
+ const [formOpen, setForm] = useState(false);
+
+ //Состояние диалогового окна
+ const [formData, setFormData] = useState({
+ filled: false,
+ rn: "",
+ prn: "",
+ sctnName: "",
+ sctnCode: "",
+ status: "",
+ code: "",
+ name: "",
+ colName: "",
+ colCode: "",
+ colVCode: "",
+ colVRn: 0,
+ rowName: "",
+ rowCode: "",
+ rowVCode: "",
+ rowVRn: 0
+ });
+
+ //Открытие диалогового окна
+ const openForm = () => {
+ setForm(true);
+ };
+
+ //Закрытие диалогового окна
+ const closeForm = () => {
+ setForm(false);
+ };
+
+ //Очистка диалогового окна
+ const clearFormData = () => {
+ setFormData({
+ rn: "",
+ code: "",
+ name: ""
+ });
+ };
+
+ //Подключение к контексту взаимодействия с сервером
+ const { executeStored } = useContext(BackEndСtx);
+
+ //Подключение к контексту приложения
+ const { pOnlineShowDictionary } = useContext(ApplicationСtx);
+
+ //Подключение к контексту навигации
+ const { getNavigationSearch } = useContext(NavigationCtx);
+
+ //Переключение раздела
+ const handleChange = (event, newValue) => {
+ setTabValue(newValue);
+ };
+
+ //Отработка нажатия на кнопку добавления секции
+ const addSectionClick = () => {
+ setFormData({ status: Statuses.CREATE, prn: Number(getNavigationSearch().NRN) });
+ openForm();
+ };
+
+ //Отработка нажатия на кнопку исправления секции
+ const editSectionClick = (rn, code, name) => {
+ setFormData({ rn: rn, code: code, name: name, status: Statuses.EDIT });
+ openForm();
+ };
+
+ //Отработка нажатия на кнопку удаления секции
+ const deleteSectionClick = (rn, code, name) => {
+ setFormData({ rn: rn, code: code, name: name, status: Statuses.DELETE });
+ openForm();
+ };
+
+ //Отработка нажатия на кнопку добавления показателя раздела
+ const addColumnRowClick = (prn, sctnCode, sctnName) => {
+ setFormData({ status: Statuses.COLUMNROW_CREATE, prn: prn, sctnCode: sctnCode, sctnName: sctnName });
+ openForm();
+ };
+
+ //Отработка нажатия на кнопку исправления показателя раздела
+ const editColumnRowClick = (rn, name) => {
+ setFormData({ status: Statuses.COLUMNROW_EDIT, rn: rn, name: name });
+ openForm();
+ };
+
+ //Отработка нажатия на кнопку удаления показателя раздела
+ const deleteColumnRowClick = (rn, name) => {
+ setFormData({ status: Statuses.COLUMNROW_DELETE, rn: rn, name: name });
+ openForm();
+ };
+
+ //Отработка нажатия на словарь граф
+ const dictColumnClick = () => {
+ pOnlineShowDictionary({
+ unitCode: "RRPColumn",
+ callBack: res =>
+ res.success === true
+ ? setFormData(pv => ({
+ ...pv,
+ colCode: res.outParameters.out_CODE,
+ colVCode: res.outParameters.out_RRPVERSION_CODE,
+ colVRn: res.outParameters.out_RRPVERSION
+ }))
+ : null
+ });
+ };
+
+ //Отработка нажатия на словарь строк
+ const dictRowClick = () => {
+ pOnlineShowDictionary({
+ unitCode: "RRPRow",
+ callBack: res =>
+ res.success === true
+ ? setFormData(pv => ({
+ ...pv,
+ rowCode: res.outParameters.out_CODE,
+ rowVCode: res.outParameters.out_RRPVERSION_CODE,
+ rowVRn: res.outParameters.out_RRPVERSION
+ }))
+ : null
+ });
+ };
+
+ //Нажатие на кнопку подтверждения создания/исправления/удаления на форме
+ const formBtnOkClick = () => {
+ let formStateProps = {};
+ if (formData.status === (Statuses.CREATE || Statuses.EDIT || Statuses.COLUMNROW_CREATE))
+ formStateProps = { ...formStateProps, code: document.querySelector("#code-outlined").value };
+ if (formData.status === (Statuses.CREATE || Statuses.EDIT || Statuses.COLUMNROW_CREATE || Statuses.COLUMNROW_EDIT))
+ formStateProps = { ...formStateProps, name: document.querySelector("#name-outlined").value };
+ setFormData(pv => ({
+ ...pv,
+ ...formStateProps,
+ filled: true
+ }));
+ closeForm();
+ };
+
+ //Формирование разделов
+ const a11yProps = index => {
+ return {
+ id: `simple-tab-${index}`,
+ "aria-controls": `simple-tabpanel-${index}`
+ };
+ };
+
+ //Отработка изменений в разделе или показателе раздела
+ const changeSections = useCallback(async () => {
+ if (formData.filled) {
+ switch (formData.status) {
+ case Statuses.CREATE:
+ insertSections();
+ clearFormData();
+ break;
+ case Statuses.EDIT:
+ updateSections();
+ clearFormData();
+ break;
+ case Statuses.DELETE:
+ deleteSections();
+ clearFormData();
+ break;
+ case Statuses.COLUMNROW_CREATE:
+ addColumnRow();
+ clearFormData();
+ break;
+ case Statuses.COLUMNROW_EDIT:
+ editColumnRow();
+ clearFormData();
+ break;
+ case Statuses.COLUMNROW_DELETE:
+ deleteColumnRow();
+ clearFormData();
+ break;
+ }
+ setRrpDoc(pv => ({ ...pv, reload: true }));
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [formData]);
+
+ //Добавление раздела
+ const insertSections = useCallback(async () => {
+ const data = await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.INSERT_RRPCONF_SECTIONS",
+ args: {
+ NPRN: formData.prn,
+ SCODE: formData.code,
+ SNAME: formData.name
+ }
+ });
+ setFormData(pv => ({
+ ...pv,
+ rn: Number(data.NRN)
+ }));
+ }, [formData.prn, formData.code, formData.name, executeStored]);
+
+ //Исправление раздела
+ const updateSections = useCallback(async () => {
+ await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.UPDATE_RRPCONF_SECTIONS",
+ args: {
+ NRN: formData.rn,
+ SCODE: formData.code,
+ SNAME: formData.name
+ }
+ });
+ }, [formData.name, formData.code, formData.rn, executeStored]);
+
+ //Удаление раздела
+ const deleteSections = useCallback(async () => {
+ await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.DELETE_RRPCONF_SECTIONS",
+ args: {
+ NRN: formData.rn
+ }
+ });
+ }, [formData.rn, executeStored]);
+
+ //Добавление показателя раздела
+ const addColumnRow = useCallback(async () => {
+ await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.INSERT_RRPCONF_COLUMNROW",
+ args: {
+ NPRN: formData.prn,
+ SCODE: formData.code,
+ SNAME: formData.name,
+ SCOLCODE: formData.colCode,
+ SCOLVER: formData.colVCode,
+ SROWCODE: formData.rowCode,
+ SROWVER: formData.rowVCode
+ }
+ });
+ }, [executeStored, formData.code, formData.colVCode, formData.colCode, formData.name, formData.prn, formData.rowCode, formData.rowVCode]);
+
+ //Исправление показателя раздела
+ const editColumnRow = useCallback(async () => {
+ await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.UPDATE_RRPCONF_COLUMNROW",
+ args: { NRN: formData.rn, SNAME: formData.name }
+ });
+ }, [executeStored, formData.name, formData.rn]);
+
+ //Удаление показателя раздела
+ const deleteColumnRow = useCallback(async () => {
+ await executeStored({ stored: "PKG_P8PANELS_RRPCONFED.DELETE_RRPCONF_COLUMNROW", args: { NRN: formData.rn } });
+ }, [executeStored, formData.rn]);
+
+ //Получение мнемокода и наименования показателя раздела
+ const getSctnMrkCodeName = useCallback(async () => {
+ const data = await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.GET_RRPCONFSCTNMRK_CODE_NAME",
+ args: { SSCTNCODE: formData.sctnCode, SROWCODE: formData.rowCode, SCOLUMNCODE: formData.colCode }
+ });
+ setFormData(pv => ({
+ ...pv,
+ code: data.SCODE,
+ name: data.SNAME
+ }));
+ }, [executeStored, formData.colCode, formData.rowCode, formData.sctnCode]);
+
+ //Загрузка данных разделов регламентированного отчёта
+ const loadData = useCallback(async () => {
+ if (rrpDoc.reload) {
+ //Переменная номера раздела с фокусом
+ let tabFocus = 0;
+ const data = await executeStored({
+ stored: "PKG_P8PANELS_RRPCONFED.GET_RRPCONF_SECTIONS",
+ args: {
+ NRN_RRPCONF: Number(getNavigationSearch().NRN)
+ },
+ respArg: "COUT"
+ });
+ //Флаг первой загрузки данных
+ let firstLoad = dataGrids.length == 0 ? true : false;
+ //Копирование массива уже загруженных разделов
+ let cloneDGs = dataGrids.slice();
+ //Массив из нескольких разделов и из одного
+ const sections = data.SECTIONS.length ? data.SECTIONS : [data.SECTIONS];
+ //Заполнение очередного раздела по шаблону
+ sections.map(s => {
+ let dg = {};
+ Object.assign(dg, dataGrid, {
+ rn: s.NRN,
+ code: s.SCODE,
+ name: s.SNAME,
+ dataLoaded: true,
+ columnsDef: [...(s.XDATA.XCOLUMNS_DEF || [])],
+ groups: [...(s.XDATA.XGROUPS || [])],
+ rows: [...(s.XDATA.XROWS || [])],
+ reload: false
+ });
+ //Ищем загружен ли уже раздел с таким же ид.
+ const dgItem = dataGrids.find(x => x.rn === dg.rn);
+ //Его индекс, если нет соответствия, то -1
+ let index = dataGrids.indexOf(dgItem);
+ //Если было соответствие
+ if (dgItem) {
+ //Если в нём не найдено изменений
+ if (JSON.stringify(dgItem, null, 4) === JSON.stringify(dg, null, 4)) {
+ //То из копированного массива его удаляем
+ cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dgItem.rn)), 1);
+ } else {
+ //Иначе обновляем раздел в массиве
+ dataGrids[index] = dg;
+ //Удаляем из копированного массива
+ cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dg.rn)), 1);
+ //Устанавливаем фокус на обновлённый раздел
+ tabFocus = index;
+ }
+ } else {
+ //Если раздел новый, то добавляем его в массив данных
+ dataGrids.push(dg);
+ //И устанавливаем на него фокус, если флаг первой загрузки = false
+ tabFocus = !firstLoad ? dataGrids.length - 1 : 0;
+ }
+ });
+ //Обходим разделы, что остались в копированном массиве (на удаление)
+ cloneDGs.map(s => {
+ let curIndex = dataGrids.indexOf(dataGrids.find(x => x.rn === s.rn));
+ //Устаревший раздел удаляем из массива данных
+ dataGrids.splice(curIndex, 1);
+ //Фокус на предшествующий раздел
+ tabFocus = curIndex - 1;
+ });
+ setRrpDoc(pv => ({
+ ...pv,
+ docLoaded: true,
+ reload: false,
+ sections: dataGrids
+ }));
+ setTabValue(tabFocus);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [rrpDoc.reload, rrpDoc.docLoaded, dataGrid.reload, dataGrid.docLoaded, executeStored]);
+
+ //При необходимости обновить данные таблицы
+ useEffect(() => {
+ loadData();
+ }, [rrpDoc.reload, dataGrid.reload, loadData]);
+
+ //Обновление при изменении разделов
+ useEffect(() => {
+ changeSections();
+ }, [changeSections]);
+
+ //Получение наименования и мнемокода показателя раздела при заполнении необходимых полей
+ useEffect(() => {
+ formData.status == Statuses.COLUMNROW_CREATE && formData.sctnName && formData.sctnCode && formData.colCode && formData.rowCode
+ ? getSctnMrkCodeName()
+ : null;
+ }, [formData.colCode, formData.rowCode, formData.sctnCode, formData.sctnName, formData.status, getSctnMrkCodeName]);
+
+ //Генерация содержимого
+ return (
+
+ {formOpen ? (
+ setFormData(pv => ({ ...pv, code: v }))}
+ nameOnChange={v => setFormData(pv => ({ ...pv, name: v }))}
+ dictColumnClick={dictColumnClick}
+ dictRowClick={dictRowClick}
+ />
+ ) : null}
+ {rrpDoc.docLoaded ? (
+
+
+
+ {rrpDoc.sections.map((s, i) => {
+ return (
+
+ {s.name}
+ editSectionClick(s.rn, s.code, s.name)}>
+ edit
+
+ deleteSectionClick(s.rn, s.code, s.name)}>
+ delete
+
+
+ }
+ wrapped
+ />
+ );
+ })}
+
+
+ add
+
+
+ {rrpDoc.sections.map((s, i) => {
+ return (
+
+
+ {s.dataLoaded ? (
+ dataCellRender({ ...prms }, editColumnRowClick, deleteColumnRowClick)}
+ />
+ ) : null}
+
+ );
+ })}
+
+ ) : null}
+
+ );
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { RrpConfEditor };
diff --git a/db/PKG_P8PANELS_RRPCONFED.pck b/db/PKG_P8PANELS_RRPCONFED.pck
new file mode 100644
index 0000000..74be876
--- /dev/null
+++ b/db/PKG_P8PANELS_RRPCONFED.pck
@@ -0,0 +1,435 @@
+create or replace package PKG_P8PANELS_RRPCONFED as
+
+ /* Добавление раздела регламентированного отчёта */
+ procedure INSERT_RRPCONF_SECTIONS
+ (
+ NPRN in number, -- Ид. настройки форм регламентированного отчёта
+ SCODE in varchar2, -- Мнемокод
+ SNAME in varchar2, -- Наименование
+ NRN out number -- Ид. созданной записи
+ );
+
+ /* Исправление раздела регламентированного отчёта */
+ procedure UPDATE_RRPCONF_SECTIONS
+ (
+ NRN in number, -- Ид. раздела
+ SCODE in varchar2, -- Мнемокод раздела
+ SNAME in varchar2 -- Наименование раздела
+ );
+
+ /* Удаление раздела регламентированного отчёта */
+ procedure DELETE_RRPCONF_SECTIONS
+ (
+ NRN in number -- Ид. раздела
+ );
+
+ /* Добавление показателя раздела регламентированного отчёта */
+ procedure INSERT_RRPCONF_COLUMNROW
+ (
+ NPRN in number, -- Ид. раздела
+ SCODE in varchar2, -- Мнемокод показателя раздела
+ SNAME in varchar2, -- Наименование показателя раздела
+ SCOLCODE in varchar2, -- Мнемокод графы
+ SCOLVER in varchar2, -- Мнемокод редакции графы
+ SROWCODE in varchar2, -- Мнемокод строки
+ SROWVER in varchar2, -- Мнемокод редакции строки
+ NRN out number -- Ид. созданной записи
+ );
+
+ /* Исправление показателя раздела регламентированного отчёта */
+ procedure UPDATE_RRPCONF_COLUMNROW
+ (
+ NRN in number, -- Ид. показателя раздела
+ SNAME in varchar2 -- Новое наименование
+ );
+
+ /* Удаление показателя раздела регламентированного отчёта */
+ procedure DELETE_RRPCONF_COLUMNROW
+ (
+ NRN in number -- Ид. показателя раздела
+ );
+
+ /* Формирование кода и наименования показателя раздела регламентированного отчёта */
+ procedure GET_RRPCONFSCTNMRK_CODE_NAME
+ (
+ SSCTNCODE in varchar2, -- Мнемокод раздела
+ SROWCODE in varchar2, -- Мнемокод строки
+ SCOLUMNCODE in varchar2, -- Мнемокод графы
+ SCODE out varchar2, -- Мнемокод показателя раздела
+ SNAME out varchar2 -- Наименование показателя раздела
+ );
+
+ /* Получение разделов регламентированного отчёта */
+ procedure GET_RRPCONF_SECTIONS
+ (
+ NRN_RRPCONF in number, -- Ид. нстройки форм регламентированного отчёта
+ COUT out clob -- Список разделов
+ );
+
+end PKG_P8PANELS_RRPCONFED;
+/
+create or replace package body PKG_P8PANELS_RRPCONFED as
+
+ /* Добавление раздела регламентированного отчёта */
+ procedure INSERT_RRPCONF_SECTIONS
+ (
+ NPRN in number, -- Ид. настройки форм регламентированного отчёта
+ SCODE in varchar2, -- Мнемокод
+ SNAME in varchar2, -- Наименование
+ NRN out number -- Ид. созданной записи
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ begin
+ P_RRPCONFSCTN_INSERT(NCOMPANY => NCOMPANY,
+ NPRN => NPRN,
+ SCODE => SCODE,
+ SNAME => SNAME,
+ SRRPCONFSCTN => null,
+ SRRPPRMGRP => null,
+ SNOTE => null,
+ NHTML_HIDE => 0,
+ NHTML_HIDE_NAME_COL => 0,
+ NHTML_MAKE_HIER_GRP => 0,
+ SCLSF_CODE => null,
+ NLINKS_UPDATE => 0,
+ NDUP_RN => null,
+ NRN => NRN);
+ end INSERT_RRPCONF_SECTIONS;
+
+ /* Исправление раздела регламентированного отчёта */
+ procedure UPDATE_RRPCONF_SECTIONS
+ (
+ NRN in number, -- Ид. раздела
+ SCODE in varchar2, -- Мнемокод раздела
+ SNAME in varchar2 -- Наименование раздела
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ begin
+ P_RRPCONFSCTN_UPDATE(NRN => NRN,
+ NCOMPANY => NCOMPANY,
+ SCODE => SCODE,
+ SNAME => SNAME,
+ SRRPCONFSCTN => null,
+ SRRPPRMGRP => null,
+ SNOTE => null,
+ NHTML_HIDE => 0,
+ NHTML_HIDE_NAME_COL => 0,
+ NHTML_MAKE_HIER_GRP => 0,
+ SCLSF_CODE => null,
+ NFORMULA_UPDATE => 0,
+ NMARK_UPDATE => 0);
+ end UPDATE_RRPCONF_SECTIONS;
+
+ /* Удаление раздела регламентированного отчёта */
+ procedure DELETE_RRPCONF_SECTIONS
+ (
+ NRN in number -- Ид. раздела
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ begin
+ P_RRPCONFSCTN_DELETE(NRN => NRN, NCOMPANY => NCOMPANY);
+ end DELETE_RRPCONF_SECTIONS;
+
+ /* Добавление показателя раздела регламентированного отчёта */
+ procedure INSERT_RRPCONF_COLUMNROW
+ (
+ NPRN in number, -- Ид. раздела
+ SCODE in varchar2, -- Мнемокод показателя раздела
+ SNAME in varchar2, -- Наименование показателя раздела
+ SCOLCODE in varchar2, -- Мнемокод графы
+ SCOLVER in varchar2, -- Мнемокод редакции графы
+ SROWCODE in varchar2, -- Мнемокод строки
+ SROWVER in varchar2, -- Мнемокод редакции строки
+ NRN out number -- Ид. созданной записи
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ NCOUNT PKG_STD.TNUMBER; -- Счётчик показателей раздела
+ begin
+ select count(*) into NCOUNT from RRPCONFSCTNMRK T where T.PRN = NPRN;
+ P_RRPCONFSCTNMRK_INSERT(NCOMPANY => NCOMPANY,
+ NPRN => NPRN,
+ NNUMB => NCOUNT + 1,
+ SCODE => SCODE,
+ SNAME => SNAME,
+ SRRPROW => SROWCODE,
+ SRRPVERSION_ROW => SROWVER,
+ SRRPCOLUMN => SCOLCODE,
+ SRRPVERSION_COLUMN => SCOLVER,
+ SPKG_ROW => null,
+ SPRC_ROW => null,
+ SPKG_COL => null,
+ SPRC_COL => null,
+ SRRPPRM => null,
+ NIGNORE_ZOOM => 0,
+ NIGNORE_SHARP => 0,
+ SCLSF_CODE => null,
+ SNOTE => null,
+ NDUP_RN => null,
+ NRN => NRN);
+ end INSERT_RRPCONF_COLUMNROW;
+
+ /* Исправление показателя раздела регламентированного отчёта */
+ procedure UPDATE_RRPCONF_COLUMNROW
+ (
+ NRN in number, -- Ид. показателя раздела
+ SNAME in varchar2 -- Новое наименование
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ NNUMB PKG_STD.TNUMBER; -- Номер показателя раздела
+ SCODE PKG_STD.TSTRING; -- Мнемокод показателя раздела
+ SCOLCODE PKG_STD.TSTRING; -- Мнемокод графы
+ SCOLVER PKG_STD.TSTRING; -- Мнемокод редакции графы
+ SROWCODE PKG_STD.TSTRING; -- Мнемокод строки
+ SROWVER PKG_STD.TSTRING; -- Мнемокод редакции строки
+ begin
+ select T.NUMB,
+ T.CODE,
+ R.CODE,
+ RVER.CODE,
+ C.CODE,
+ CVER.CODE
+ into NNUMB,
+ SCODE,
+ SROWCODE,
+ SROWVER,
+ SCOLCODE,
+ SCOLVER
+ from RRPCONFSCTNMRK T,
+ RRPCOLUMN C,
+ RRPVERSION CVER,
+ RRPROW R,
+ RRPVERSION RVER
+ where T.RN = NRN
+ and T.RRPROW = R.RN(+)
+ and R.RRPVERSION = RVER.RN(+)
+ and T.RRPCOLUMN = C.RN(+)
+ and C.RRPVERSION = CVER.RN(+);
+ P_RRPCONFSCTNMRK_UPDATE(NRN => NRN,
+ NCOMPANY => NCOMPANY,
+ NNUMB => NNUMB,
+ SCODE => SCODE,
+ SNAME => SNAME,
+ SRRPROW => SROWCODE,
+ SRRPVERSION_ROW => SROWVER,
+ SRRPCOLUMN => SCOLCODE,
+ SRRPVERSION_COLUMN => SCOLVER,
+ SPKG_ROW => null,
+ SPRC_ROW => null,
+ SPKG_COL => null,
+ SPRC_COL => null,
+ SRRPPRM => null,
+ NIGNORE_ZOOM => 0,
+ NIGNORE_SHARP => 0,
+ SCLSF_CODE => null,
+ NFORMULA_UPDATE => 0,
+ SNOTE => null);
+ end UPDATE_RRPCONF_COLUMNROW;
+
+ /* Удаление показателя раздела регламентированного отчёта */
+ procedure DELETE_RRPCONF_COLUMNROW
+ (
+ NRN in number -- Ид. показателя раздела
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ begin
+ P_RRPCONFSCTNMRK_DELETE(NCOMPANY => NCOMPANY, NRN => NRN);
+ end DELETE_RRPCONF_COLUMNROW;
+
+ /* Формирование кода и наименования показателя раздела регламентированного отчёта */
+ procedure GET_RRPCONFSCTNMRK_CODE_NAME
+ (
+ SSCTNCODE in varchar2, -- Мнемокод раздела
+ SROWCODE in varchar2, -- Мнемокод строки
+ SCOLUMNCODE in varchar2, -- Мнемокод графы
+ SCODE out varchar2, -- Мнемокод показателя раздела
+ SNAME out varchar2 -- Наименование показателя раздела
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
+ NROWRN PKG_STD.TREF; -- Ид. строки
+ NCOLUMNRN PKG_STD.TREF; -- Ид. графы
+ begin
+ P_RRPCONFSCTNMRK_MAKE_CODE(SRRPCONFSCTN => SSCTNCODE,
+ SRRPROW => SROWCODE,
+ SRRPCOLUMN => SCOLUMNCODE,
+ SCODE => SCODE);
+ select R.RN into NROWRN from RRPROW R where R.CODE = SROWCODE;
+ select C.RN into NCOLUMNRN from RRPCOLUMN C where C.CODE = SCOLUMNCODE;
+ P_RRPCONFSCTNMRK_MAKE_NAME(NCOMPANY => NCOMPANY,
+ NRRPROW => NROWRN,
+ NRRPCOLUMN => NCOLUMNRN,
+ NCHANGE_NAME => 1,
+ NCHANGE_NAME_PARENT => 0,
+ SNAME => SNAME);
+ end GET_RRPCONFSCTNMRK_CODE_NAME;
+
+ /* Получение разделов регламентированного отчёта */
+ procedure GET_RRPCONF_SECTIONS
+ (
+ NRN_RRPCONF in number, -- Ид. нстройки форм регламентированного отчёта
+ COUT out clob -- Список разделов
+ )
+ is
+ NVERSION PKG_STD.TREF; -- Рег. номер версии словаря контрагентов
+ RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
+ RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы
+ CDG clob; -- XML данных раздела
+ CCURCLOB clob; -- XML текущего раздела
+ NCURRN PKG_STD.TREF; -- Ид. текущего раздела
+ SCURCODE PKG_STD.TSTRING; -- Мнемокод текущего раздела
+ SCURNAME PKG_STD.TSTRING; -- Наименование текущего раздела
+ SCUR_ROW PKG_STD.TSTRING := 'default'; -- Текущая строка таблицы
+ CXML PKG_CONTVALLOC2NS.TCONTAINER; -- Контейнер для данных XML
+
+ /* Курсор с отбором показателей раздела по ид. раздела */
+ cursor C1 (NSCTN_RN in number) is
+ select T.RN NRN,
+ T.PRN NPRN,
+ T.RRPCONF NRRPCONF,
+ T.RRPPRM NRRPPRM,
+ T.CODE SCODE,
+ T.NAME SNAME,
+ R.CODE SROW_CODE,
+ R.NAME SROW_NAME,
+ C.CODE SCOLUMN_CODE,
+ C.NAME SCOLUMN_NAME
+ from RRPCONFSCTNMRK T,
+ RRPROW R,
+ RRPCOLUMN C
+ where T.PRN in (select T2.RN
+ from RRPCONFSCTN T2
+ where T2.PRN = NRN_RRPCONF
+ and T2.VERSION = NVERSION)
+ and T.VERSION = NVERSION
+ and T.RRPROW = R.RN (+)
+ and T.RRPCOLUMN = C.RN (+)
+ and T.PRN = NSCTN_RN
+ order by T.CODE;
+
+ /* Курсор с отбором граф раздела по ид. раздела */
+ cursor CN (NSCTN_RN in number) is
+ select distinct(C.CODE) SCOLUMN_CODE,
+ C.NAME SCOLUMN_NAME
+ from RRPCONFSCTNMRK T,
+ RRPCOLUMN C
+ where T.PRN in (select T2.RN
+ from RRPCONFSCTN T2
+ where T2.PRN = NRN_RRPCONF
+ and T2.VERSION = NVERSION)
+ and T.VERSION = NVERSION
+ and T.RRPCOLUMN = C.RN (+)
+ and T.PRN = NSCTN_RN
+ order by SCOLUMN_CODE;
+ begin
+ /* Очистка контейнера */
+ PKG_CONTVALLOC2NS.PURGE(RCONTAINER => CXML);
+ /* Определение версии раздела */
+ NVERSION := GET_SESSION_VERSION(SUNITCODE => 'RRPConfig');
+ /* Цикл по разделам настройки форм регламентированного отчёта */
+ for C in (select T.RN NRN,
+ T.VERSION NVERSION,
+ T.CRN NCRN,
+ T.PRN NPRN,
+ T.CODE SCODE,
+ T.NAME SNAME
+ from RRPCONFSCTN T
+ where T.PRN = NRN_RRPCONF
+ and T.VERSION = NVERSION)
+ loop
+ /* Инициализируем таблицу данных */
+ RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE();
+ /* Формируем структуру заголовка */
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SROW_NAME',
+ SCAPTION => 'Наименование строки',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ /* Цикл формирования колонок с графами */
+ for CL in CN(C.NRN)
+ loop
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SCOL_' || CL.SCOLUMN_CODE,
+ SCAPTION => CL.SCOLUMN_NAME,
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NRN_' || CL.SCOLUMN_CODE,
+ SCAPTION => CL.SCOLUMN_NAME || ' Идентификаторы',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
+ BVISIBLE => false);
+ end loop;
+ /* Для нового раздела очищаем переменную кода строки */
+ SCUR_ROW := 'default';
+ /* Инициализируем строку */
+ RDG_ROW := PKG_P8PANELS_VISUAL.TROW_MAKE();
+ /* Цикл заполнения строк данными о показателях раздела */
+ for CR in C1(C.NRN)
+ loop
+ /* Если новая строка */
+ if (SCUR_ROW != CR.SROW_CODE) then
+ /* Если строка не первая */
+ if (SCUR_ROW != 'default') then
+ /* Добавим строку для раздела */
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
+ /* Инициализируем новую строку */
+ RDG_ROW := PKG_P8PANELS_VISUAL.TROW_MAKE();
+ end if;
+ /* Запоминаем мнемокод новой строки */
+ SCUR_ROW := CR.SROW_CODE;
+ /* Заполняем наименование строки */
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SROW_NAME', SVALUE => CR.SROW_NAME);
+ end if;
+ /* Заполняем наименование показателя раздела */
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SCOL_' || CR.SCOLUMN_CODE, SVALUE => CR.SNAME);
+ /* Заполняем ид. показателя раздела */
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN_' || CR.SCOLUMN_CODE, NVALUE => CR.NRN);
+ end loop;
+ /* Добавим последнюю строку для раздела */
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
+ /* Сериализуем описание */
+ CDG := PKG_P8PANELS_VISUAL.TDATA_GRID_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
+ /* Заполняем контейнер данными о разделе */
+ PKG_CONTVALLOC2NS.PUTS(RCONTAINER => CXML, NTABID => C.NRN, SROWID => C.NRN || '_CODE', SVALUE => C.SCODE);
+ PKG_CONTVALLOC2NS.PUTS(RCONTAINER => CXML, NTABID => C.NRN, SROWID => C.NRN || '_NAME', SVALUE => C.SNAME);
+ PKG_CONTVALLOC2NS.PUTLC(RCONTAINER => CXML, NTABID => C.NRN, SROWID => C.NRN || '_CLOB', LCVALUE => CDG);
+ end loop;
+ /* Формируем XML с данными */
+ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);
+ PKG_XFAST.DOWN_NODE(SNAME => 'DATA');
+ /* Цикл по контейнеру с данными о разделах */
+ for X in 1 .. PKG_CONTVALLOC2NS.COUNT_(RCONTAINER => CXML)
+ loop
+ /* Ид. раздела */
+ if (X = 1) then
+ NCURRN := PKG_CONTVALLOC2NS.FIRST_(RCONTAINER => CXML);
+ else
+ NCURRN := PKG_CONTVALLOC2NS.NEXT_(RCONTAINER => CXML, NTABID => NCURRN);
+ end if;
+ /* Мнемокод раздела */
+ SCURCODE := PKG_CONTVALLOC2NS.GETS(RCONTAINER => CXML, NTABID => NCURRN, SROWID => NCURRN || '_CODE');
+ /* Наименование раздела */
+ SCURNAME := PKG_CONTVALLOC2NS.GETS(RCONTAINER => CXML, NTABID => NCURRN, SROWID => NCURRN || '_NAME');
+ /* Clob с показателями раздела */
+ CCURCLOB := PKG_CONTVALLOC2NS.GETLC(RCONTAINER => CXML, NTABID => NCURRN, SROWID => NCURRN || '_CLOB');
+ /* Формирование элемента XML с данными о разделе */
+ PKG_XFAST.DOWN_NODE(SNAME => 'SECTIONS');
+ PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => NCURRN);
+ PKG_XFAST.ATTR(SNAME => 'SCODE', SVALUE => SCURCODE);
+ PKG_XFAST.ATTR(SNAME => 'SNAME', SVALUE => SCURNAME);
+ PKG_XFAST.VALUE_XML(LCVALUE => CCURCLOB);
+ PKG_XFAST.UP();
+ end loop;
+ PKG_XFAST.UP();
+ /* Сериализуем описание */
+ COUT := PKG_XFAST.SERIALIZE_TO_CLOB();
+ PKG_XFAST.EPILOGUE();
+ /* Очистка контейнера */
+ PKG_CONTVALLOC2NS.PURGE(RCONTAINER => CXML);
+ end GET_RRPCONF_SECTIONS;
+
+end PKG_P8PANELS_RRPCONFED;
+/
diff --git a/db/grants.sql b/db/grants.sql
index 695a5a6..c12f082 100644
--- a/db/grants.sql
+++ b/db/grants.sql
@@ -2,3 +2,4 @@ grant execute on PKG_P8PANELS to public;
grant execute on PKG_P8PANELS_PROJECTS to public;
grant execute on PKG_P8PANELS_SAMPLES to public;
grant execute on PKG_P8PANELS_EQUIPSRV to public;
+grant execute on PKG_P8PANELS_RRPCONFED to public;
\ No newline at end of file