diff --git a/app/panels/rrp_conf_editor/components/rrp_section.js b/app/panels/rrp_conf_editor/components/rrp_section.js index 9b6b1fe..b64fe9e 100644 --- a/app/panels/rrp_conf_editor/components/rrp_section.js +++ b/app/panels/rrp_conf_editor/components/rrp_section.js @@ -9,7 +9,23 @@ import React, { useState } from "react"; //Классы React import PropTypes from "prop-types"; //Контроль свойств компонента -import { Box, IconButton, Icon, Dialog, DialogTitle, DialogContent, Typography, List, ListItem } from "@mui/material"; //Интерфейсные элементы +import { + Box, + IconButton, + Icon, + Dialog, + DialogTitle, + DialogContent, + Button, + Typography, + List, + ListItem, + Select, + FormControl, + InputLabel, + MenuItem, + DialogActions +} from "@mui/material"; //Интерфейсные элементы import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../../components/p8p_data_grid"; //Таблица данных import { P8P_DATA_GRID_CONFIG_PROPS } from "../../../config_wrapper"; //Подключение компонентов к настройкам приложения import { SectionTabPanel } from "./section_tab_panel"; //Компонент вкладки раздела @@ -67,7 +83,8 @@ const STYLES = { }, HELP_LIST_ITEM_DESC: { fontSize: "inherit" - } + }, + DIALOG_ACTIONS: { justifyContent: "end", paddingRight: "24px", paddingLeft: "24px" } }; //------------------------------------ @@ -136,6 +153,89 @@ HelpDialog.propTypes = { handleOpenHelpChange: PropTypes.func.isRequired }; +//Диалог сортировки +const SortDialog = ({ init, handleOpenSortChange, onOrderChange }) => { + //Собственное состояние сортировки + const [order, setOrder] = useState({ row: init.rowOrder ? init.rowOrder : 0, column: init.columnOrder ? init.columnOrder : 0 }); + + //Изменеие сортировки + const handleOrderChange = e => setOrder(pv => ({ ...pv, [e.target.name]: e.target.value })); + + //Нажатие на кнопку Ok + const handleOk = () => { + onOrderChange({ rowOrder: order.row, columnOrder: order.column }); + handleOpenSortChange(); + }; + + //Кнопка "Очистить", значения по умолчанию + const handleClear = () => { + setOrder({ row: 0, column: 0 }); + }; + + //Кнопка "Отмена" + const handleCancel = () => { + handleOpenSortChange(); + }; + + //Генерация содержимого + return ( + + + + + Сортировка + + + + close + + + + + + + + Строки + + + + + + Графы + + + + + + + + + + + ); +}; + +//Контроль свойств - Диалог сортировки +SortDialog.propTypes = { + init: PropTypes.object.isRequired, + handleOpenSortChange: PropTypes.func.isRequired, + onOrderChange: PropTypes.func.isRequired +}; + //----------- //Тело модуля //----------- @@ -145,6 +245,8 @@ const SectionTab = ({ section, tabValue, index, + order, + onOrderChange, containerProps, handleMarkAdd, handleReload, @@ -161,6 +263,14 @@ const SectionTab = ({ setOpenHelp(!openHelp); }; + //Состояние - диалог сортировки + const [openSort, setOpenSort] = useState(false); + + //Изменение состояния диалога сортировки + const handleOpenSortChange = () => { + setOpenSort(!openSort); + }; + //Генерация содержимого return ( <> @@ -175,6 +285,9 @@ const SectionTab = ({ + handleOpenSortChange()}> + sort + handleOpenHelpChange()}> help @@ -217,6 +330,7 @@ const SectionTab = ({ ) : null} + {openSort ? : null} {openHelp ? : null} ); @@ -227,6 +341,8 @@ SectionTab.propTypes = { section: PropTypes.object.isRequired, tabValue: PropTypes.number, index: PropTypes.number, + order: PropTypes.object.isRequired, + onOrderChange: PropTypes.func.isRequired, containerProps: PropTypes.object, handleMarkAdd: PropTypes.func, handleReload: PropTypes.func, diff --git a/app/panels/rrp_conf_editor/hooks.js b/app/panels/rrp_conf_editor/hooks.js index 8030d1d..72aedd9 100644 --- a/app/panels/rrp_conf_editor/hooks.js +++ b/app/panels/rrp_conf_editor/hooks.js @@ -39,7 +39,7 @@ const useWindowResize = () => { }; //Хук для настройки регламентированного отчета -const useConf = (currentTab, handleSectionChange) => { +const useConf = (currentTab, handleSectionChange, order) => { //Собственное состояние - таблица данных const dataGrid = { rn: 0, @@ -58,6 +58,7 @@ const useConf = (currentTab, handleSectionChange) => { const [rrpConf, setRrpConf] = useState({ docLoaded: false, sections: [], + orderChanged: false, reload: true }); @@ -76,103 +77,116 @@ const useConf = (currentTab, handleSectionChange) => { }, []); //Загрузка данных разделов регламентированного отчёта - const loadData = useCallback(async () => { - if (rrpConf.reload) { - //Переменная номера раздела с фокусом - let tabFocus = currentTab ? currentTab : 0; - const data = await executeStored({ - stored: "PKG_P8PANELS_RRPCONFED.RRPCONF_GET_SECTIONS", - args: { - NRN_RRPCONF: Number(getNavigationSearch().NRN) - }, - respArg: "COUT" - }); - //Флаг первой загрузки данных - let firstLoad = dataGrids.length == 0 ? true : false; - //Копирование массива уже загруженных разделов - let cloneDGs = dataGrids.slice(); - //Массив из нескольких разделов и из одного - const sections = data.SECTIONS ? (data.SECTIONS.length ? data.SECTIONS : [data.SECTIONS]) : []; - //Заполнение очередного раздела по шаблону - sections.map(s => { - let dg = {}; - Object.assign(dg, dataGrid, { - ...s.XDATA.XDATA_GRID, - rn: s.NRN, - code: s.SCODE, - name: s.SNAME, - delete_allow: s.NDELETE_ALLOW, - dataLoaded: true, - columnsDef: [...(s.XDATA.XDATA_GRID.columnsDef || [])], - groups: [...(s.XDATA.XDATA_GRID.groups || [])], - rows: [...(s.XDATA.XDATA_GRID.rows || [])], - reload: false + const loadData = useCallback( + async () => { + if (rrpConf.reload) { + //Переменная номера раздела с фокусом + let tabFocus = currentTab ? currentTab : 0; + const data = await executeStored({ + stored: "PKG_P8PANELS_RRPCONFED.RRPCONF_GET_SECTIONS", + args: { + NRN_RRPCONF: Number(getNavigationSearch().NRN), + NROW_ORDER: Number(order.rowOrder), + NCOL_ORDER: Number(order.columnOrder) + }, + respArg: "COUT" }); - //Если раздел имеет составы показателей - if (s.MARK_CNS.MARK_CN) { - //Обходим строки раздела - dg.rows.map(row => { - //Цикл по ключам строки - for (let key in row) { - //Если это ключ для группы составов показателей - if (key.match(/MARK_CNS_.*/)) { - //Считываем рег. номер показателя - let markRn = key.substring(9); - //Переносим из раздела - row[key] = Array.isArray(s.MARK_CNS.MARK_CN) - ? [...s.MARK_CNS.MARK_CN].filter(el => el.NPRN === row[`NMARK_RN_${markRn}`]) - : s.MARK_CNS.MARK_CN.NPRN === row[`NMARK_RN_${markRn}`] - ? [s.MARK_CNS.MARK_CN] - : null; + //Флаг первой загрузки данных + let firstLoad = dataGrids.length == 0 ? true : false; + //Копирование массива уже загруженных разделов + let cloneDGs = dataGrids.slice(); + //Массив из нескольких разделов и из одного + const sections = data.SECTIONS ? (data.SECTIONS.length ? data.SECTIONS : [data.SECTIONS]) : []; + //Заполнение очередного раздела по шаблону + sections + .sort((a, b) => a.SCODE - b.SCODE) + .map(s => { + let dg = {}; + Object.assign(dg, dataGrid, { + ...s.XDATA.XDATA_GRID, + rn: s.NRN, + code: s.SCODE, + name: s.SNAME, + delete_allow: s.NDELETE_ALLOW, + dataLoaded: true, + columnsDef: [...(s.XDATA.XDATA_GRID.columnsDef || [])], + groups: [...(s.XDATA.XDATA_GRID.groups || [])], + rows: [...(s.XDATA.XDATA_GRID.rows || [])], + reload: false + }); + //Если раздел имеет составы показателей + if (s.MARK_CNS.MARK_CN) { + //Обходим строки раздела + dg.rows.map(row => { + //Цикл по ключам строки + for (let key in row) { + //Если это ключ для группы составов показателей + if (key.match(/MARK_CNS_.*/)) { + //Считываем рег. номер показателя + let markRn = key.substring(9); + //Переносим из раздела + row[key] = Array.isArray(s.MARK_CNS.MARK_CN) + ? [...s.MARK_CNS.MARK_CN].filter(el => el.NPRN === row[`NMARK_RN_${markRn}`]) + : s.MARK_CNS.MARK_CN.NPRN === row[`NMARK_RN_${markRn}`] + ? [s.MARK_CNS.MARK_CN] + : null; + } + } + }); + } + //Ищем загружен ли уже раздел с таким же ид. + 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 = rrpConf.orderChanged ? 0 : index; } + } else { + //Если раздел новый, то добавляем его в массив данных + dataGrids.push(dg); + //И устанавливаем на него фокус, если флаг первой загрузки = false + tabFocus = !firstLoad ? dataGrids.length - 1 : 0; } }); - } - //Ищем загружен ли уже раздел с таким же ид. - 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); - //Фокус на предшествующий раздел - if (curIndex > 0) tabFocus = curIndex - 1; - //Иначе фокус на следующий, если был удалён первый раздел - else tabFocus = curIndex; - }); - setRrpConf(pv => ({ - ...pv, - docLoaded: true, - reload: false, - sections: dataGrids - })); - handleSectionChange(tabFocus); - } + //Обходим разделы, что остались в копированном массиве (на удаление) + cloneDGs.map(s => { + let curIndex = dataGrids.indexOf(dataGrids.find(x => x.rn === s.rn)); + //Устаревший раздел удаляем из массива данных + dataGrids.splice(curIndex, 1); + //Фокус на предшествующий раздел + if (curIndex > 0) tabFocus = curIndex - 1; + //Иначе фокус на следующий, если был удалён первый раздел + else tabFocus = curIndex; + }); + setRrpConf(pv => ({ + ...pv, + docLoaded: true, + orderChanged: false, + reload: false, + sections: dataGrids + })); + handleSectionChange(tabFocus); + } + }, // eslint-disable-next-line react-hooks/exhaustive-deps - }, [rrpConf.reload, rrpConf.docLoaded, dataGrid.reload, dataGrid.docLoaded, executeStored]); + [rrpConf.reload, rrpConf.docLoaded, dataGrid.reload, dataGrid.docLoaded, executeStored] + ); + + //При изменении сортировок + useEffect(() => { + setRrpConf(pv => ({ ...pv, orderChanged: true, reload: true })); + }, [order]); //При необходимости обновить данные таблицы useEffect(() => { diff --git a/app/panels/rrp_conf_editor/rrp_conf_editor.js b/app/panels/rrp_conf_editor/rrp_conf_editor.js index b579b01..f86e797 100644 --- a/app/panels/rrp_conf_editor/rrp_conf_editor.js +++ b/app/panels/rrp_conf_editor/rrp_conf_editor.js @@ -44,8 +44,14 @@ const RrpConfEditor = () => { //Состояние вкладки const [tabValue, handleSectionChange] = useTab(""); + //Состояние сортировки строк и граф + const [order, setOrder] = useState({ rowOrder: 0, columnOrder: 0 }); + + //Изменение состояния сортировки строк и граф + const handleOrder = newOrder => setOrder(newOrder); + //Состояние настройки - const [rrpConf, handleReload] = useConf(tabValue, handleSectionChange); + const [rrpConf, handleReload] = useConf(tabValue, handleSectionChange, order); //Функции открытия разделов const [handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert] = useRecOpen(handleReload); @@ -136,6 +142,8 @@ const RrpConfEditor = () => { section={s} tabValue={tabValue} index={i} + order={order} + onOrderChange={handleOrder} containerProps={{ height, pxOuterMenuH, pxPanelHeaderH, pxTabsH }} handleReload={handleReload} handleMarkOpen={handleMarkOpen} diff --git a/db/PKG_P8PANELS_RRPCONFED.pck b/db/PKG_P8PANELS_RRPCONFED.pck index 494de72..6c9ef47 100644 --- a/db/PKG_P8PANELS_RRPCONFED.pck +++ b/db/PKG_P8PANELS_RRPCONFED.pck @@ -3,23 +3,25 @@ create or replace package PKG_P8PANELS_RRPCONFED as /* Получение разделов регламентированного отчёта */ procedure RRPCONF_GET_SECTIONS ( - NRN_RRPCONF in number, -- Ид. нстройки форм регламентированного отчёта - COUT out clob -- Список разделов + NRN_RRPCONF in number, -- Рег. номер настройки форм регламентированного отчёта + NROW_ORDER in number := 0, -- Порядок сортировки строк + NCOL_ORDER in number := 0, -- Порядок сортировки граф + COUT out clob -- Список разделов ); /* Добавление раздела регламентированного отчёта */ procedure RRPCONFSCTN_INSERT ( - NPRN in number, -- Ид. настройки форм регламентированного отчёта + NPRN in number, -- Рег. номер настройки форм регламентированного отчёта SCODE in varchar2, -- Мнемокод SNAME in varchar2, -- Наименование - NRN out number -- Ид. созданной записи + NRN out number -- Рег. номер созданной записи ); /* Исправление раздела регламентированного отчёта */ procedure RRPCONFSCTN_UPDATE ( - NRN in number, -- Ид. раздела + NRN in number, -- Рег. номер раздела SCODE in varchar2, -- Мнемокод раздела SNAME in varchar2 -- Наименование раздела ); @@ -27,16 +29,16 @@ create or replace package PKG_P8PANELS_RRPCONFED as /* Удаление раздела регламентированного отчёта */ procedure RRPCONFSCTN_DELETE ( - NRN in number -- Ид. раздела + NRN in number -- Рег. номер раздела ); /* Получение кодов настройки, раздела и показателя раздела по ид. показателя раздела */ procedure RRPCONFSCTNMRK_GET_CODES ( - NRN in number, -- Ид. показателя раздела - SRRPCONF out varchar2, -- Код настройки формы регламентированного отчёта - SRRPCONFSCTN out varchar2, -- Код раздела - SRRPCONFSCTNMRK out varchar2 -- Код показателя раздела + NRN in number, -- Рег. номер показателя раздела + SRRPCONF out varchar2, -- Мнемокод настройки формы регламентированного отчёта + SRRPCONFSCTN out varchar2, -- Мнемокод раздела + SRRPCONFSCTNMRK out varchar2 -- Мнемокод показателя раздела ); /* Формирование кода и наименования показателя раздела регламентированного отчёта */ @@ -59,25 +61,25 @@ create or replace package PKG_P8PANELS_RRPCONFED as /* Добавление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_INSERT ( - NPRN in number, -- Ид. раздела + NPRN in number, -- Рег. номер раздела SCODE in varchar2, -- Мнемокод показателя раздела SNAME in varchar2, -- Наименование показателя раздела NRRPROW in number, -- Рег. номер строки NRRPCOLUMN in number, -- Рег. номер графы - NRN out number -- Ид. созданной записи + NRN out number -- Рег. номер созданной записи ); /* Исправление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_UPDATE ( - NRN in number, -- Ид. показателя раздела + NRN in number, -- Рег. номер показателя раздела SNAME in varchar2 -- Новое наименование ); /* Удаление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_DELETE ( - NRN in number -- Ид. показателя раздела + NRN in number -- Рег. номер показателя раздела ); end PKG_P8PANELS_RRPCONFED; @@ -778,7 +780,9 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Получение разделов регламентированного отчёта */ procedure RRPCONF_GET_SECTIONS ( - NRN_RRPCONF in number, -- Ид. нстройки форм регламентированного отчёта + NRN_RRPCONF in number, -- Рег. номер настройки форм регламентированного отчёта + NROW_ORDER in number := 0, -- Порядок сортировки строк + NCOL_ORDER in number := 0, -- Порядок сортировки граф COUT out clob -- Список разделов ) is @@ -794,58 +798,140 @@ create or replace package body PKG_P8PANELS_RRPCONFED as SSECTION_CODE PKG_STD.TSTRING; -- Мнемокод раздела настройки SSECTION_NAME PKG_STD.TSTRING; -- Наименование раздела настройки CSECTION_CLOB clob; -- Данные по разделу настройки + CSQL_ROWS clob; -- Запрос по строкам + SORDERS_R PKG_STD.TSTRING; -- Сортировка строк + ICURSOR_R integer; -- Курсор для исполнения запроса по строкам + NROW_RN PKG_STD.TREF; -- Рег. номер строки + NROW_POS PKG_STD.TNUMBER := 0; -- Позиция строки + SROW_CODE PKG_STD.TSTRING; -- Код строки + SROW_NAME PKG_STD.TSTRING; -- Наименование строки + CSQL_COLS clob; -- Запрос по графам + SORDERS_C PKG_STD.TSTRING; -- Сортировка граф + ICURSOR_C integer; -- Курсор для исполнения запроса по графам + NCOL_RN PKG_STD.TREF; -- Рег. номер графы + SCOL_CODE PKG_STD.TSTRING; -- Код графы + SCOL_NAME PKG_STD.TSTRING; -- Наименование графы + + /* Формирование текстового представления сортировки */ + function ORDER_TEXT_GET + ( + NORDER in number, -- Порядок сортировки + SALIAS in varchar2, -- Алиас таблицы + NTYPE in number -- Тип таблицы (0 - графы, 1 - строки) + ) return varchar2 -- Текстовое представление сортировки + is + SRESULT PKG_STD.TSTRING; -- Текстовое представление сортировки + STABLE_COLUMN_CODE PKG_STD.TSTRING; -- Наименование колонки таблицы, содержащую код + begin + /* Определяем наименование колонки, содержающую код */ + if (NTYPE = 0) then + /* Код графы */ + STABLE_COLUMN_CODE := 'COLUMN_CODE'; + else + /* Код графы */ + STABLE_COLUMN_CODE := 'ROW_CODE'; + end if; + /* Формируем представление сортировки */ + case NORDER + /* Код - номер сортировки - мнемокод */ + when 1 then + SRESULT := PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.' || STABLE_COLUMN_CODE || ', 40, ''0''),' || SALIAS || + '.SORT_NUMB,' || PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.CODE, 20, ''0'')'; + /* Мнемокод - номер сортировки - код */ + when 2 then + SRESULT := PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.CODE, 20, ''0''),' || SALIAS || '.SORT_NUMB,' || + PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.' || STABLE_COLUMN_CODE || ', 40, ''0'')'; + /* Номер сортировки - код - мнемокод */ + else + SRESULT := SALIAS || '.SORT_NUMB,' || PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.' || STABLE_COLUMN_CODE || + ', 40, ''0''),' || PKG_SQL_BUILD.LPAD_() || '(' || SALIAS || '.CODE, 20, ''0'')'; + end case; + /* Возвращаем результат */ + return SRESULT; + end ORDER_TEXT_GET; /* Инициализация колонок граф показателей */ procedure MARKS_COLUMNS_INIT ( RDG in out nocopy PKG_P8PANELS_VISUAL.TDG, -- Описание таблицы - NRRPCONFSCTN in number -- Рег. номер раздела + NRRPCONFSCTN in number, -- Рег. номер раздела + SORDER in varchar2 -- Сортировка ) is + CSQL clob; -- Запрос по графам показателей раздела + ICURSOR integer; -- Курсор для исполнения запроса по графам показателей раздела + SCOL_CODE PKG_STD.TSTRING; -- Мнемокод графы + SCOL_NAME PKG_STD.TSTRING; -- Наименование графы begin - /* Цикл по графам показателей раздела */ - for REC in (select C.CODE, - C.NAME - from RRPCONFSCTNMRK T, - RRPCOLUMN C - where T.PRN = NRRPCONFSCTN - and T.RRPCOLUMN = C.RN - group by C.RN, - C.CODE, - C.NAME - order by C.CODE) + /* Добавляем подсказку совместимости */ + CSQL := null; + CSQL := PKG_SQL_BUILD.COMPATIBLE(SSQL => CSQL); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => 'select C.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.NAME'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from RRPCONFSCTNMRK T,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' RRPCOLUMN C'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where T.PRN = ' || NRRPCONFSCTN); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and T.RRPCOLUMN = C.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' group by C.RN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.NAME,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.COLUMN_CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.SORT_NUMB'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' order by ' || SORDER); + /* Разбираем его */ + ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); + PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => CSQL); + /* Описываем структуру записи курсора */ + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 1); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 2); + /* Делаем выборку */ + if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then + null; + end if; + /* Обходим графы показателей раздела */ + while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0) loop + /* Считываем рег. номер строки */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR, IPOSITION => 1, SVALUE => SCOL_CODE); + /* Считываем код строки */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR, IPOSITION => 2, SVALUE => SCOL_NAME); /* Наименование графы */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, - SNAME => 'SCOL_' || REC.CODE, - SCAPTION => REC.NAME, + SNAME => 'SCOL_' || SCOL_CODE, + SCAPTION => SCOL_NAME, SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, NWIDTH => 200); /* Рег. номер графы */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, - SNAME => 'NCOL_RN_' || REC.CODE, - SCAPTION => REC.NAME || ' рег. номер', + SNAME => 'NCOL_RN_' || SCOL_CODE, + SCAPTION => SCOL_NAME || ' рег. номер', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BVISIBLE => false); /* Рег. номер показателя */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, - SNAME => 'NMARK_RN_' || REC.CODE, - SCAPTION => REC.NAME || ' рег. номер показателя', + SNAME => 'NMARK_RN_' || SCOL_CODE, + SCAPTION => SCOL_NAME || ' рег. номер показателя', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BVISIBLE => false); /* Мнемокод показателя */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, - SNAME => 'SMARK_CODE_' || REC.CODE, - SCAPTION => REC.NAME || ' мнемокод показателя', + SNAME => 'SMARK_CODE_' || SCOL_CODE, + SCAPTION => SCOL_NAME || ' мнемокод показателя', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); /* Для составов показтелей */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, - SNAME => 'MARK_CNS_' || REC.CODE, - SCAPTION => REC.NAME || ' состав показателя', + SNAME => 'MARK_CNS_' || SCOL_CODE, + SCAPTION => SCOL_NAME || ' состав показателя', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); end loop; + /* Освобождаем курсор */ + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); + exception + when others then + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); + raise; end MARKS_COLUMNS_INIT; /* Считывание показателя по строке/графе */ @@ -898,91 +984,159 @@ create or replace package body PKG_P8PANELS_RRPCONFED as loop /* Инициализируем таблицу данных */ RDG := PKG_P8PANELS_VISUAL.TDG_MAKE(BFIXED_HEADER => true, NFIXED_COLUMNS => 1); - /* Формируем структуру заголовка */ + /* Наименование строки */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SROW_NAME', SCAPTION => '', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, NWIDTH => 150); - /* Формируем структуру заголовка */ + /* Позиция строки */ + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NROW_POS', + SCAPTION => 'Позиция строки', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BVISIBLE => false); + /* Мнемокод строки */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SROW_CODE', SCAPTION => 'Мнемокод строки', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); - /* Формируем структуру заголовка */ + /* Рег. номер строки */ PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NROW_RN', SCAPTION => 'Рег. номер строки', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BVISIBLE => false); + /* Обнуляем счётчик позиции строки */ + NROW_POS := 0; /* Если раздел содержит показатели */ if (S.NMARKS_EXISTS = 1) then + /* Формируем текстовое представление сортировки графы */ + SORDERS_C := ORDER_TEXT_GET(NORDER => NCOL_ORDER, SALIAS => 'C', NTYPE => 0); /* Инициализируем колонки граф */ - MARKS_COLUMNS_INIT(RDG => RDG, NRRPCONFSCTN => S.NRN); - /* Обходим строки раздела */ - for R in (select R.RN, - R.CODE, - R.NAME - from RRPCONFSCTNMRK T, - RRPROW R - where T.PRN = S.NRN - and R.RN = T.RRPROW - group by R.RN, - R.CODE, - R.NAME, - R.ROW_CODE, - R.SORT_NUMB - order by R.SORT_NUMB, - LPAD(R.ROW_CODE, 40, '0'), - LPAD(R.CODE, 20, '0')) - loop - /* Заполняем наименование строки */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SROW_NAME', SVALUE => R.NAME, BCLEAR => true); - /* Заполняем мнемокод строки */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SROW_CODE', SVALUE => R.CODE); - /* Заполняем рег. номер строки */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NROW_RN', NVALUE => R.RN); - /* Обходим графы раздела */ - for C in (select C.RN, - C.CODE, - C.NAME - from RRPCONFSCTNMRK T, - RRPCOLUMN C - where T.PRN = S.NRN - and C.RN = T.RRPCOLUMN - group by C.RN, - C.CODE, - C.NAME, - C.COLUMN_CODE, - C.SORT_NUMB - order by C.SORT_NUMB, - LPAD(C.COLUMN_CODE, 40, '0'), - LPAD(C.CODE, 20, '0')) + MARKS_COLUMNS_INIT(RDG => RDG, NRRPCONFSCTN => S.NRN, SORDER => SORDERS_C); + begin + /* Формируем текстовое представление сортировки строки */ + SORDERS_R := ORDER_TEXT_GET(NORDER => NROW_ORDER, SALIAS => 'R', NTYPE => 1); + /* Добавляем подсказку совместимости */ + CSQL_ROWS := PKG_SQL_BUILD.COMPATIBLE(); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => 'select R.RN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.NAME'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' from RRPCONFSCTNMRK T,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' RRPROW R'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' where T.PRN = ' || S.NRN); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' and R.RN = T.RRPROW'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' group by R.RN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.NAME,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.ROW_CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' R.SORT_NUMB'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_ROWS, SELEMENT1 => ' order by ' || SORDERS_R); + /* Разбираем его */ + ICURSOR_R := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); + PKG_SQL_DML.PARSE(ICURSOR => ICURSOR_R, SQUERY => CSQL_ROWS); + /* Описываем структуру записи курсора */ + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR_R, IPOSITION => 1); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR_R, IPOSITION => 2); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR_R, IPOSITION => 3); + /* Делаем выборку */ + if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR_R) = 0) then + null; + end if; + /* Обходим выбранные записи */ + while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR_R) > 0) loop - /* Считываем показатель по строке/графе */ - RRRPCONFSCTNMRK := RRPCONFSCTNMRK_GET_ROWCOL(NRRPCONFSCTN => S.NRN, NRRPROW => R.RN, NRRPCOLUMN => C.RN); - /* Заполняем рег. номер графы */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SCOL_' || C.CODE, SVALUE => C.NAME); - /* Заполняем рег. номер графы */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NCOL_RN_' || C.CODE, NVALUE => C.RN); - /* Заполняем рег. номер показателя */ + /* Считываем рег. номер строки */ + PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR_R, IPOSITION => 1, NVALUE => NROW_RN); + /* Считываем код строки */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR_R, IPOSITION => 2, SVALUE => SROW_CODE); + /* Считываем наименование строки */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR_R, IPOSITION => 3, SVALUE => SROW_NAME); + /* Заполняем наименование строки */ PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, - SNAME => 'NMARK_RN_' || C.CODE, - NVALUE => RRRPCONFSCTNMRK.RN); - /* Если ошибка считывания показателя */ - if (RRRPCONFSCTNMRK.RN is not null) then - /* Заполняем мнемокод показателя */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, - SNAME => 'SMARK_CODE_' || C.CODE, - SVALUE => RRRPCONFSCTNMRK.CODE); - /* Добавляем атрибут состава показателей */ - PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'MARK_CNS_' || C.CODE, SVALUE => null); + SNAME => 'SROW_NAME', + SVALUE => SROW_NAME, + BCLEAR => true); + /* Заполняем позицию строки */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NROW_POS', NVALUE => NROW_POS); + /* Заполняем мнемокод строки */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SROW_CODE', SVALUE => SROW_CODE); + /* Заполняем рег. номер строки */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NROW_RN', NVALUE => NROW_RN); + /* Добавляем подсказку совместимости */ + CSQL_COLS := PKG_SQL_BUILD.COMPATIBLE(); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => 'select C.RN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.NAME'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' from RRPCONFSCTNMRK T,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' RRPCOLUMN C'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' where T.PRN = ' || S.NRN); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' and C.RN = T.RRPCOLUMN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' group by C.RN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.NAME,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.COLUMN_CODE,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' C.SORT_NUMB'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL_COLS, SELEMENT1 => ' order by ' || SORDERS_C); + /* Разбираем его */ + ICURSOR_C := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); + PKG_SQL_DML.PARSE(ICURSOR => ICURSOR_C, SQUERY => CSQL_COLS); + /* Описываем структуру записи курсора */ + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR_C, IPOSITION => 1); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR_C, IPOSITION => 2); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR_C, IPOSITION => 3); + /* Делаем выборку */ + if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR_C) = 0) then + null; end if; + /* Обходим выбранные записи */ + while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR_C) > 0) + loop + /* Считываем рег. номер графы */ + PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR_C, IPOSITION => 1, NVALUE => NCOL_RN); + /* Считываем код графы */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR_C, IPOSITION => 2, SVALUE => SCOL_CODE); + /* Считываем наименование графы */ + PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR_C, IPOSITION => 3, SVALUE => SCOL_NAME); + /* Считываем показатель по строке/графе */ + RRRPCONFSCTNMRK := RRPCONFSCTNMRK_GET_ROWCOL(NRRPCONFSCTN => S.NRN, + NRRPROW => NROW_RN, + NRRPCOLUMN => NCOL_RN); + /* Заполняем наименование графы */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SCOL_' || SCOL_CODE, SVALUE => SCOL_NAME); + /* Заполняем рег. номер графы */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NCOL_RN_' || SCOL_CODE, NVALUE => NCOL_RN); + /* Заполняем рег. номер показателя */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, + SNAME => 'NMARK_RN_' || SCOL_CODE, + NVALUE => RRRPCONFSCTNMRK.RN); + /* Если ошибка считывания показателя */ + if (RRRPCONFSCTNMRK.RN is not null) then + /* Заполняем мнемокод показателя */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, + SNAME => 'SMARK_CODE_' || SCOL_CODE, + SVALUE => RRRPCONFSCTNMRK.CODE); + /* Добавляем атрибут состава показателей */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'MARK_CNS_' || SCOL_CODE, SVALUE => null); + end if; + end loop; + /* Освобождаем курсор */ + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR_C); + /* Добавим строку для раздела */ + PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); + /* Инкрементируем счётчик позиции строки */ + NROW_POS := NROW_POS + 1; end loop; - /* Добавим строку для раздела */ - PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); - end loop; + /* Освобождаем курсор */ + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR_R); + exception + when others then + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR_R); + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR_C); + raise; + end; end if; /* Сериализуем описание */ CDG := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1); @@ -1058,10 +1212,10 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Добавление раздела регламентированного отчёта */ procedure RRPCONFSCTN_INSERT ( - NPRN in number, -- Ид. настройки форм регламентированного отчёта + NPRN in number, -- Рег. номер настройки форм регламентированного отчёта SCODE in varchar2, -- Мнемокод SNAME in varchar2, -- Наименование - NRN out number -- Ид. созданной записи + NRN out number -- Рег. номер созданной записи ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации @@ -1086,7 +1240,7 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Исправление раздела регламентированного отчёта */ procedure RRPCONFSCTN_UPDATE ( - NRN in number, -- Ид. раздела + NRN in number, -- Рег. номер раздела SCODE in varchar2, -- Мнемокод раздела SNAME in varchar2 -- Наименование раздела ) @@ -1125,7 +1279,7 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Удаление раздела регламентированного отчёта */ procedure RRPCONFSCTN_DELETE ( - NRN in number -- Ид. раздела + NRN in number -- Рег. номер раздела ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации @@ -1142,10 +1296,10 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Получение кодов настройки, раздела и показателя раздела по ид. показателя раздела */ procedure RRPCONFSCTNMRK_GET_CODES ( - NRN in number, -- Ид. показателя раздела - SRRPCONF out varchar2, -- Код настройки формы регламентированного отчёта - SRRPCONFSCTN out varchar2, -- Код раздела - SRRPCONFSCTNMRK out varchar2 -- Код показателя раздела + NRN in number, -- Рег. номер показателя раздела + SRRPCONF out varchar2, -- Мнемокод настройки формы регламентированного отчёта + SRRPCONFSCTN out varchar2, -- Мнемокод раздела + SRRPCONFSCTNMRK out varchar2 -- Мнемокод показателя раздела ) is begin @@ -1227,12 +1381,12 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Добавление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_INSERT ( - NPRN in number, -- Ид. раздела + NPRN in number, -- Рег. номер раздела SCODE in varchar2, -- Мнемокод показателя раздела SNAME in varchar2, -- Наименование показателя раздела NRRPROW in number, -- Рег. номер строки NRRPCOLUMN in number, -- Рег. номер графы - NRN out number -- Ид. созданной записи + NRN out number -- Рег. номер созданной записи ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации @@ -1285,7 +1439,7 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Исправление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_UPDATE ( - NRN in number, -- Ид. показателя раздела + NRN in number, -- Рег. номер показателя раздела SNAME in varchar2 -- Новое наименование ) is @@ -1340,7 +1494,7 @@ create or replace package body PKG_P8PANELS_RRPCONFED as /* Удаление показателя раздела регламентированного отчёта */ procedure RRPCONFSCTNMRK_DELETE ( - NRN in number -- Ид. показателя раздела + NRN in number -- Рег. номер показателя раздела ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации