Панель "Доски задач" - добавление перенесено в заголовок, исправлены ошибки работы заливки событий по условиям

This commit is contained in:
Mikhail Chechnev 2025-10-23 17:39:50 +03:00
parent a7a883ecc6
commit 2ad4cfdba9
7 changed files with 170 additions and 178 deletions

View File

@ -76,9 +76,6 @@ const ClntTaskBoard = () => {
//Состояние доступных маршрутов события //Состояние доступных маршрутов события
const [availableRoutes, setAvailableRoutes] = useState({ source: "", routes: [] }); const [availableRoutes, setAvailableRoutes] = useState({ source: "", routes: [] });
//Состояние перетаскиваемого события
const [dragItem, setDragItem] = useState({ type: "", status: "" });
//При открытии/закрытии диалога фильтра //При открытии/закрытии диалога фильтра
const handleFilterOpen = isOpen => { const handleFilterOpen = isOpen => {
setDialogsState(pv => ({ ...pv, filterDialogIsOpen: isOpen })); setDialogsState(pv => ({ ...pv, filterDialogIsOpen: isOpen }));
@ -152,18 +149,6 @@ const ClntTaskBoard = () => {
setAvailableRoutes({ source: "", routes: [] }); setAvailableRoutes({ source: "", routes: [] });
}; };
//Обработка захвата перетаскиваемого объекта
const handleDragItemChange = (filtersType, statusCode) =>
setDragItem({
type: filtersType,
status: statusCode
});
//Обработка очистки перетаскиваемого объекта
const handleDragItemClear = () => {
setDragItem({ type: "", status: "" });
};
//Проверка доступности карточки события //Проверка доступности карточки события
const isCardAvailable = code => { const isCardAvailable = code => {
return availableRoutes.source === code || availableRoutes.routes.find(r => r.SDESTINATION === code) || !availableRoutes.source ? true : false; return availableRoutes.source === code || availableRoutes.routes.find(r => r.SDESTINATION === code) || !availableRoutes.source ? true : false;
@ -209,18 +194,17 @@ const ClntTaskBoard = () => {
/> />
) : null} ) : null}
{dialogsState.taskDialogIsOpen ? ( {dialogsState.taskDialogIsOpen ? (
<TaskDialog <TaskDialog taskType={filters.values.sType} onTasksReload={() => handleTasksReload(true)} onClose={handleTaskDialogOpen} />
taskType={dragItem.type}
taskStatus={dragItem.status}
onTasksReload={() => handleTasksReload(true)}
onClose={() => {
handleTaskDialogOpen();
handleDragItemClear();
}}
/>
) : null} ) : null}
<Box sx={STYLES.BOX_FILTER}> <Box sx={STYLES.BOX_FILTER}>
<Stack direction="row"> <Stack direction="row">
<Box>
<Stack direction="row" pl={1} pt={1}>
<IconButton onClick={handleTaskDialogOpen} title={"Добавить событие"}>
<Icon>add</Icon>
</IconButton>
</Stack>
</Box>
<Filter <Filter
isFilterDialogOpen={dialogsState.filterDialogIsOpen} isFilterDialogOpen={dialogsState.filterDialogIsOpen}
filter={filters.values} filter={filters.values}
@ -282,11 +266,8 @@ const ClntTaskBoard = () => {
statusTitle={status[statusesState.attr] || status.SEVNSTAT_NAME} statusTitle={status[statusesState.attr] || status.SEVNSTAT_NAME}
colorRules={colorRules} colorRules={colorRules}
extraData={extraData} extraData={extraData}
filtersType={filters.values.sType}
isCardAvailable={isCardAvailable} isCardAvailable={isCardAvailable}
onTasksReload={handleTasksReload} onTasksReload={handleTasksReload}
onDragItemChange={handleDragItemChange}
onTaskDialogOpen={handleTaskDialogOpen}
onNoteDialogOpen={handleNoteOpen} onNoteDialogOpen={handleNoteOpen}
onStatusColorChange={handleSettingStatusColorChange} onStatusColorChange={handleSettingStatusColorChange}
placeholder={provided.placeholder} placeholder={provided.placeholder}

View File

@ -9,7 +9,7 @@
import React, { useState } from "react"; //Классы React import React, { useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogTitle, DialogContent, DialogActions, IconButton, Icon, Button, Box, Stack } from "@mui/material"; //Интерфейсные компоненты import { Dialog, DialogTitle, DialogContent, DialogActions, IconButton, Icon, Button, Box, Stack, Typography } from "@mui/material"; //Интерфейсные компоненты
import { CustomInputField } from "./custom_input_field.js"; //Кастомное поле ввода import { CustomInputField } from "./custom_input_field.js"; //Кастомное поле ввода
import { sortAttrs, sortDest } from "../layouts.js"; //Допустимые значение поля и направления сортировки import { sortAttrs, sortDest } from "../layouts.js"; //Допустимые значение поля и направления сортировки
import { hasValue } from "../../../core/utils.js"; //Проверка наличия значения import { hasValue } from "../../../core/utils.js"; //Проверка наличия значения
@ -63,9 +63,23 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => {
<CustomInputField <CustomInputField
elementCode="clrRules" elementCode="clrRules"
elementValue={hasValue(colorRules.selectedColorRule.id) && colorRules.length !== 0 ? colorRules.selectedColorRule.id : -1} elementValue={hasValue(colorRules.selectedColorRule.id) && colorRules.length !== 0 ? colorRules.selectedColorRule.id : -1}
labelText="Заливка событий" labelText="Заливка событий*"
items={colorRules.rules.reduce((prev, cur) => [...prev, { id: cur.id, caption: cur.SDP_NAME }], [])} items={colorRules.rules.reduce(
emptyItem={{ key: -1, id: -1, caption: "-" }} (prev, cur) => [
...prev,
{
id: cur.id,
caption:
`${cur.SDP_NAME}` +
(cur.STYPE == "string"
? `${cur.fromValue ? `, значение "${cur.fromValue}"` : ""}`
: `${cur.fromValue ? `, с ${cur.fromValue}` : ""}` + `${cur.toValue ? `, по ${cur.toValue}` : ""}`) +
`${cur.SCOLOR ? `, ${cur.SCOLOR}` : ""}`
}
],
[]
)}
emptyItem={{ key: -1, id: -1, caption: "Нет" }}
onChange={handleColorRuleChange} onChange={handleColorRuleChange}
sx={STYLES.SELECT} sx={STYLES.SELECT}
/> />
@ -75,7 +89,7 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => {
<CustomInputField <CustomInputField
elementCode="attr" elementCode="attr"
elementValue={statusesState.attr} elementValue={statusesState.attr}
labelText="Поле сортировки" labelText="Порядок сортировки колонок"
items={sortAttrs.reduce((prev, cur) => [...prev, { id: cur.id, caption: cur.descr }], [])} items={sortAttrs.reduce((prev, cur) => [...prev, { id: cur.id, caption: cur.descr }], [])}
onChange={handleSortAttrChange} onChange={handleSortAttrChange}
sx={STYLES.SELECT} sx={STYLES.SELECT}
@ -88,6 +102,10 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => {
</IconButton> </IconButton>
</Stack> </Stack>
</Box> </Box>
<Typography variant={"caption"}>
*Поддерживаются правила заливки, базирующиеся на дополнительных свойствах типа &quot;Строка&quot; или &quot;Число&quot;, из
профиля пользователя, настроенного для раздела &quot;События&quot; в WEB-интерфейсе данного приложения.
</Typography>
</DialogContent> </DialogContent>
<DialogActions sx={COMMON_STYLES.DIALOG_ACTIONS}> <DialogActions sx={COMMON_STYLES.DIALOG_ACTIONS}>
<Button <Button

View File

@ -9,7 +9,7 @@
import React, { useState } from "react"; //Классы React import React, { useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import { Card, CardHeader, CardContent, Button, IconButton, Icon, Typography, Stack } from "@mui/material"; //Интерфейсные компоненты import { Card, CardHeader, CardContent, IconButton, Icon, Typography, Stack } from "@mui/material"; //Интерфейсные компоненты
import { TaskCard } from "./task_card.js"; //Компонент Карточка события import { TaskCard } from "./task_card.js"; //Компонент Карточка события
import { StatusCardSettings } from "./status_card_settings.js"; //Компонент Диалог настройки карточки событий import { StatusCardSettings } from "./status_card_settings.js"; //Компонент Диалог настройки карточки событий
import { APP_STYLES } from "../../../../app.styles"; //Типовые стили import { APP_STYLES } from "../../../../app.styles"; //Типовые стили
@ -58,7 +58,7 @@ const STYLES = {
paddingRight: "5px", paddingRight: "5px",
paddingBottom: "5px !important", paddingBottom: "5px !important",
overflowY: "auto", overflowY: "auto",
maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TITLE_PADDING_BOTTOM} - ${FILTER_HEIGHT} - 85px)`, maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TITLE_PADDING_BOTTOM} - ${FILTER_HEIGHT} - 55px)`,
...APP_STYLES.SCROLL ...APP_STYLES.SCROLL
} }
}; };
@ -74,11 +74,8 @@ const StatusCard = ({
statusTitle, statusTitle,
colorRules, colorRules,
extraData, extraData,
filtersType,
isCardAvailable, isCardAvailable,
onTasksReload, onTasksReload,
onDragItemChange,
onTaskDialogOpen,
onNoteDialogOpen, onNoteDialogOpen,
onStatusColorChange, onStatusColorChange,
placeholder placeholder
@ -123,16 +120,6 @@ const StatusCard = ({
{statusTitle} {statusTitle}
</Typography> </Typography>
} }
subheader={
<Button
onClick={() => {
onDragItemChange(filtersType, status.SEVNSTAT_CODE);
onTaskDialogOpen();
}}
>
+ Добавить
</Button>
}
sx={STYLES.CARD_HEADER} sx={STYLES.CARD_HEADER}
/> />
<CardContent sx={STYLES.CARD_CONTENT}> <CardContent sx={STYLES.CARD_CONTENT}>
@ -165,11 +152,8 @@ StatusCard.propTypes = {
statusTitle: PropTypes.string.isRequired, statusTitle: PropTypes.string.isRequired,
colorRules: PropTypes.object.isRequired, colorRules: PropTypes.object.isRequired,
extraData: PropTypes.object.isRequired, extraData: PropTypes.object.isRequired,
filtersType: PropTypes.string.isRequired,
isCardAvailable: PropTypes.func.isRequired, isCardAvailable: PropTypes.func.isRequired,
onTasksReload: PropTypes.func.isRequired, onTasksReload: PropTypes.func.isRequired,
onDragItemChange: PropTypes.func.isRequired,
onTaskDialogOpen: PropTypes.func.isRequired,
onNoteDialogOpen: PropTypes.func.isRequired, onNoteDialogOpen: PropTypes.func.isRequired,
onStatusColorChange: PropTypes.func.isRequired, onStatusColorChange: PropTypes.func.isRequired,
placeholder: PropTypes.object.isRequired placeholder: PropTypes.object.isRequired

View File

@ -15,7 +15,7 @@ import { BackEndСtx } from "../../../context/backend"; //Контекст вз
//----------- //-----------
//Хук для события //Хук для события
const useClientEvent = (taskRn, taskType = "", taskStatus = "") => { const useClientEvent = (taskRn, taskType = "") => {
//Собственное состояние //Собственное состояние
const [task, setTask] = useState({ const [task, setTask] = useState({
init: true, init: true,
@ -24,7 +24,7 @@ const useClientEvent = (taskRn, taskType = "", taskStatus = "") => {
sPrefix: "", sPrefix: "",
sNumber: "", sNumber: "",
sType: taskType, sType: taskType,
sStatus: taskStatus, sStatus: "",
sDescription: "", sDescription: "",
sClntClients: "", sClntClients: "",
sClntClnperson: "", sClntClnperson: "",
@ -118,6 +118,7 @@ const useClientEvent = (taskRn, taskType = "", taskStatus = "") => {
...pv, ...pv,
sPrefix: data.SPREF, sPrefix: data.SPREF,
sNumber: data.SNUMB, sNumber: data.SNUMB,
sStatus: data.SSTATUS,
sCurrentUser: data.SINIT_AUTHNAME, sCurrentUser: data.SINIT_AUTHNAME,
sInitClnperson: data.SINIT_PERSON, sInitClnperson: data.SINIT_PERSON,
sInitUser: !data.SINIT_PERSON ? data.SINIT_AUTHNAME : "", sInitUser: !data.SINIT_PERSON ? data.SINIT_AUTHNAME : "",

View File

@ -12,8 +12,8 @@ export const EVENT_STATES = Object.freeze({ 0: "Все", 1: "Не аннулир
//Допустимые значение поля сортировки //Допустимые значение поля сортировки
export const sortAttrs = [ export const sortAttrs = [
{ id: "SEVNSTAT_CODE", descr: "Мнемокод" }, { id: "SEVNSTAT_CODE", descr: "Мнемокод статуса" },
{ id: "SEVNSTAT_NAME", descr: "Наименование" }, { id: "SEVNSTAT_NAME", descr: "Наименование статуса" },
{ id: "SEVPOINT_DESCR", descr: "Описание точки маршрута" } { id: "SEVPOINT_DESCR", descr: "Описание точки маршрута" }
]; ];
@ -73,24 +73,16 @@ const convertHexToRGB = hex => {
//Считывание заливки события по условию //Считывание заливки события по условию
export const getTaskBgColorByRule = (task, colorRule) => { export const getTaskBgColorByRule = (task, colorRule) => {
//Инициализируем значения //Исходя из типа определяем наименование и возвращаем цвет заливки
let ruleCode = "";
//Исходя из типа определяем наименование
switch (colorRule.STYPE) { switch (colorRule.STYPE) {
case "number": case "number":
ruleCode = `N${colorRule.SFIELD}`; return (!colorRule.fromValue || Number(task.docProps[`N${colorRule.SFIELD}`]) >= Number(colorRule.fromValue)) &&
break; (!colorRule.toValue || Number(task.docProps[`N${colorRule.SFIELD}`]) <= Number(colorRule.toValue))
case "date": ? convertHexToRGB(colorRule.SCOLOR)
ruleCode = `D${colorRule.SFIELD}`; : null;
break;
default: default:
ruleCode = `S${colorRule.SFIELD}`; return task.docProps[`S${colorRule.SFIELD}`] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null;
break;
} }
//Определяем цвет заливки
let bgColor = ruleCode && task.docProps[ruleCode] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null;
//Возвращаем цвет заливки
return bgColor;
}; };
//Индикация истечения срока отработки события //Индикация истечения срока отработки события

View File

@ -35,9 +35,9 @@ const STYLES = {
//----------- //-----------
//Диалог формы события //Диалог формы события
const TaskDialog = ({ taskRn, taskType, taskStatus, editable, onTasksReload, onClose }) => { const TaskDialog = ({ taskRn, taskType, editable, onTasksReload, onClose }) => {
//Собственное состояние //Собственное состояние
const [task, setTask] = useClientEvent(taskRn, taskType, taskStatus); const [task, setTask] = useClientEvent(taskRn, taskType);
//Состояние заполненности всех обязательных свойств //Состояние заполненности всех обязательных свойств
const [dpReady, setDPReady] = useState(false); const [dpReady, setDPReady] = useState(false);
@ -167,7 +167,6 @@ const TaskDialog = ({ taskRn, taskType, taskStatus, editable, onTasksReload, onC
TaskDialog.propTypes = { TaskDialog.propTypes = {
taskRn: PropTypes.number, taskRn: PropTypes.number,
taskType: PropTypes.string.isRequired, taskType: PropTypes.string.isRequired,
taskStatus: PropTypes.string,
editable: PropTypes.bool, editable: PropTypes.bool,
onTasksReload: PropTypes.func.isRequired, onTasksReload: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired onClose: PropTypes.func.isRequired

View File

@ -36,6 +36,7 @@ create or replace package PKG_P8PANELS_CLNTTSKBRD as
SEVENT_TYPE in varchar2, -- Мнемокод типа события SEVENT_TYPE in varchar2, -- Мнемокод типа события
SPREF out varchar2, -- Префикс события SPREF out varchar2, -- Префикс события
SNUMB out varchar2, -- Номер события SNUMB out varchar2, -- Номер события
SSTATUS out varchar2, -- Начальный статус
SINIT_PERSON out varchar2, -- Сотрудник - инициатор SINIT_PERSON out varchar2, -- Сотрудник - инициатор
SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор
); );
@ -1000,8 +1001,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
RDG_ROW => RDG_ROW, RDG_ROW => RDG_ROW,
TDP_NAMES => TDP_NAMES, TDP_NAMES => TDP_NAMES,
TDP_TYPES => TDP_TYPES, TDP_TYPES => TDP_TYPES,
NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES) - 1, NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES),
NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 2, NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 1,
ICURSOR => ICURSOR, ICURSOR => ICURSOR,
NACTION => 2); NACTION => 2);
end if; end if;
@ -1119,8 +1120,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
RDG_ROW => RDG_ROW, RDG_ROW => RDG_ROW,
TDP_NAMES => TDP_NAMES, TDP_NAMES => TDP_NAMES,
TDP_TYPES => TDP_TYPES, TDP_TYPES => TDP_TYPES,
NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES) - 1, NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES),
NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 2, NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 1,
ICURSOR => ICURSOR, ICURSOR => ICURSOR,
NACTION => 1); NACTION => 1);
end if; end if;
@ -1457,11 +1458,13 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
SEVENT_TYPE in varchar2, -- Мнемокод типа события SEVENT_TYPE in varchar2, -- Мнемокод типа события
SPREF out varchar2, -- Префикс события SPREF out varchar2, -- Префикс события
SNUMB out varchar2, -- Номер события SNUMB out varchar2, -- Номер события
SSTATUS out varchar2, -- Начальный статус
SINIT_PERSON out varchar2, -- Сотрудник - инициатор SINIT_PERSON out varchar2, -- Сотрудник - инициатор
SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор
) )
is is
NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса
NEVENT_TYPE PKG_STD.TREF; -- Рег. номер типа события
SOWNER_AGENT_RN PKG_STD.TSTRING; -- Рег. номер работодателя сотрудника SOWNER_AGENT_RN PKG_STD.TSTRING; -- Рег. номер работодателя сотрудника
STAB_PREF PKG_STD.TSTRING; -- Префикс табельного номера сотрудника STAB_PREF PKG_STD.TSTRING; -- Префикс табельного номера сотрудника
STAB_NUMB PKG_STD.TSTRING; -- Таблеьный номер сотрудника STAB_NUMB PKG_STD.TSTRING; -- Таблеьный номер сотрудника
@ -1490,6 +1493,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
return SRESULT; return SRESULT;
end CLNEVNTYPES_PREF_GET; end CLNEVNTYPES_PREF_GET;
begin begin
/* Определяем рег. номер типа события */
FIND_CLNEVNTYPES_CODE(NFLAG_SMART => 0, NCOMPANY => NCOMPANY, SEVNTYPE_CODE => SEVENT_TYPE, NRN => NEVENT_TYPE);
/* Считываем префикс из параметра */ /* Считываем префикс из параметра */
SPREF := GET_OPTIONS_STR(SCODE => 'EventPrefix', NCOMP_VERS => NCOMPANY); SPREF := GET_OPTIONS_STR(SCODE => 'EventPrefix', NCOMP_VERS => NCOMPANY);
/* Если префикс не указан в параметре и задан тип события */ /* Если префикс не указан в параметре и задан тип события */
@ -1502,6 +1507,21 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
/* Считываем номер */ /* Считываем номер */
SNUMB := GET_CLNEVENTS_NEXTNUMB(NCOMPANY => NCOMPANY, SPREF => SPREF); SNUMB := GET_CLNEVENTS_NEXTNUMB(NCOMPANY => NCOMPANY, SPREF => SPREF);
end if; end if;
/* Определим начальный статус */
begin
select T.SEVNSTAT_CODE
into SSTATUS
from V_CLNEVNTYPSTS_FOR_EVENTS T
where T.NPRN = NEVENT_TYPE
and ROWNUM <= 1
order by T.NDEFAULT_STATUS desc,
T.SEVNSTAT_CODE;
exception
when NO_DATA_FOUND then
P_EXCEPTION(0,
'Для событий типа "%s" не определена начальная точка маршрута.',
SEVENT_TYPE);
end;
/* Считываем сотрудника текущего пользователя */ /* Считываем сотрудника текущего пользователя */
FIND_PERSON_AUTHID(SPERSON => SINIT_PERSON, FIND_PERSON_AUTHID(SPERSON => SINIT_PERSON,
SOWNER_AGENT => SOWNER_AGENT_RN, SOWNER_AGENT => SOWNER_AGENT_RN,
@ -2259,6 +2279,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
is is
SAUTHID PKG_STD.TSTRING := PKG_SESSION.GET_UTILIZER(); -- Пользователь SAUTHID PKG_STD.TSTRING := PKG_SESSION.GET_UTILIZER(); -- Пользователь
NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
SAPPCODE PKG_STD.TSTRING := PKG_SESSION.GET_APPLICATION(); -- Код приложения сеанса
BXML blob; -- XML профиля пользователя для раздела "События" BXML blob; -- XML профиля пользователя для раздела "События"
RDOC PKG_XPATH.TDOCUMENT; -- Документ XML RDOC PKG_XPATH.TDOCUMENT; -- Документ XML
RNODE_ROOT PKG_XPATH.TNODE; -- Корневой узел RNODE_ROOT PKG_XPATH.TNODE; -- Корневой узел
@ -2275,8 +2296,6 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
NTO_VALUE PKG_STD.TNUMBER; -- Значение по (number) NTO_VALUE PKG_STD.TNUMBER; -- Значение по (number)
SFROM_VALUE PKG_STD.TSTRING; -- Значение с (string) SFROM_VALUE PKG_STD.TSTRING; -- Значение с (string)
STO_VALUE PKG_STD.TSTRING; -- Значение по (string) STO_VALUE PKG_STD.TSTRING; -- Значение по (string)
DFROM_VALUE PKG_STD.TLDATE; -- Значение с (date)
DTO_VALUE PKG_STD.TLDATE; -- Значение по (date)
/* Считывание наименования свойства документа */ /* Считывание наименования свойства документа */
function DOCS_PROPS_NAME_GET function DOCS_PROPS_NAME_GET
@ -2287,6 +2306,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
NRN PKG_STD.TREF; -- Рег. номер свойства документа NRN PKG_STD.TREF; -- Рег. номер свойства документа
SRESULT PKG_STD.TSTRING; -- Наименование доп. свойства SRESULT PKG_STD.TSTRING; -- Наименование доп. свойства
begin begin
/* Если переданный код свойства соответствует формату */
if (INSTR(SFIELD, 'DP_') <> 0) then
/* Определяем рег. номер свойства документа по формату "DP_<РЕГ_НОМЕР>" */ /* Определяем рег. номер свойства документа по формату "DP_<РЕГ_НОМЕР>" */
NRN := TO_NUMBER(SUBSTR(SFIELD, INSTR(SFIELD, '_') + 1)); NRN := TO_NUMBER(SUBSTR(SFIELD, INSTR(SFIELD, '_') + 1));
/* Считываем наименование из записи свойства документа */ /* Считываем наименование из записи свойства документа */
@ -2300,6 +2321,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
P_EXCEPTION(0, P_EXCEPTION(0,
'Ошибка считывания наименования свойства документа с рег. номером (%s).'); 'Ошибка считывания наименования свойства документа с рег. номером (%s).');
end; end;
end if;
/* Возвращаем результат */ /* Возвращаем результат */
return SRESULT; return SRESULT;
end DOCS_PROPS_NAME_GET; end DOCS_PROPS_NAME_GET;
@ -2308,6 +2330,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
function USERPROFILES_GET function USERPROFILES_GET
( (
NCOMPANY in number, -- Рег. номер организации NCOMPANY in number, -- Рег. номер организации
SAPPCODE in varchar2, -- Код приложения
SAUTHID in varchar2 -- Мнемокод пользователя SAUTHID in varchar2 -- Мнемокод пользователя
) return blob -- Профиль пользователя для раздела "События" ) return blob -- Профиль пользователя для раздела "События"
is is
@ -2322,7 +2345,12 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
and U.AUTHID = SAUTHID and U.AUTHID = SAUTHID
and U.REC_TYPE = 1 and U.REC_TYPE = 1
and U.UNITMODE = 0 and U.UNITMODE = 0
and U.UNITCODE = SUNIT_CLNEVENTS; and U.UNITCODE = SUNIT_CLNEVENTS
and U.KIND = 2
and U.UNITFUNC is null
and U.REC_KEY is null
and U.SHOW_METHOD = 'main'
and U.APPCODE = SAPPCODE;
exception exception
when others then when others then
return null; return null;
@ -2332,7 +2360,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
end USERPROFILES_GET; end USERPROFILES_GET;
begin begin
/* Считываем профиль пользователя для раздела "События" */ /* Считываем профиль пользователя для раздела "События" */
BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAUTHID => SAUTHID); BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAPPCODE => SAPPCODE, SAUTHID => SAUTHID);
/* Проверим, что профиль не пустой */ /* Проверим, что профиль не пустой */
if (BXML is null) then if (BXML is null) then
return; return;
@ -2359,13 +2387,15 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
SFIELD := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'field'); SFIELD := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'field');
SCOLOR := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'color'); SCOLOR := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'color');
SDATA_TYPE := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'dataType'); SDATA_TYPE := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'dataType');
/* Считываем наименование свойства документа */
SDP_NAME := DOCS_PROPS_NAME_GET(SFIELD => SFIELD);
/* Если это правило по доп. свойству и типа "строка" или "число" */
if (SDP_NAME is not null) and (SDATA_TYPE in ('number', 'string')) then
PKG_XFAST.DOWN_NODE(SNAME => 'XRULES'); PKG_XFAST.DOWN_NODE(SNAME => 'XRULES');
/* Код правила */ /* Код правила */
PKG_XFAST.DOWN_NODE(SNAME => 'SFIELD'); PKG_XFAST.DOWN_NODE(SNAME => 'SFIELD');
PKG_XFAST.VALUE(SVALUE => SFIELD); PKG_XFAST.VALUE(SVALUE => SFIELD);
PKG_XFAST.UP(); PKG_XFAST.UP();
/* Считываем наименование свойства документа */
SDP_NAME := DOCS_PROPS_NAME_GET(SFIELD => SFIELD);
/* Наименование доп. свойства */ /* Наименование доп. свойства */
PKG_XFAST.DOWN_NODE(SNAME => 'SDP_NAME'); PKG_XFAST.DOWN_NODE(SNAME => 'SDP_NAME');
PKG_XFAST.VALUE(SVALUE => SDP_NAME); PKG_XFAST.VALUE(SVALUE => SDP_NAME);
@ -2397,9 +2427,9 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
/* Строка */ /* Строка */
when 'string' then when 'string' then
SFROM_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, SFROM_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE,
SPATTERN => 'fromValue')); SPATTERN => 'value'));
STO_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, STO_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE,
SPATTERN => 'toValue')); SPATTERN => 'value'));
/* Строка с */ /* Строка с */
PKG_XFAST.DOWN_NODE(SNAME => 'SFROM'); PKG_XFAST.DOWN_NODE(SNAME => 'SFROM');
PKG_XFAST.VALUE(SVALUE => SFROM_VALUE); PKG_XFAST.VALUE(SVALUE => SFROM_VALUE);
@ -2408,22 +2438,9 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as
PKG_XFAST.DOWN_NODE(SNAME => 'STO'); PKG_XFAST.DOWN_NODE(SNAME => 'STO');
PKG_XFAST.VALUE(SVALUE => STO_VALUE); PKG_XFAST.VALUE(SVALUE => STO_VALUE);
PKG_XFAST.UP(); PKG_XFAST.UP();
/* Дата */
else
DFROM_VALUE := PKG_XPATH.VALUE_DATE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE,
SPATTERN => 'fromValue'));
DTO_VALUE := PKG_XPATH.VALUE_DATE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE,
SPATTERN => 'toValue'));
/* Дата с */
PKG_XFAST.DOWN_NODE(SNAME => 'DFROM');
PKG_XFAST.VALUE(DVALUE => DFROM_VALUE);
PKG_XFAST.UP();
/* Дата по */
PKG_XFAST.DOWN_NODE(SNAME => 'DTO');
PKG_XFAST.VALUE(DVALUE => DTO_VALUE);
PKG_XFAST.UP();
end case; end case;
PKG_XFAST.UP(); PKG_XFAST.UP();
end if;
end loop; end loop;
PKG_XPATH.FREE(RDOCUMENT => RDOC); PKG_XPATH.FREE(RDOCUMENT => RDOC);
PKG_XFAST.UP(); PKG_XFAST.UP();