Compare commits

...

12 Commits

Author SHA1 Message Date
Mikhail Chechnev
18dac12396 ЦИТК-979 - Редактор запросов - переименовал процедуру формирования SQL-выражения 2025-10-15 15:18:17 +03:00
Mikhail Chechnev
d446fd96ab ЦИТК-979 - Редактор условия запроса - раздельное хранение канонического SQL-выражения и выражения с подстановками 2025-10-14 19:21:18 +03:00
Mikhail Chechnev
6efbb8508c ЦИТК-979 - Редактор условия запроса - реализовано добавление элемента условия по месту курсора/выделения 2025-10-14 14:45:53 +03:00
Mikhail Chechnev
3df01a36c6 ЦИТК-979 - Редактор запросов - исправлена ошибка сброса состояния диалога редактирования аргумента запроса при возникновении серверной ошибки 2025-10-14 14:13:03 +03:00
Mikhail Chechnev
1530bfa3bf ЦИТК-979 - Редактор запросов - Поддержка подстановки отладочных значений аргументов в SQL-выражение 2025-10-14 00:09:52 +03:00
Mikhail Chechnev
64145d7ac0 ЦИТК-979 - Редактор запросов - Контроль имени аргументов: только латинские буквы, цифры и подчеркивание, начало только с буквы, принудительный APPERCASE, контроль уникальности 2025-10-13 17:03:32 +03:00
Mikhail Chechnev
63e3d3833e ЦИТК-979 - Редактор запросов - контроль соответствия условий отбора запроса набору его аргументов, инкапсуляция обновления SQL-выражения запроса в базовом пакете 2025-10-13 16:27:51 +03:00
Mikhail Chechnev
db5bf1f72c WEBAPP: Свежая сборка 2025-10-10 22:35:10 +03:00
Mikhail Chechnev
0388d5630b ЦИТК-878 - "Доски задач" - включение панели в поставку 2025-10-10 22:27:16 +03:00
Mikhail Chechnev
c9e4894a40 ЦИТК-979 - Редактор запросов - сокрытие области текста запроса при отображении редактора 2025-10-10 22:22:42 +03:00
Mikhail Chechnev
9cbc52cff2 ЦИТК-878 - "Доски задач" - доработана под логику смены статуса события с релиза "июнь 2025", исправлена ошибка инициализации клиента с пустым хранилищем, купирована ошибка с отсутствием профиля настроек 2025-10-10 21:58:03 +03:00
Mikhail Chechnev
fe1e3ba04f ЦИТК-878 - Гранты для панели "Доски задач" 2025-10-10 21:09:00 +03:00
17 changed files with 1519 additions and 227 deletions

View File

@ -95,7 +95,7 @@ const useColorRules = () => {
const [colorRules, setColorRules] = useState({ const [colorRules, setColorRules] = useState({
loaded: false, loaded: false,
rules: [], rules: [],
selectedColorRule: JSON.parse(getLocalStorageValue("settingsColorRule") || {}) selectedColorRule: JSON.parse(getLocalStorageValue("settingsColorRule")) || {}
}); });
//Подключение к контексту взаимодействия с сервером //Подключение к контексту взаимодействия с сервером

View File

@ -160,7 +160,7 @@ const useTasksFunctions = () => {
callBack: sendPrms => { callBack: sendPrms => {
const mainArgs = { const mainArgs = {
NIDENT: pointInfo.NIDENT, NIDENT: pointInfo.NIDENT,
NSTEP: 3, NSTEP: 4,
NEVENT: nEvent, NEVENT: nEvent,
SEVENT_STAT: pointInfo.SEVENT_STAT, SEVENT_STAT: pointInfo.SEVENT_STAT,
SSEND_CLIENT: sendPrms.outParameters.out_CLIENT_CODE, SSEND_CLIENT: sendPrms.outParameters.out_CLIENT_CODE,
@ -182,7 +182,7 @@ const useTasksFunctions = () => {
//Общие аргументы //Общие аргументы
const mainArgs = { const mainArgs = {
NIDENT: pointInfo.NIDENT, NIDENT: pointInfo.NIDENT,
NSTEP: 3, NSTEP: 4,
NEVENT: nEvent, NEVENT: nEvent,
SEVENT_STAT: pointInfo.SEVENT_STAT SEVENT_STAT: pointInfo.SEVENT_STAT
}; };
@ -193,46 +193,71 @@ const useTasksFunctions = () => {
[handleEventRoutesPointExecutersOpen, handleStateChange] [handleEventRoutesPointExecutersOpen, handleStateChange]
); );
//При выполнении третьего шага
const handleMakeThirdStep = useCallback(
async ({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => {
//Выполняем переход на следующий шаг
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: {
NIDENT: pointInfo.NIDENT,
NSTEP: 3,
NPASS: pointInfo.NPASS
}
});
//Выполняем выбор исполнителя
handleExecuterSelect({
nEvent,
pointInfo,
onReload,
onNoteOpen
});
},
[executeStored, handleExecuterSelect]
);
//При выполнении второго шага //При выполнении второго шага
const handleMakeSecondStep = useCallback( const handleMakeSecondStep = useCallback(
async ({ nIdent, nPass }) => { async ({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => {
//Состояние параметров текущего действия
let currentPointInfo = { ...pointInfo };
//Выполняем переход на следующий шаг //Выполняем переход на следующий шаг
const secondStep = await executeStored({ const secondStep = await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE", stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: { args: {
NIDENT: nIdent, NIDENT: currentPointInfo.NIDENT,
NSTEP: 2, NSTEP: 2,
NPASS: nPass NPASS: currentPointInfo.NPASS
} }
}); });
//Возвращаем параметры выполнения //Устанавливаем признак необходимости выбора исполнителя
return secondStep; currentPointInfo.NSELECT_EXEC = secondStep.NSELECT_EXEC;
//Выполняем третий шаг
handleMakeThirdStep({ nEvent, pointInfo: currentPointInfo, onReload, onNoteOpen });
}, },
[executeStored] [executeStored, handleMakeThirdStep]
); );
//При выборе следующей точки события //При выборе следующей точки события
const handleNextPointSelect = useCallback( const handleNextPointSelect = useCallback(
({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => { ({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => {
//Состояние параметров текущего действия
let currentPointInfo = { ...pointInfo };
//Открываем раздел "Маршруты событий (точки перехода)" для выбора следующей точки //Открываем раздел "Маршруты событий (точки перехода)" для выбора следующей точки
handleEventRoutesPointsPassessOpen({ handleEventRoutesPointsPassessOpen({
sEventType: pointInfo.SEVENT_TYPE, sEventType: currentPointInfo.SEVENT_TYPE,
sEventStatus: pointInfo.SEVENT_STAT, sEventStatus: currentPointInfo.SEVENT_STAT,
nPoint: pointInfo.NPOINT, nPoint: currentPointInfo.NPOINT,
callBack: async point => { callBack: async point => {
//Устанавливаем полученную точку перехода
currentPointInfo.NPASS = point.outParameters.out_RN;
currentPointInfo.SEVENT_STAT = point.outParameters.out_NEXT_POINT;
//Выполняем второй шаг //Выполняем второй шаг
let secondStep = await handleMakeSecondStep({ nIdent: pointInfo.NIDENT, nPass: point.outParameters.out_RN }); handleMakeSecondStep({ nEvent, pointInfo: currentPointInfo, onReload, onNoteOpen });
//Выполняем выбор исполнителя
handleExecuterSelect({
nEvent,
pointInfo: { ...pointInfo, SEVENT_STAT: point.outParameters.out_NEXT_POINT, NSELECT_EXEC: secondStep.NSELECT_EXEC },
onReload,
onNoteOpen
});
} }
}); });
}, },
[handleEventRoutesPointsPassessOpen, handleMakeSecondStep, handleExecuterSelect] [handleEventRoutesPointsPassessOpen, handleMakeSecondStep]
); );
//По нажатию действия "Перейти" //По нажатию действия "Перейти"
@ -259,17 +284,12 @@ const useTasksFunctions = () => {
onNoteOpen onNoteOpen
}); });
} else { } else {
//Выполняем перехода без выбора точки //Выполняем второй шаг
handleExecuterSelect({ handleMakeSecondStep({ nEvent, pointInfo: eventInfo, onReload, onNoteOpen });
nEvent,
pointInfo: eventInfo,
onReload,
onNoteOpen
});
} }
} }
}, },
[executeStored, handleExecuterSelect, handleNextPointSelect] [executeStored, handleMakeSecondStep, handleNextPointSelect]
); );
return { handleTaskStateChange, handleTaskSend }; return { handleTaskStateChange, handleTaskSend };

