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 ( + + {formTitle()} + theme.palette.grey[500] + }} + > + close + + + {curStatus == Statuses.DELETE || curStatus == Statuses.COLUMNROW_DELETE ? ( + curStatus == Statuses.DELETE ? ( + Вы хотите удалить раздел {curName}? + ) : ( + Вы хотите удалить показатель раздела {curName}? + ) + ) : ( +
+ {curStatus != Statuses.COLUMNROW_EDIT ? ( + + ) : null} + + {curStatus == Statuses.COLUMNROW_CREATE ? ( +
+ + +
+ ) : null} +
+ )} +
+ + {renderSwitch()} + + +
+ ); +}; + +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 ( + + ); +}; + +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