ЦИТК-823 - Редактор настройки регламентированного отчёта

This commit is contained in:
Vladislav 2024-06-10 11:27:20 +03:00
parent 06f0b35f92
commit 548acf33d9
8 changed files with 1233 additions and 0 deletions

View File

@ -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 (
<Button variant="contained" onClick={btnOkClick}>
{btnText}
</Button>
);
};
return (
<Dialog open={formOpen} onClose={closeForm}>
<DialogTitle>{formTitle()}</DialogTitle>
<IconButton
aria-label="close"
onClick={closeForm}
sx={{
position: "absolute",
right: 8,
top: 8,
color: theme => theme.palette.grey[500]
}}
>
<Icon>close</Icon>
</IconButton>
<DialogContent>
{curStatus == Statuses.DELETE || curStatus == Statuses.COLUMNROW_DELETE ? (
curStatus == Statuses.DELETE ? (
<Typography>Вы хотите удалить раздел {curName}?</Typography>
) : (
<Typography>Вы хотите удалить показатель раздела {curName}?</Typography>
)
) : (
<div>
{curStatus != Statuses.COLUMNROW_EDIT ? (
<CustomFormControl elementCode="code" elementValue={curCode} labelText="Мнемокод" changeFunc={codeOnChange} />
) : null}
<CustomFormControl elementCode="name" elementValue={curName} labelText="Наименование" changeFunc={nameOnChange} />
{curStatus == Statuses.COLUMNROW_CREATE ? (
<div>
<CustomFormControl
elementCode="column"
elementValue={curColCode}
labelText="Графа"
changeFunc={dictColumnClick}
withDictionary={true}
/>
<CustomFormControl
elementCode="row"
elementValue={curRowCode}
labelText="Строка"
changeFunc={dictRowClick}
withDictionary={true}
/>
</div>
) : null}
</div>
)}
</DialogContent>
<DialogActions sx={STYLES.PADDING_DIALOG_BUTTONS_RIGHT}>
{renderSwitch()}
<Button variant="contained" onClick={closeForm}>
Отмена
</Button>
</DialogActions>
</Dialog>
);
};
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 };

View File

@ -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 (
<Box sx={{ p: 1 }}>
<FormControl sx={STYLES.DIALOG_WINDOW_WIDTH} {...other}>
<InputLabel htmlFor={`${elementCode}-outlined`}>{labelText}</InputLabel>
<OutlinedInput
id={`${elementCode}-outlined`}
value={elementValue ? elementValue : ""}
onChange={!withDictionary ? e => changeFunc(e.target.value) : null}
aria-describedby={`${elementCode}-outlined-helper-text`}
label={labelText}
endAdornment={
withDictionary ? (
<InputAdornment position="end">
<IconButton aria-label={`${elementCode} select`} onClick={changeFunc} edge="end">
<Icon>list</Icon>
</IconButton>
</InputAdornment>
) : null
}
/>
</FormControl>
</Box>
);
};
CustomFormControl.propTypes = {
elementCode: PropTypes.string.isRequired,
elementValue: PropTypes.string,
labelText: PropTypes.string.isRequired,
changeFunc: PropTypes.func.isRequired,
withDictionary: PropTypes.bool
};
//----------------
//Интерфейс модуля
//----------------
export { CustomFormControl };

View File

@ -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 (
<div role="tabpanel" hidden={value !== index} id={`simple-tabpanel-${index}`} aria-labelledby={`simple-tab-${index}`} {...other}>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
};
CustomTabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired
};
//----------------
//Интерфейс модуля
//----------------
export { CustomTabPanel };

View File

@ -0,0 +1,16 @@
/*
Парус 8 - Панели мониторинга - Редактор настройки регламентированного отчёта
Панель мониторинга: Точка входа
*/
//---------------------
//Подключение библиотек
//---------------------
import { RrpConfEditor } from "./rrp_conf_editor"; //Корневая панель выполнения работ
//----------------
//Интерфейс модуля
//----------------
export const RootClass = RrpConfEditor;

View File

@ -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 = (
<Stack direction="row">
<Typography width="-webkit-fill-available">{row[columnDef.name]}</Typography>
<IconButton justifyContent="flex-end" onClick={() => editCR(row["NRN_" + columnDef.name.substring(5)], row[columnDef.name])}>
<Icon>edit</Icon>
</IconButton>
<IconButton justifyContent="flex-end" onClick={() => deleteCR(row["NRN_" + columnDef.name.substring(5)], row[columnDef.name])}>
<Icon>delete</Icon>
</IconButton>
</Stack>
))
: null;
return { data };
};

View File

@ -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 (
<Box sx={{ width: "100%" }}>
{formOpen ? (
<CustomDialog
formOpen={formOpen}
closeForm={closeForm}
curStatus={formData.status}
curCode={formData.code}
curName={formData.name}
curColCode={formData.colCode}
curRowCode={formData.rowCode}
btnOkClick={formBtnOkClick}
codeOnChange={v => setFormData(pv => ({ ...pv, code: v }))}
nameOnChange={v => setFormData(pv => ({ ...pv, name: v }))}
dictColumnClick={dictColumnClick}
dictRowClick={dictRowClick}
/>
) : null}
{rrpDoc.docLoaded ? (
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Stack direction="row">
<Tabs value={tabValue} onChange={handleChange} aria-label="section tab">
{rrpDoc.sections.map((s, i) => {
return (
<Tab
key={s.rn}
{...a11yProps(i)}
label={
<Stack direction="row" textAlign="center">
{s.name}
<IconButton onClick={() => editSectionClick(s.rn, s.code, s.name)}>
<Icon>edit</Icon>
</IconButton>
<IconButton onClick={() => deleteSectionClick(s.rn, s.code, s.name)}>
<Icon>delete</Icon>
</IconButton>
</Stack>
}
wrapped
/>
);
})}
</Tabs>
<IconButton onClick={addSectionClick}>
<Icon>add</Icon>
</IconButton>
</Stack>
{rrpDoc.sections.map((s, i) => {
return (
<CustomTabPanel key={s.rn} value={tabValue} index={i}>
<Button variant="contained" onClick={() => addColumnRowClick(s.rn, s.code, s.name)}>
+ Добавить
</Button>
{s.dataLoaded ? (
<P8PDataGrid
{...P8P_DATA_GRID_CONFIG_PROPS}
columnsDef={s.columnsDef}
groups={s.groups}
rows={s.rows}
size={P8P_DATA_GRID_SIZE.LARGE}
reloading={s.reload}
dataCellRender={prms => dataCellRender({ ...prms }, editColumnRowClick, deleteColumnRowClick)}
/>
) : null}
</CustomTabPanel>
);
})}
</Box>
) : null}
</Box>
);
};
//----------------
//Интерфейс модуля
//----------------
export { RrpConfEditor };

View File

@ -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;
/

View File

@ -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;