View File

@ -183,9 +183,7 @@ export const formatSqlDate = timeStamp => {
}; };
//Считывание значений из локального хранилища //Считывание значений из локального хранилища
export const getLocalStorageValue = (sName, defaultValue = null) => { export const getLocalStorageValue = (sName, defaultValue = null) => localStorage.getItem(sName) || defaultValue;
return localStorage.getItem(sName) ? localStorage.getItem(sName) : defaultValue;
};
//Форматирование фильтра в массив для отбора //Форматирование фильтра в массив для отбора
export const convertFilterValuesToArray = filterValues => { export const convertFilterValuesToArray = filterValues => {

View File

@ -18,14 +18,26 @@ import { InspectorQueryArguments } from "../inspector_query_args/inspector_query
import { InspectorQueryConditions } from "../inspector_query_cond/inspector_query_cond"; //Управление условиями отбора запроса import { InspectorQueryConditions } from "../inspector_query_cond/inspector_query_cond"; //Управление условиями отбора запроса
import { InspectorQueryEntities } from "../inspector_query_ents/inspector_query_ents"; //Управление сущностями запроса import { InspectorQueryEntities } from "../inspector_query_ents/inspector_query_ents"; //Управление сущностями запроса
import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_rls"; //Управление связями запроса import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_rls"; //Управление связями запроса
import { QueryArea } from "./query_area"; //Область запроса import { InspectorQueryArea } from "../inspector_query_area/inspector_query_area"; //Область SQL-выражения
//----------- //-----------
//Тело модуля //Тело модуля
//----------- //-----------
//Инспектор свойств //Инспектор свойств
const Inspector = ({ query, entity, relation, entities = [], args = [], cond = null, qry = "", qryMsg = "", onOptionsChanged = null }) => { const Inspector = ({
query,
entity,
relation,
entities = [],
args = [],
cond = null,
substArgsVals = 0,
qry = "",
qryBnd = "",
qryMsg = "",
onOptionsChanged = null
}) => {
//При изменении настроек запроса //При изменении настроек запроса
const handleOptionsChanged = () => onOptionsChanged && onOptionsChanged(); const handleOptionsChanged = () => onOptionsChanged && onOptionsChanged();
@ -44,7 +56,7 @@ const Inspector = ({ query, entity, relation, entities = [], args = [], cond = n
<InspectorQueryRelations query={query} relation={relation} onOptionsChanged={handleOptionsChanged} /> <InspectorQueryRelations query={query} relation={relation} onOptionsChanged={handleOptionsChanged} />
</> </>
)} )}
<QueryArea qry={qry} qryMsg={qryMsg} /> <InspectorQueryArea query={query} substArgsVals={substArgsVals} qry={qry} qryBnd={qryBnd} qryMsg={qryMsg} />
</P8PEditorBox> </P8PEditorBox>
); );
}; };
@ -57,7 +69,9 @@ Inspector.propTypes = {
entities: PropTypes.arrayOf(ENTITY_SHAPE), entities: PropTypes.arrayOf(ENTITY_SHAPE),
args: PropTypes.arrayOf(ARGUMENT_SHAPE), args: PropTypes.arrayOf(ARGUMENT_SHAPE),
cond: PropTypes.string, cond: PropTypes.string,
substArgsVals: PropTypes.number,
qry: PropTypes.string, qry: PropTypes.string,
qryBnd: PropTypes.string,
qryMsg: PropTypes.string, qryMsg: PropTypes.string,
onOptionsChanged: PropTypes.func onOptionsChanged: PropTypes.func
}; };

View File

@ -0,0 +1,35 @@
/*
Парус 8 - Панели мониторинга - Редактор запросов
Пользовательские хуки для работы с областью SQL-выражения
*/
//---------------------
//Подключение библиотек
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
//-----------
//Работа с областью SQL-выражения
const useQuerySQLExpr = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Установка флага сокрытия/отображения значений аргументов в SQL-выражении запроса
const toggleSubstArgsVals = useCallback(async () => {
await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_OPT_SUBST_ARGS_VALS_TGL", args: { NRN: query }, loader: false });
}, [query, executeStored]);
//Возвращаем интерфейс хука
return { toggleSubstArgsVals };
};
//----------------
//Интерфейс модуля
//----------------
export { useQuerySQLExpr };

View File

@ -1,17 +1,18 @@
/* /*
Парус 8 - Панели мониторинга - Редактор запросов Парус 8 - Панели мониторинга - Редактор запросов
Область запроса Область SQL-выражения
*/ */
//--------------------- //---------------------
//Подключение библиотек //Подключение библиотек
//--------------------- //---------------------
import React, { useState } from "react"; //Классы React import React, { useState, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import { Fab, Icon, Drawer, IconButton, TextField, Stack, Box, Snackbar, Alert } from "@mui/material"; //Компоненты MUI import { Fab, Icon, Drawer, IconButton, TextField, Stack, Box, Snackbar, Alert } from "@mui/material"; //Компоненты MUI
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
import { APP_STYLES } from "../../../../../app.styles"; //Общие стили приложения import { APP_STYLES } from "../../../../../app.styles"; //Общие стили приложения
import { useQuerySQLExpr } from "./hooks"; //Пользовательские хуки для работы с SQL-выражением
//--------- //---------
//Константы //Константы
@ -38,17 +39,29 @@ const SNACK_BAR_MESSAGE_INIT = { text: null, type: null };
//Тело модуля //Тело модуля
//----------- //-----------
//Область запроса //Область SQL-выражения
const QueryArea = ({ qry = "", qryMsg = "" }) => { const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryBnd = "", qryMsg = "" }) => {
//Собственное состояние - отображение запроса с подстановками
const [showQryBnd, setShowQryBnd] = useState(substArgsVals);
//Собственное состояние - текст всплывающего сообщения //Собственное состояние - текст всплывающего сообщения
const [snackBarMessage, setSnackBarMessage] = useState(SNACK_BAR_MESSAGE_INIT); const [snackBarMessage, setSnackBarMessage] = useState(SNACK_BAR_MESSAGE_INIT);
//Собственное состояние - отображение области SQL запроса //Собственное состояние - отображение области SQL запроса
const [displaySQL, setDisplaySQL] = useState(true); const [displaySQL, setDisplaySQL] = useState(false);
//Собственное состояние - развёрнутость //Собственное состояние - развёрнутость
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
//Работа с SQL-выражением
const { toggleSubstArgsVals } = useQuerySQLExpr(query);
//При нажатии на кнопку отображения/сокрытия значений аргументов в SQL-выражении запроса
const handleToggleSubstArgsValsClick = async () => {
await toggleSubstArgsVals();
setShowQryBnd(showQryBnd === 1 ? 0 : 1);
};
//При нажатии на кнопку копирования текста запроса //При нажатии на кнопку копирования текста запроса
const handleCopyClick = async () => { const handleCopyClick = async () => {
try { try {
@ -74,6 +87,13 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
//Расчет размеров тектовых полей //Расчет размеров тектовых полей
const [qryRows, qryMsgRows] = expanded ? [15, 6] : [5, 3]; const [qryRows, qryMsgRows] = expanded ? [15, 6] : [5, 3];
//Расчет параметров отображения запроса
const [dispQry, qryViewTitle, qryViewIcon] =
showQryBnd === 0 ? [qry, "Отобразить значения аргументов", "code"] : [qryBnd, "Скрыть значения аргументов", "code_off"];
//При изменении состояние отображения подстановок в запросе
useEffect(() => setShowQryBnd(substArgsVals), [substArgsVals]);
//Генерация содержимого //Генерация содержимого
return ( return (
<> <>
@ -87,9 +107,14 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
<Box p={2}> <Box p={2}>
<Stack direction={"row"} justifyContent={"right"} spacing={2}> <Stack direction={"row"} justifyContent={"right"} spacing={2}>
{qry && ( {qry && (
<IconButton onClick={handleCopyClick} title={"Скопировать текст запроса"}> <>
<Icon>content_copy</Icon> <IconButton onClick={handleToggleSubstArgsValsClick} title={qryViewTitle}>
</IconButton> <Icon>{qryViewIcon}</Icon>
</IconButton>
<IconButton onClick={handleCopyClick} title={"Скопировать текст запроса"}>
<Icon>content_copy</Icon>
</IconButton>
</>
)} )}
<IconButton onClick={handleExpandClick} title={expanded ? "Свернуть" : "Развернуть"}> <IconButton onClick={handleExpandClick} title={expanded ? "Свернуть" : "Развернуть"}>
<Icon>{expanded ? "expand_more" : "expand_less"}</Icon> <Icon>{expanded ? "expand_more" : "expand_less"}</Icon>
@ -99,12 +124,12 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
</IconButton> </IconButton>
</Stack> </Stack>
<Stack direction={"column"} spacing={2}> <Stack direction={"column"} spacing={2}>
{qry && ( {dispQry && (
<TextField <TextField
label={"Текст запроса"} label={"Текст запроса"}
multiline multiline
fullWidth fullWidth
value={qry} value={dispQry}
minRows={qryRows} minRows={qryRows}
maxRows={qryRows} maxRows={qryRows}
variant={"standard"} variant={"standard"}
@ -139,9 +164,12 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
); );
}; };
//Контроль свойств компонента - Область запроса //Контроль свойств компонента - Область SQL-выражения
QueryArea.propTypes = { InspectorQueryArea.propTypes = {
query: PropTypes.number.isRequired,
substArgsVals: PropTypes.number,
qry: PropTypes.string, qry: PropTypes.string,
qryBnd: PropTypes.string,
qryMsg: PropTypes.string qryMsg: PropTypes.string
}; };
@ -149,4 +177,4 @@ QueryArea.propTypes = {
//Интерфейс модуля //Интерфейс модуля
//---------------- //----------------
export { QueryArea }; export { InspectorQueryArea };

View File

@ -19,24 +19,21 @@ import { DATA_TYPE } from "../../common"; //Общие константы ред
//Диалог добавления/исправления аргумента запроса //Диалог добавления/исправления аргумента запроса
const ArgIUDialog = ({ name = "", title = "", dataType = DATA_TYPE.NUMB, mandatory = 0, value = "", insert = true, onOk, onCancel }) => { const ArgIUDialog = ({ name = "", title = "", dataType = DATA_TYPE.NUMB, mandatory = 0, value = "", insert = true, onOk, onCancel }) => {
//Собственное состояние - текущее состояние аргумента //Собственное состояние - текущие значения полей аргумента запроса
const [current, setCurrent] = useState({ value, dataType }); const [current, setCurrent] = useState({ name, title, dataType, mandatory, value });
//Нажатие на кнопку "Ok" //Нажатие на кнопку "Ok"
const handleOk = values => onOk && onOk({ ...values }); const handleOk = () => onOk && onOk(current);
//Нажатие на кнопку "Отмена" //Нажатие на кнопку "Отмена"
const handleCancel = () => onCancel && onCancel(); const handleCancel = () => onCancel && onCancel();
//При изменении значений в поле ввода //При изменении значений в поле ввода
const handleInputChange = (name, value) => { const handleInputChange = (name, value) => {
//Если поменяли тип данных - надо пересмотреть поля для ввода //Сохраним в состоянии новое значение, если сменили тип данных - сбросим "отладочное значение"
if (name === "dataType") { setCurrent(pv => ({ ...pv, [name]: value, ...(name === "dataType" ? { value: "" } : {}) }));
//Сохраним в состоянии новый тип данных и сбросим "отладочное значение", ведь оно зависит от типа данных (от этого состояния зависит свойство inputs, передаваемое в P8PDialog ниже) //Мы сами пересчитали форму, туда придут новые настройки элементов ввода через свойство inputs, не надо делать пересчет состояния внутри диалога
setCurrent({ dataType: value, value: "" }); return true;
//Мы сами пересчитали форму, туда придут новые настройки элементов ввода через свойство inputs, не надо делать пересчет состояния внутри диалога
return true;
}
}; };
//Генерация содержимого //Генерация содержимого
@ -44,8 +41,8 @@ const ArgIUDialog = ({ name = "", title = "", dataType = DATA_TYPE.NUMB, mandato
<P8PDialog <P8PDialog
title={`${insert === true ? TITLES.INSERT : TITLES.UPDATE} аргумента`} title={`${insert === true ? TITLES.INSERT : TITLES.UPDATE} аргумента`}
inputs={[ inputs={[
{ name: "name", value: name, label: "Имя", disabled: insert != true }, { name: "name", value: current.name, label: "Имя", disabled: insert != true },
{ name: "title", value: title, label: "Приглашение" }, { name: "title", value: current.title, label: "Приглашение" },
{ {
name: "dataType", name: "dataType",
value: current.dataType, value: current.dataType,
@ -58,7 +55,7 @@ const ArgIUDialog = ({ name = "", title = "", dataType = DATA_TYPE.NUMB, mandato
}, },
{ {
name: "mandatory", name: "mandatory",
value: mandatory, value: current.mandatory,
label: "Обязательный", label: "Обязательный",
list: [ list: [
{ name: "Нет", value: 0 }, { name: "Нет", value: 0 },

View File

@ -50,6 +50,19 @@ const QueryCondDialog = ({ cond, entities, args, onOk, onCancel }) => {
} }
}; };
//Добавление значения в редактор по месту курсора
const addCondValueToCursor = value => {
let newValue = conditions + value;
if (coditionInputRef.current) {
newValue = coditionInputRef.current.value;
newValue =
newValue.substring(0, coditionInputRef.current.selectionStart) + value + newValue.substring(coditionInputRef.current.selectionEnd);
coditionInputRef.current.value = newValue;
}
moveCondCursorToEnd();
setConditions(newValue);
};
//Нажатие на кнопку "ОК" //Нажатие на кнопку "ОК"
const handleOk = () => onOk && onOk(conditions); const handleOk = () => onOk && onOk(conditions);
@ -60,16 +73,10 @@ const QueryCondDialog = ({ cond, entities, args, onOk, onCancel }) => {
const handleChange = e => setConditions(e.target.value); const handleChange = e => setConditions(e.target.value);
//При выборе компонента условия //При выборе компонента условия
const handleComponentSelected = value => { const handleComponentSelected = value => addCondValueToCursor(value);
setConditions(pv => pv + value);
moveCondCursorToEnd();
};
//При нажатии на кнопку операции //При нажатии на кнопку операции
const handleOperationButtonClick = value => { const handleOperationButtonClick = value => addCondValueToCursor(value);
setConditions(pv => pv + value);
moveCondCursorToEnd();
};
//При нажатии на кнопку очистки условий //При нажатии на кнопку очистки условий
const handleClearClick = () => setConditions(""); const handleClearClick = () => setConditions("");

View File

@ -139,8 +139,12 @@ const useQuery = query => {
loader: true loader: true
}); });
setQueryDiagram(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || [])); setQueryDiagram(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || []));
setQueryOption({ args: data?.XOPT?.XARGS?.XARG || [], cond: data?.XOPT?.XCOND || null }); setQueryOption({
setQuerySQL({ qry: data?.XQRY, qryMsg: data?.XQRY_MSG }); args: data?.XOPT?.XARGS?.XARG || [],
cond: data?.XOPT?.XCOND || null,
substArgsVals: data?.XOPT?.XSUBST_ARGS_VALS || 0
});
setQuerySQL({ qry: data?.XQRY, qryBnd: data?.XQRY_BND, qryMsg: data?.XQRY_MSG });
setInit(true); setInit(true);
} finally { } finally {
setRefresh(false); setRefresh(false);

View File

@ -15,6 +15,7 @@ create table P8PNL_QE_QUERY
ENTS clob, -- Сущности запроса ENTS clob, -- Сущности запроса
RLS clob, -- Отношения сущностей запроса RLS clob, -- Отношения сущностей запроса
QRY clob, -- Запрос (SQL выражение) QRY clob, -- Запрос (SQL выражение)
QRY_BND clob, -- Запрос (SQL выражение) с подставленными значениями аргументов
QRY_MSG clob, -- Сообщение при формировании запроса (предупреждения и ошибки формирования) QRY_MSG clob, -- Сообщение при формировании запроса (предупреждения и ошибки формирования)
constraint C_P8PNL_QE_QUERY_RN_PK primary key (RN), constraint C_P8PNL_QE_QUERY_RN_PK primary key (RN),
constraint C_P8PNL_QE_QUERY_CODE_NB check (rtrim(CODE) is not null), constraint C_P8PNL_QE_QUERY_CODE_NB check (rtrim(CODE) is not null),

View File

@ -94,7 +94,7 @@ create or replace package PKG_P8PANELS_CLNTTSKBRD as
SCLIENT_CLIENT in out varchar2, -- Клиент–организация, для отбора исполнителей SCLIENT_CLIENT in out varchar2, -- Клиент–организация, для отбора исполнителей
SCLIENT_PERSON in out varchar2, -- Клиент–сотрудник, для отбора исполнителей SCLIENT_PERSON in out varchar2, -- Клиент–сотрудник, для отбора исполнителей
NPOINT in out number, -- Текущая точка маршрута NPOINT in out number, -- Текущая точка маршрута
NPASS in number, -- Точка перехода NPASS in out number, -- Точка перехода
NSELECT_EXEC out number, -- Признак необходимости выбора исполнителя NSELECT_EXEC out number, -- Признак необходимости выбора исполнителя
SEXECUTEMETHOD out varchar2, -- Мнемокод метода SEXECUTEMETHOD out varchar2, -- Мнемокод метода
SSEND_CLIENT in varchar2, -- Направить организация SSEND_CLIENT in varchar2, -- Направить организация
@ -1770,7 +1770,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
SCLIENT_CLIENT in out varchar2, -- Клиент–организация, для отбора исполнителей SCLIENT_CLIENT in out varchar2, -- Клиент–организация, для отбора исполнителей
SCLIENT_PERSON in out varchar2, -- Клиент–сотрудник, для отбора исполнителей SCLIENT_PERSON in out varchar2, -- Клиент–сотрудник, для отбора исполнителей
NPOINT in out number, -- Текущая точка маршрута NPOINT in out number, -- Текущая точка маршрута
NPASS in number, -- Точка перехода NPASS in out number, -- Точка перехода
NSELECT_EXEC out number, -- Признак необходимости выбора исполнителя NSELECT_EXEC out number, -- Признак необходимости выбора исполнителя
SEXECUTEMETHOD out varchar2, -- Мнемокод метода SEXECUTEMETHOD out varchar2, -- Мнемокод метода
SSEND_CLIENT in varchar2, -- Направить организация SSEND_CLIENT in varchar2, -- Направить организация
@ -1882,43 +1882,17 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
NSEND_PREDEFINED_PROC => NSEND_PREDEFINED_PROC); NSEND_PREDEFINED_PROC => NSEND_PREDEFINED_PROC);
/* Если это первый шаг и уже известен следующий статус */ /* Если это первый шаг и уже известен следующий статус */
if ((NSTEP_CURRENT = 1) and (SNEXT_STAT is not null)) then if ((NSTEP_CURRENT = 1) and (SNEXT_STAT is not null)) then
/* Сразу выполняем следующее действие */ /* Определим точку перехода */
P_CLNEVENTS_CHANGE_STATE_WEB(NCOMPANY => NCOMPANY, NPASS := EVRTPTPASS_NEXT_GET(NCOMPANY => NCOMPANY,
NIDENT => NIDENT, SEVENT_TYPE => SEVENT_TYPE,
NSTEP => NSTEP, NPOINT => NPOINT,
NEVENT => NEVENT, SEVENT_STAT => SEVENT_STAT,
SEVENT => SEVENT, SNEXT_STAT => SNEXT_STAT);
SEVENT_TYPE => SEVENT_TYPE,
SEVENT_STAT => SEVENT_STAT,
SINIT_PERSON => SINIT_PERSON,
SINIT_AUTHNAME => SINIT_AUTHNAME,
SCLIENT_CLIENT => SCLIENT_CLIENT,
SCLIENT_PERSON => SCLIENT_PERSON,
NPOINT => NPOINT,
NPASS => EVRTPTPASS_NEXT_GET(NCOMPANY => NCOMPANY,
SEVENT_TYPE => SEVENT_TYPE,
NPOINT => NPOINT,
SEVENT_STAT => SEVENT_STAT,
SNEXT_STAT => SNEXT_STAT),
NSELECT_EXEC => NSELECT_EXEC,
NCONFIRM_REQUIRED => NCONFIRM_REQUIRED,
SCONFIRM_TEXT => SCONFIRM_TEXT,
SEXECUTEMETHOD => SEXECUTEMETHOD,
SSEND_CLIENT => SSEND_CLIENT,
SSEND_DIVISION => SSEND_DIVISION,
SSEND_POST => SSEND_POST,
SSEND_PERFORM => SSEND_PERFORM,
SSEND_PERSON => SSEND_PERSON,
SSEND_STAFFGRP => SSEND_STAFFGRP,
SSEND_USER_GROUP => SSEND_USER_GROUP,
SSEND_USER_NAME => SSEND_USER_NAME,
NSEND_PREDEFINED_EXEC => NSEND_PREDEFINED_EXEC,
NSEND_PREDEFINED_PROC => NSEND_PREDEFINED_PROC);
/* Указываем следующий статус */ /* Указываем следующий статус */
SEVENT_STAT := SNEXT_STAT; SEVENT_STAT := SNEXT_STAT;
end if; end if;
/* Если это последний шаг */ /* Если это последний шаг */
if (NSTEP_CURRENT = 3) then if (NSTEP_CURRENT = 4) then
/* Если добавлено примечание */ /* Если добавлено примечание */
if (SNOTE is not null) then if (SNOTE is not null) then
P_CLNEVNOTES_INSERT(NCOMPANY => NCOMPANY, P_CLNEVNOTES_INSERT(NCOMPANY => NCOMPANY,
@ -2351,9 +2325,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
and U.UNITCODE = SUNIT_CLNEVENTS; and U.UNITCODE = SUNIT_CLNEVENTS;
exception exception
when others then when others then
P_EXCEPTION(0, return null;
'Профиль пользователя "%s" для раздела "События" не найден.',
SAUTHID);
end; end;
/* Возвращаем результат */ /* Возвращаем результат */
return BRESULT; return BRESULT;
@ -2361,6 +2333,11 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
begin begin
/* Считываем профиль пользователя для раздела "События" */ /* Считываем профиль пользователя для раздела "События" */
BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAUTHID => SAUTHID); BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAUTHID => SAUTHID);
/* Проверим, что профиль не пустой */
if (BXML is null) then
return;
end if;
/* Данные в профиле есть - будем разбирать */
begin begin
/* Формируем XML данных */ /* Формируем XML данных */
PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_); PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);

View File

@ -155,6 +155,12 @@ create or replace package PKG_P8PANELS_QE as
SCOND in varchar2 -- Условия отбора SCOND in varchar2 -- Условия отбора
); );
/* Переключение флага подстановки значений аргументов запроса в SQL-выражение */
procedure QUERY_OPT_SUBST_ARGS_VALS_TGL
(
NRN in number -- Рег. номер запроса
);
end PKG_P8PANELS_QE; end PKG_P8PANELS_QE;
/ /
create or replace package body PKG_P8PANELS_QE as create or replace package body PKG_P8PANELS_QE as
@ -281,8 +287,6 @@ create or replace package body PKG_P8PANELS_QE as
is is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -295,8 +299,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор сущностей */ /* Сохраняем обновленный набор сущностей */
PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS); PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_ENT_ADD; end QUERY_ENT_ADD;
/* Удаление сущности из запроса */ /* Удаление сущности из запроса */
@ -310,8 +313,6 @@ create or replace package body PKG_P8PANELS_QE as
RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей
RENT PKG_P8PANELS_QE_BASE.TENT; -- Удаляемая сущность RENT PKG_P8PANELS_QE_BASE.TENT; -- Удаляемая сущность
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -346,8 +347,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */ /* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_ENT_REMOVE; end QUERY_ENT_REMOVE;
/* Установка координат сущности в редакторе диаграммы запроса */ /* Установка координат сущности в редакторе диаграммы запроса */
@ -404,8 +404,6 @@ create or replace package body PKG_P8PANELS_QE as
RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SCHECK_MSG PKG_STD.TLSTRING; -- Сообщение при проверке атрибутов SCHECK_MSG PKG_STD.TLSTRING; -- Сообщение при проверке атрибутов
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -453,8 +451,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */ /* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_ENT_ATTRS_SET; end QUERY_ENT_ATTRS_SET;
/* Добавление связи в запрос */ /* Добавление связи в запрос */
@ -467,8 +464,6 @@ create or replace package body PKG_P8PANELS_QE as
is is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -481,8 +476,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */ /* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_RL_ADD; end QUERY_RL_ADD;
/* Удаление связи из запроса */ /* Удаление связи из запроса */
@ -494,8 +488,6 @@ create or replace package body PKG_P8PANELS_QE as
is is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -508,8 +500,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */ /* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_RL_REMOVE; end QUERY_RL_REMOVE;
/* Установка признака обязательности связи */ /* Установка признака обязательности связи */
@ -522,8 +513,6 @@ create or replace package body PKG_P8PANELS_QE as
is is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Читаем запись запроса */ /* Читаем запись запроса */
RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN); RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN);
@ -534,8 +523,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */ /* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_RL_MANDATORY_SET; end QUERY_RL_MANDATORY_SET;
/* Добавление аргумента запроса */ /* Добавление аргумента запроса */
@ -567,6 +555,8 @@ create or replace package body PKG_P8PANELS_QE as
SVALUE => SVALUE); SVALUE => SVALUE);
/* Сохраняем обновленную настройку */ /* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT); PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_OPT_ARG_ADD; end QUERY_OPT_ARG_ADD;
/* Изменение аргумента запроса */ /* Изменение аргумента запроса */
@ -608,6 +598,8 @@ create or replace package body PKG_P8PANELS_QE as
SVALUE => SVALUE); SVALUE => SVALUE);
/* Сохраняем обновленную настройку */ /* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT); PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_OPT_ARG_EDIT; end QUERY_OPT_ARG_EDIT;
/* Удаление аргумента запроса */ /* Удаление аргумента запроса */
@ -637,6 +629,8 @@ create or replace package body PKG_P8PANELS_QE as
PKG_P8PANELS_QE_BASE.TARGS_REMOVE(RARGS => ROPT.RARGS, SNAME => SNAME); PKG_P8PANELS_QE_BASE.TARGS_REMOVE(RARGS => ROPT.RARGS, SNAME => SNAME);
/* Сохраняем обновленную настройку */ /* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT); PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_OPT_ARG_REMOVE; end QUERY_OPT_ARG_REMOVE;
/* Установка условий отбора запроса */ /* Установка условий отбора запроса */
@ -648,8 +642,6 @@ create or replace package body PKG_P8PANELS_QE as
is is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin begin
/* Провим права доступа */ /* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -662,9 +654,35 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленную настройку */ /* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT); PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */ /* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG); PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_OPT_COND_SET; end QUERY_OPT_COND_SET;
/* Переключение флага подстановки значений аргументов запроса в SQL-выражение */
procedure QUERY_OPT_SUBST_ARGS_VALS_TGL
(
NRN in number -- Рег. номер запроса
)
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
/* Читаем запись запроса */
RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN);
/* Читаем текущую настройку */
ROPT := PKG_P8PANELS_QE_BASE.QUERY_OPT_GET(COPT => RQ.OPT);
/* Установим новый флаг подстановки значений аргументов в запрос */
if (ROPT.NSUBST_ARGS_VALS = 1) then
ROPT.NSUBST_ARGS_VALS := 0;
else
ROPT.NSUBST_ARGS_VALS := 1;
end if;
/* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_OPT_SUBST_ARGS_VALS_TGL;
end PKG_P8PANELS_QE; end PKG_P8PANELS_QE;
/ /

View File

@ -16,8 +16,9 @@ create or replace package PKG_P8PANELS_QE_BASE as
/* Типы данных - Настройка запроса */ /* Типы данных - Настройка запроса */
type TOPT is record type TOPT is record
( (
RARGS TARGS, -- Аргументы RARGS TARGS, -- Аргументы
SCOND PKG_STD.TSTRING -- Условия отбора SCOND PKG_STD.TSTRING, -- Условия отбора
NSUBST_ARGS_VALS PKG_STD.TNUMBER -- Флаг подстановки значений аргументов в запрос (1 - да, 0 - нет)
); );
/* Типы данных - Атрибут сущности */ /* Типы данных - Атрибут сущности */
@ -329,19 +330,18 @@ create or replace package PKG_P8PANELS_QE_BASE as
ROPT in TOPT -- Настройка запроса ROPT in TOPT -- Настройка запроса
); );
/* Запись SQL-выражения запроса */ /* Обновление SQL-выражения запроса */
procedure QUERY_QRY_SET procedure QUERY_QRY_REFRESH
( (
NRN in number, -- Рег. номер запроса NRN in number -- Рег. номер запроса
CQRY in clob, -- SQL-выражение
CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
); );
/* Формирование SQL запроса */ /* Формирование SQL-выражения запроса */
procedure QUERY_SQL_BUILD procedure QUERY_QRY_BUILD
( (
NRN in number, -- Рег. номер запроса NRN in number, -- Рег. номер запроса
SQRY out varchar2, -- SQL-выражение SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
); );
@ -354,21 +354,23 @@ create or replace package body PKG_P8PANELS_QE_BASE as
SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление
/* Константы - Теги для сериализации */ /* Константы - Теги для сериализации */
STAG_DATA constant PKG_STD.TSTRING := 'XDATA'; -- Данные STAG_DATA constant PKG_STD.TSTRING := 'XDATA'; -- Данные
STAG_QUERIES constant PKG_STD.TSTRING := 'XQUERIES'; -- Запросы STAG_QUERIES constant PKG_STD.TSTRING := 'XQUERIES'; -- Запросы
STAG_QUERY constant PKG_STD.TSTRING := 'XQUERY'; -- Запрос STAG_QUERY constant PKG_STD.TSTRING := 'XQUERY'; -- Запрос
STAG_ARGS constant PKG_STD.TSTRING := 'XARGS'; -- Аргументы запроса STAG_ARGS constant PKG_STD.TSTRING := 'XARGS'; -- Аргументы запроса
STAG_ARG constant PKG_STD.TSTRING := 'XARG'; -- Аргумент запроса STAG_ARG constant PKG_STD.TSTRING := 'XARG'; -- Аргумент запроса
STAG_ATTRS constant PKG_STD.TSTRING := 'XATTRS'; -- Атрибуты сущности STAG_ATTRS constant PKG_STD.TSTRING := 'XATTRS'; -- Атрибуты сущности
STAG_ATTR constant PKG_STD.TSTRING := 'XATTR'; -- Атрибут сущности STAG_ATTR constant PKG_STD.TSTRING := 'XATTR'; -- Атрибут сущности
STAG_ENTS constant PKG_STD.TSTRING := 'XENTS'; -- Сущности STAG_ENTS constant PKG_STD.TSTRING := 'XENTS'; -- Сущности
STAG_ENT constant PKG_STD.TSTRING := 'XENT'; -- Сущность STAG_ENT constant PKG_STD.TSTRING := 'XENT'; -- Сущность
STAG_RLS constant PKG_STD.TSTRING := 'XRLS'; -- Связи STAG_RLS constant PKG_STD.TSTRING := 'XRLS'; -- Связи
STAG_RL constant PKG_STD.TSTRING := 'XRL'; -- Связь STAG_RL constant PKG_STD.TSTRING := 'XRL'; -- Связь
STAG_OPT constant PKG_STD.TSTRING := 'XOPT'; -- Настройка запроса STAG_OPT constant PKG_STD.TSTRING := 'XOPT'; -- Настройка запроса
STAG_COND constant PKG_STD.TSTRING := 'XCOND'; -- Условия запроса STAG_COND constant PKG_STD.TSTRING := 'XCOND'; -- Условия запроса
STAG_QRY constant PKG_STD.TSTRING := 'XQRY'; -- SQL-выражение запроса STAG_SUBST_ARGS_VALS constant PKG_STD.TSTRING := 'XSUBST_ARGS_VALS'; -- Флаг подстановки значений аргументов в запрос
STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса STAG_QRY constant PKG_STD.TSTRING := 'XQRY'; -- SQL-выражение запроса
STAG_QRY_BND constant PKG_STD.TSTRING := 'XQRY_BND'; -- SQL-выражение запроса с подстановками
STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса
/* Константы - Атрибуты для сериализации */ /* Константы - Атрибуты для сериализации */
SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор
@ -475,6 +477,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as
P_EXCEPTION(0, P_EXCEPTION(0,
'Имя аргумента содержит недопустимые символы (разрешены латинские буквы, цифры и символ нижнего подчеркивания).'); 'Имя аргумента содержит недопустимые символы (разрешены латинские буквы, цифры и символ нижнего подчеркивания).');
end loop; end loop;
for C in (select null from DUAL where not REGEXP_LIKE(SUBSTR(SNAME, 1, 1), '^[A-z]+$'))
loop
P_EXCEPTION(0, 'Имя аргумента должно начинаться с буквы.');
end loop;
if (UPPER(SNAME) in (UPPER(SARG_NAME_PAGE), UPPER(SARG_NAME_PAGE_SIZE))) then if (UPPER(SNAME) in (UPPER(SARG_NAME_PAGE), UPPER(SARG_NAME_PAGE_SIZE))) then
P_EXCEPTION(0, 'Это имя аргумента зарезервировано Системой.'); P_EXCEPTION(0, 'Это имя аргумента зарезервировано Системой.');
end if; end if;
@ -582,7 +588,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
loop loop
begin begin
/* Возвращаем найденный индекс */ /* Возвращаем найденный индекс */
if (RARGS(I).SNAME = SNAME) then if (UPPER(RARGS(I).SNAME) = UPPER(SNAME)) then
return I; return I;
end if; end if;
exception exception
@ -614,7 +620,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end if; end if;
/* Проверим уникальность имени */ /* Проверим уникальность имени */
if ((SNAME is not null) and (TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => SNAME) is not null)) then if ((SNAME is not null) and (TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => SNAME) is not null)) then
P_EXCEPTION(0, 'Аргумент с именем "%s" уже существует.', SNAME); P_EXCEPTION(0, 'Аргумент с именем "%s" уже существует.', UPPER(SNAME));
end if; end if;
/* Формируем аргумент */ /* Формируем аргумент */
RARG := TARG_MAKE(SNAME => SNAME, RARG := TARG_MAKE(SNAME => SNAME,
@ -768,6 +774,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
TARGS_TO_XML(RARGS => ROPT.RARGS); TARGS_TO_XML(RARGS => ROPT.RARGS);
/* Условия отбора */ /* Условия отбора */
PKG_XFAST.HERB(SNAME => STAG_COND, SVALUE => ROPT.SCOND); PKG_XFAST.HERB(SNAME => STAG_COND, SVALUE => ROPT.SCOND);
/* Флаг подстановки значений аргументов в запрос */
PKG_XFAST.HERB(SNAME => STAG_SUBST_ARGS_VALS, NVALUE => ROPT.NSUBST_ARGS_VALS);
/* Закрываем описание настройки */ /* Закрываем описание настройки */
PKG_XFAST.UP(); PKG_XFAST.UP();
end TOPT_TO_XML; end TOPT_TO_XML;
@ -795,9 +803,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as
/* Считаваем узел настройки */ /* Считаваем узел настройки */
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_OPT); XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_OPT);
/* Получаем значения */ /* Получаем значения */
RRES.SCOND := PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => STAG_COND); RRES.SCOND := PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => STAG_COND);
RRES.RARGS := TARGS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE, RRES.NSUBST_ARGS_VALS := PKG_XPATH.VALUE_NUM(RNODE => XNODE, SPATTERN => STAG_SUBST_ARGS_VALS);
SPATTERN => STAG_ARGS))); RRES.RARGS := TARGS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE,
SPATTERN => STAG_ARGS)));
/* Освободим документ */ /* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC); PKG_XPATH.FREE(RDOCUMENT => XDOC);
exception exception
@ -2334,6 +2343,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end if; end if;
/* SQL-выражение */ /* SQL-выражение */
PKG_XFAST.HERB(SNAME => STAG_QRY, LCVALUE => RQ.QRY); PKG_XFAST.HERB(SNAME => STAG_QRY, LCVALUE => RQ.QRY);
/* SQL-выражение с подстановками */
PKG_XFAST.HERB(SNAME => STAG_QRY_BND, LCVALUE => RQ.QRY_BND);
/* Сообщение при формировании SQL-выражения */ /* Сообщение при формировании SQL-выражения */
PKG_XFAST.HERB(SNAME => STAG_QRY_MSG, LCVALUE => RQ.QRY_MSG); PKG_XFAST.HERB(SNAME => STAG_QRY_MSG, LCVALUE => RQ.QRY_MSG);
/* Закрываем корень */ /* Закрываем корень */
@ -2689,6 +2700,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
( (
NRN in number, -- Рег. номер запроса NRN in number, -- Рег. номер запроса
CQRY in clob, -- SQL-выражение CQRY in clob, -- SQL-выражение
CQRY_BND in clob, -- SQL-выражение с подставленными значениями аргументов
CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
) )
is is
@ -2696,6 +2708,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
/* Сохраним её */ /* Сохраним её */
update P8PNL_QE_QUERY T update P8PNL_QE_QUERY T
set T.QRY = CQRY, set T.QRY = CQRY,
T.QRY_BND = CQRY_BND,
T.QRY_MSG = CQRY_MSG T.QRY_MSG = CQRY_MSG
where T.RN = NRN; where T.RN = NRN;
/* Контроль изменения данных */ /* Контроль изменения данных */
@ -2706,11 +2719,28 @@ create or replace package body PKG_P8PANELS_QE_BASE as
QUERY_CH_DATE_SYNC(NRN => NRN); QUERY_CH_DATE_SYNC(NRN => NRN);
end QUERY_QRY_SET; end QUERY_QRY_SET;
/* Формирование SQL запроса */ /* Обновление SQL-выражения запроса */
procedure QUERY_SQL_BUILD procedure QUERY_QRY_REFRESH
(
NRN in number -- Рег. номер запроса
)
is
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_BND PKG_STD.TLSTRING; -- SQL-выражение запроса с подстановками
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Сформируем SQL-выражение */
QUERY_QRY_BUILD(NRN => NRN, SQRY => SQRY, SQRY_BND => SQRY_BND, SQRY_MSG => SQRY_MSG);
/* Обновим его в запросе */
QUERY_QRY_SET(NRN => NRN, CQRY => SQRY, CQRY_BND => SQRY_BND, CQRY_MSG => SQRY_MSG);
end QUERY_QRY_REFRESH;
/* Формирование SQL-выражения запроса */
procedure QUERY_QRY_BUILD
( (
NRN in number, -- Рег. номер запроса NRN in number, -- Рег. номер запроса
SQRY out varchar2, -- SQL-выражение SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
) )
is is
@ -2720,7 +2750,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
ROPT TOPT; -- Настройка запроса ROPT TOPT; -- Настройка запроса
/* Кумулятивная установка сообщения формирования запроса */ /* Кумулятивная установка сообщения формирования запроса */
procedure SET_MSG procedure ADD_QRY_MSG
( (
SMESSAGE in varchar2, -- Текст сообщения SMESSAGE in varchar2, -- Текст сообщения
BCLEAR_QRY in boolean := true -- Флаг очистки сформированного запроса BCLEAR_QRY in boolean := true -- Флаг очистки сформированного запроса
@ -2728,14 +2758,45 @@ create or replace package body PKG_P8PANELS_QE_BASE as
is is
begin begin
if (BCLEAR_QRY) then if (BCLEAR_QRY) then
SQRY := null; SQRY := null;
SQRY_BND := null;
end if; end if;
if (SQRY_MSG is null) then if (SQRY_MSG is null) then
SQRY_MSG := SMESSAGE; SQRY_MSG := SMESSAGE;
else else
SQRY_MSG := SQRY_MSG || CHR(10) || CHR(13) || SMESSAGE; SQRY_MSG := SQRY_MSG || CHR(10) || CHR(13) || SMESSAGE;
end if; end if;
end SET_MSG; end ADD_QRY_MSG;
/* Проверка соответствия условий запроса набору его аргументов */
procedure CHECK_COND_ARGS
(
ROPT TOPT -- Настройка запроса
)
is
RCOND_VARS PKG_CONTVARLOC.TCONTAINER; -- Коллекция переменных условия запроса
SCOND_VAR PKG_STD.TSTRING; -- Текущая переменная условия запроса
begin
/* Извлечен переменные из условия запроса */
RCOND_VARS := PKG_SQL_BUILD.VAR_LIST(SSQL => ROPT.SCOND);
/* Если переменные в условии есть */
if (PKG_CONTVARLOC.COUNT_(RCONTAINER => RCOND_VARS) > 0) then
/* Обходим их */
SCOND_VAR := PKG_CONTVARLOC.FIRST_(RCONTAINER => RCOND_VARS);
while (SCOND_VAR is not null)
loop
/* Проверяем вхождение текущей переменной в состав аргументов запроса */
if (TARGS_INDEX_BY_NAME(RARGS => ROPT.RARGS, SNAME => SCOND_VAR) is null) then
/* В аргументах такой нет - добавляем предупреждение */
ADD_QRY_MSG(SMESSAGE => 'Переменная условия запроса "' || SCOND_VAR ||
'" отсутствует в составе его аргументов.',
BCLEAR_QRY => false);
end if;
/* Ищем следующу */
SCOND_VAR := PKG_CONTVARLOC.NEXT_(RCONTAINER => RCOND_VARS, SNAME => SCOND_VAR);
end loop;
end if;
end CHECK_COND_ARGS;
/* Поиск корневой (не имеет связей по выходу - т.е. нигде не является источником) сущности запроса */ /* Поиск корневой (не имеет связей по выходу - т.е. нигде не является источником) сущности запроса */
procedure FIND_ROOT_ENT procedure FIND_ROOT_ENT
@ -2898,7 +2959,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end if; end if;
else else
/* Корневую сущность не нашли */ /* Корневую сущность не нашли */
SET_MSG(SMESSAGE => SMESSAGE, BCLEAR_QRY => false); ADD_QRY_MSG(SMESSAGE => SMESSAGE, BCLEAR_QRY => false);
end if; end if;
end BUILD_FROM; end BUILD_FROM;
@ -2912,35 +2973,71 @@ create or replace package body PKG_P8PANELS_QE_BASE as
begin begin
if (ROPT.SCOND is not null) then if (ROPT.SCOND is not null) then
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'where ' || ROPT.SCOND); PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'where ' || ROPT.SCOND);
end if; end if;
end BUILD_WHERE; end BUILD_WHERE;
/* Подстановка отладочных значений в SQL-выражение */
procedure BOUND
(
ROPT TOPT, -- Настройка запроса
SQRY in varchar2, -- Сформированное SQL-выражение
SQRY_BND out varchar2 -- SQL-выражение с подстановками
)
is
begin
SQRY_BND := SQRY;
if ((ROPT.RARGS is not null) and (ROPT.RARGS.COUNT > 0)) then
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
loop
begin
case
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_STR(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
SVALUE => ROPT.RARGS(I).SVALUE);
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_NUM(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
NVALUE => TO_NUMBER(ROPT.RARGS(I).SVALUE));
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_DATE(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
DVALUE => TO_DATE(ROPT.RARGS(I).SVALUE, 'yyyy-mm-dd'));
else
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_ANY(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
SANY => ROPT.RARGS(I).SVALUE);
end case;
exception
when others then
ADD_QRY_MSG(SMESSAGE => 'Ошибка конвертации при подстановке значения "' || ROPT.RARGS(I).SVALUE ||
'" в аргумент запроса "' || ROPT.RARGS(I).SNAME || '".',
BCLEAR_QRY => false);
end;
end loop;
end if;
end BOUND;
begin begin
/*
TODO: owner="root" created="10.09.2025"
text="Предусмотреть отладочные значения для аргументов запроса"
*/
/*
TODO: owner="root" created="11.09.2025"
text="Проверять соответствие условий отбора запроса набору его аргументов"
*/
/* Читаем описание запроса */ /* Читаем описание запроса */
RQ := QUERY_GET(NRN => NRN); RQ := QUERY_GET(NRN => NRN);
/* Читаем сущности запроса */ /* Читаем сущности запроса */
RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS); RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS);
/* Нет сущностей - нет запроса */ /* Нет сущностей - нет запроса */
if ((RENTS is null) or (RENTS.COUNT = 0)) then if ((RENTS is null) or (RENTS.COUNT = 0)) then
SET_MSG(SMESSAGE => 'В запросе нет сущностей.'); ADD_QRY_MSG(SMESSAGE => 'В запросе нет сущностей.');
return; return;
end if; end if;
/* Читаем связи запроса */ /* Читаем связи запроса */
RRLS := QUERY_RLS_GET(CRLS => RQ.RLS); RRLS := QUERY_RLS_GET(CRLS => RQ.RLS);
/* Нельзя построить запрос, если есть несвязанные сущности */ /* Нельзя построить запрос, если есть несвязанные сущности */
if ((RENTS.COUNT > 1) and ((RRLS is null) or (RENTS.COUNT - 1 > RRLS.COUNT))) then if ((RENTS.COUNT > 1) and ((RRLS is null) or (RENTS.COUNT - 1 > RRLS.COUNT))) then
SET_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.'); ADD_QRY_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.');
return; return;
end if; end if;
/* Читаем настройку запроса */ /* Читаем настройку запроса */
ROPT := QUERY_OPT_GET(COPT => RQ.OPT); ROPT := QUERY_OPT_GET(COPT => RQ.OPT);
/* Проверяем параметры запроса */
CHECK_COND_ARGS(ROPT => ROPT);
/* Добавляем подсказку совместимости */ /* Добавляем подсказку совместимости */
SQRY := PKG_SQL_BUILD.COMPATIBLE(SSQL => SQRY); SQRY := PKG_SQL_BUILD.COMPATIBLE(SSQL => SQRY);
/* Собираем запрос - поля */ /* Собираем запрос - поля */
@ -2949,11 +3046,13 @@ create or replace package body PKG_P8PANELS_QE_BASE as
BUILD_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY); BUILD_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
/* Собираем запрос - условия */ /* Собираем запрос - условия */
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY); BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
/* Сделаем подстановки */
BOUND(ROPT => ROPT, SQRY => SQRY, SQRY_BND => SQRY_BND);
exception exception
when others then when others then
PKG_STATE.DIAGNOSTICS_STACKED(); PKG_STATE.DIAGNOSTICS_STACKED();
SET_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false); ADD_QRY_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false);
end QUERY_SQL_BUILD; end QUERY_QRY_BUILD;
end PKG_P8PANELS_QE_BASE; end PKG_P8PANELS_QE_BASE;
/ /

View File

@ -3,5 +3,6 @@ grant execute on PKG_P8PANELS_PROJECTS to public;
grant execute on PKG_P8PANELS_SAMPLES to public; grant execute on PKG_P8PANELS_SAMPLES to public;
grant execute on PKG_P8PANELS_EQUIPSRV to public; grant execute on PKG_P8PANELS_EQUIPSRV to public;
grant execute on PKG_P8PANELS_RRPCONFED to public; grant execute on PKG_P8PANELS_RRPCONFED to public;
grant execute on PKG_P8PANELS_CLNTTSKBRD to public;
grant execute on PKG_P8PANELS_PE to public; grant execute on PKG_P8PANELS_PE to public;
grant execute on PKG_P8PANELS_QE to public; grant execute on PKG_P8PANELS_QE to public;

1159
dist/p8-panels.js vendored

File diff suppressed because one or more lines are too long

BIN
img/clnt_task_board.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

View File

@ -28,6 +28,12 @@
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelAssemblyMon" caption="Мониторинг сборки изделий" panelName="MechRecAssemblyMon"/> <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelAssemblyMon" caption="Мониторинг сборки изделий" panelName="MechRecAssemblyMon"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelHelp" caption="Руководство &quot;Оперативное управление производством&quot;" panelName="MechRecHelp"/> <MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelHelp" caption="Руководство &quot;Оперативное управление производством&quot;" panelName="MechRecHelp"/>
</App> </App>
<App name="Client">
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowClntPanelsRoot" caption="Панели мониторинга" url="Modules/P8-Panels/"/>
<MenuItem parent="{CA9A9853-AC90-412A-85B1-E39927147846}" separator="true"/>
<MenuItem parent="{CA9A9853-AC90-412A-85B1-E39927147846}" name="ShowClntTaskBoard" caption="Доски задач" panelName="ClntTaskBoard"/>
</App>
</MenuItems> </MenuItems>
<Panels urlBase="Modules/P8-Panels/#/"> <Panels urlBase="Modules/P8-Panels/#/">
<Panel <Panel
@ -180,5 +186,15 @@
icon="" icon=""
showInPanelsList="false" showInPanelsList="false"
preview=""/> preview=""/>
<Panel
name="ClntTaskBoard"
group="Управление деловыми процессами"
caption="Доски задач"
desc="Мониторинг и управление назначенными задачами на Канбан-доске"
url="clnt_task_board"
path="clnt_task_board"
icon="dashboard_customize"
showInPanelsList="true"
preview="./img/clnt_task_board.jpg"/>
</Panels> </Panels>
</CITK.P8Panels> </CITK.P8Panels>