diff --git a/app/panels/clnt_task_board/clnt_task_board.js b/app/panels/clnt_task_board/clnt_task_board.js index 095cc2b..92f19c9 100644 --- a/app/panels/clnt_task_board/clnt_task_board.js +++ b/app/panels/clnt_task_board/clnt_task_board.js @@ -76,9 +76,6 @@ const ClntTaskBoard = () => { //Состояние доступных маршрутов события const [availableRoutes, setAvailableRoutes] = useState({ source: "", routes: [] }); - //Состояние перетаскиваемого события - const [dragItem, setDragItem] = useState({ type: "", status: "" }); - //При открытии/закрытии диалога фильтра const handleFilterOpen = isOpen => { setDialogsState(pv => ({ ...pv, filterDialogIsOpen: isOpen })); @@ -152,18 +149,6 @@ const ClntTaskBoard = () => { setAvailableRoutes({ source: "", routes: [] }); }; - //Обработка захвата перетаскиваемого объекта - const handleDragItemChange = (filtersType, statusCode) => - setDragItem({ - type: filtersType, - status: statusCode - }); - - //Обработка очистки перетаскиваемого объекта - const handleDragItemClear = () => { - setDragItem({ type: "", status: "" }); - }; - //Проверка доступности карточки события const isCardAvailable = code => { return availableRoutes.source === code || availableRoutes.routes.find(r => r.SDESTINATION === code) || !availableRoutes.source ? true : false; @@ -209,18 +194,17 @@ const ClntTaskBoard = () => { /> ) : null} {dialogsState.taskDialogIsOpen ? ( - handleTasksReload(true)} - onClose={() => { - handleTaskDialogOpen(); - handleDragItemClear(); - }} - /> + handleTasksReload(true)} onClose={handleTaskDialogOpen} /> ) : null} + + + + add + + + { statusTitle={status[statusesState.attr] || status.SEVNSTAT_NAME} colorRules={colorRules} extraData={extraData} - filtersType={filters.values.sType} isCardAvailable={isCardAvailable} onTasksReload={handleTasksReload} - onDragItemChange={handleDragItemChange} - onTaskDialogOpen={handleTaskDialogOpen} onNoteDialogOpen={handleNoteOpen} onStatusColorChange={handleSettingStatusColorChange} placeholder={provided.placeholder} diff --git a/app/panels/clnt_task_board/components/settings_dialog.js b/app/panels/clnt_task_board/components/settings_dialog.js index eb8420d..eecebe9 100644 --- a/app/panels/clnt_task_board/components/settings_dialog.js +++ b/app/panels/clnt_task_board/components/settings_dialog.js @@ -9,7 +9,7 @@ import React, { useState } from "react"; //Классы React 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 { sortAttrs, sortDest } from "../layouts.js"; //Допустимые значение поля и направления сортировки import { hasValue } from "../../../core/utils.js"; //Проверка наличия значения @@ -63,9 +63,23 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => { [...prev, { id: cur.id, caption: cur.SDP_NAME }], [])} - emptyItem={{ key: -1, id: -1, caption: "-" }} + labelText="Заливка событий*" + items={colorRules.rules.reduce( + (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} sx={STYLES.SELECT} /> @@ -75,7 +89,7 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => { [...prev, { id: cur.id, caption: cur.descr }], [])} onChange={handleSortAttrChange} sx={STYLES.SELECT} @@ -88,6 +102,10 @@ const SettingsDialog = ({ initial, onSettingsChange, onClose, ...other }) => { + + *Поддерживаются правила заливки, базирующиеся на дополнительных свойствах типа "Строка" или "Число", из + профиля пользователя, настроенного для раздела "События" в WEB-интерфейсе данного приложения. + - } sx={STYLES.CARD_HEADER} /> @@ -165,11 +152,8 @@ StatusCard.propTypes = { statusTitle: PropTypes.string.isRequired, colorRules: PropTypes.object.isRequired, extraData: PropTypes.object.isRequired, - filtersType: PropTypes.string.isRequired, isCardAvailable: PropTypes.func.isRequired, onTasksReload: PropTypes.func.isRequired, - onDragItemChange: PropTypes.func.isRequired, - onTaskDialogOpen: PropTypes.func.isRequired, onNoteDialogOpen: PropTypes.func.isRequired, onStatusColorChange: PropTypes.func.isRequired, placeholder: PropTypes.object.isRequired diff --git a/app/panels/clnt_task_board/hooks/task_dialog_hooks.js b/app/panels/clnt_task_board/hooks/task_dialog_hooks.js index 55b45a7..414c369 100644 --- a/app/panels/clnt_task_board/hooks/task_dialog_hooks.js +++ b/app/panels/clnt_task_board/hooks/task_dialog_hooks.js @@ -15,7 +15,7 @@ import { BackEndСtx } from "../../../context/backend"; //Контекст вз //----------- //Хук для события -const useClientEvent = (taskRn, taskType = "", taskStatus = "") => { +const useClientEvent = (taskRn, taskType = "") => { //Собственное состояние const [task, setTask] = useState({ init: true, @@ -24,7 +24,7 @@ const useClientEvent = (taskRn, taskType = "", taskStatus = "") => { sPrefix: "", sNumber: "", sType: taskType, - sStatus: taskStatus, + sStatus: "", sDescription: "", sClntClients: "", sClntClnperson: "", @@ -118,6 +118,7 @@ const useClientEvent = (taskRn, taskType = "", taskStatus = "") => { ...pv, sPrefix: data.SPREF, sNumber: data.SNUMB, + sStatus: data.SSTATUS, sCurrentUser: data.SINIT_AUTHNAME, sInitClnperson: data.SINIT_PERSON, sInitUser: !data.SINIT_PERSON ? data.SINIT_AUTHNAME : "", diff --git a/app/panels/clnt_task_board/layouts.js b/app/panels/clnt_task_board/layouts.js index a1c2cd2..674670f 100644 --- a/app/panels/clnt_task_board/layouts.js +++ b/app/panels/clnt_task_board/layouts.js @@ -12,8 +12,8 @@ export const EVENT_STATES = Object.freeze({ 0: "Все", 1: "Не аннулир //Допустимые значение поля сортировки export const sortAttrs = [ - { id: "SEVNSTAT_CODE", descr: "Мнемокод" }, - { id: "SEVNSTAT_NAME", descr: "Наименование" }, + { id: "SEVNSTAT_CODE", descr: "Мнемокод статуса" }, + { id: "SEVNSTAT_NAME", descr: "Наименование статуса" }, { id: "SEVPOINT_DESCR", descr: "Описание точки маршрута" } ]; @@ -73,24 +73,16 @@ const convertHexToRGB = hex => { //Считывание заливки события по условию export const getTaskBgColorByRule = (task, colorRule) => { - //Инициализируем значения - let ruleCode = ""; - //Исходя из типа определяем наименование + //Исходя из типа определяем наименование и возвращаем цвет заливки switch (colorRule.STYPE) { case "number": - ruleCode = `N${colorRule.SFIELD}`; - break; - case "date": - ruleCode = `D${colorRule.SFIELD}`; - break; + return (!colorRule.fromValue || Number(task.docProps[`N${colorRule.SFIELD}`]) >= Number(colorRule.fromValue)) && + (!colorRule.toValue || Number(task.docProps[`N${colorRule.SFIELD}`]) <= Number(colorRule.toValue)) + ? convertHexToRGB(colorRule.SCOLOR) + : null; default: - ruleCode = `S${colorRule.SFIELD}`; - break; + return task.docProps[`S${colorRule.SFIELD}`] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null; } - //Определяем цвет заливки - let bgColor = ruleCode && task.docProps[ruleCode] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null; - //Возвращаем цвет заливки - return bgColor; }; //Индикация истечения срока отработки события diff --git a/app/panels/clnt_task_board/task_dialog.js b/app/panels/clnt_task_board/task_dialog.js index 7591f9a..d616134 100644 --- a/app/panels/clnt_task_board/task_dialog.js +++ b/app/panels/clnt_task_board/task_dialog.js @@ -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); @@ -167,7 +167,6 @@ const TaskDialog = ({ taskRn, taskType, taskStatus, editable, onTasksReload, onC TaskDialog.propTypes = { taskRn: PropTypes.number, taskType: PropTypes.string.isRequired, - taskStatus: PropTypes.string, editable: PropTypes.bool, onTasksReload: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired diff --git a/db/PKG_P8PANELS_CLNTTSKBRD.pck b/db/PKG_P8PANELS_CLNTTSKBRD.pck index c1fd029..3af6ce6 100644 --- a/db/PKG_P8PANELS_CLNTTSKBRD.pck +++ b/db/PKG_P8PANELS_CLNTTSKBRD.pck @@ -36,6 +36,7 @@ create or replace package PKG_P8PANELS_CLNTTSKBRD as SEVENT_TYPE in varchar2, -- Мнемокод типа события SPREF out varchar2, -- Префикс события SNUMB out varchar2, -- Номер события + SSTATUS out varchar2, -- Начальный статус SINIT_PERSON out varchar2, -- Сотрудник - инициатор SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор ); @@ -1000,8 +1001,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as RDG_ROW => RDG_ROW, TDP_NAMES => TDP_NAMES, TDP_TYPES => TDP_TYPES, - NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES) - 1, - NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 2, + NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES), + NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 1, ICURSOR => ICURSOR, NACTION => 2); end if; @@ -1119,8 +1120,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as RDG_ROW => RDG_ROW, TDP_NAMES => TDP_NAMES, TDP_TYPES => TDP_TYPES, - NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES) - 1, - NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 2, + NFIRST_NUMB => RDG.RCOL_DEFS.COUNT - PKG_CONTVALLOC1S.COUNT_(RCONTAINER => TDP_NAMES), + NLAST_NUMB => RDG.RCOL_DEFS.COUNT - 1, ICURSOR => ICURSOR, NACTION => 1); end if; @@ -1457,11 +1458,13 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as SEVENT_TYPE in varchar2, -- Мнемокод типа события SPREF out varchar2, -- Префикс события SNUMB out varchar2, -- Номер события + SSTATUS out varchar2, -- Начальный статус SINIT_PERSON out varchar2, -- Сотрудник - инициатор SINIT_AUTHNAME out varchar2 -- Пользователь - инициатор ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + NEVENT_TYPE PKG_STD.TREF; -- Рег. номер типа события SOWNER_AGENT_RN PKG_STD.TSTRING; -- Рег. номер работодателя сотрудника STAB_PREF PKG_STD.TSTRING; -- Префикс табельного номера сотрудника STAB_NUMB PKG_STD.TSTRING; -- Таблеьный номер сотрудника @@ -1490,6 +1493,8 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as return SRESULT; end CLNEVNTYPES_PREF_GET; 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); /* Если префикс не указан в параметре и задан тип события */ @@ -1502,6 +1507,21 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as /* Считываем номер */ SNUMB := GET_CLNEVENTS_NEXTNUMB(NCOMPANY => NCOMPANY, SPREF => SPREF); 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, SOWNER_AGENT => SOWNER_AGENT_RN, @@ -2254,29 +2274,28 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as /* Считывание настройки раздела "События" для пользователя */ procedure CLNEVENTS_DP_RULES_GET ( - COUT out clob -- XML с настройкой раздела + COUT out clob -- XML с настройкой раздела ) is - SAUTHID PKG_STD.TSTRING := PKG_SESSION.GET_UTILIZER(); -- Пользователь - NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации - BXML blob; -- XML профиля пользователя для раздела "События" - RDOC PKG_XPATH.TDOCUMENT; -- Документ XML - RNODE_ROOT PKG_XPATH.TNODE; -- Корневой узел - RNODE_MAIN PKG_XPATH.TNODE; -- Основной узел - RNODE_GRIDFRAME PKG_XPATH.TNODE; -- Узел "gridFrame" - RNODE_DECOR_RULES PKG_XPATH.TNODE; -- Узел "decorationRules" - RNODE_RULE PKG_XPATH.TNODE; -- Узел "rule" - RNODE_RULE_LIST PKG_XPATH.TNODES; -- Список узлов "rule" - SFIELD PKG_STD.TSTRING; -- Код свойства документа (в формате "DP_<РЕГ_НОМЕР>") - SCOLOR PKG_STD.TSTRING; -- Код цвета - SDATA_TYPE PKG_STD.TSTRING; -- Тип данных - SDP_NAME PKG_STD.TSTRING; -- Наименование свойства документа - NFROM_VALUE PKG_STD.TNUMBER; -- Значение с (number) - NTO_VALUE PKG_STD.TNUMBER; -- Значение по (number) - SFROM_VALUE PKG_STD.TSTRING; -- Значение с (string) - STO_VALUE PKG_STD.TSTRING; -- Значение по (string) - DFROM_VALUE PKG_STD.TLDATE; -- Значение с (date) - DTO_VALUE PKG_STD.TLDATE; -- Значение по (date) + SAUTHID PKG_STD.TSTRING := PKG_SESSION.GET_UTILIZER(); -- Пользователь + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации + SAPPCODE PKG_STD.TSTRING := PKG_SESSION.GET_APPLICATION(); -- Код приложения сеанса + BXML blob; -- XML профиля пользователя для раздела "События" + RDOC PKG_XPATH.TDOCUMENT; -- Документ XML + RNODE_ROOT PKG_XPATH.TNODE; -- Корневой узел + RNODE_MAIN PKG_XPATH.TNODE; -- Основной узел + RNODE_GRIDFRAME PKG_XPATH.TNODE; -- Узел "gridFrame" + RNODE_DECOR_RULES PKG_XPATH.TNODE; -- Узел "decorationRules" + RNODE_RULE PKG_XPATH.TNODE; -- Узел "rule" + RNODE_RULE_LIST PKG_XPATH.TNODES; -- Список узлов "rule" + SFIELD PKG_STD.TSTRING; -- Код свойства документа (в формате "DP_<РЕГ_НОМЕР>") + SCOLOR PKG_STD.TSTRING; -- Код цвета + SDATA_TYPE PKG_STD.TSTRING; -- Тип данных + SDP_NAME PKG_STD.TSTRING; -- Наименование свойства документа + NFROM_VALUE PKG_STD.TNUMBER; -- Значение с (number) + NTO_VALUE PKG_STD.TNUMBER; -- Значение по (number) + SFROM_VALUE PKG_STD.TSTRING; -- Значение с (string) + STO_VALUE PKG_STD.TSTRING; -- Значение по (string) /* Считывание наименования свойства документа */ function DOCS_PROPS_NAME_GET @@ -2287,19 +2306,22 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as NRN PKG_STD.TREF; -- Рег. номер свойства документа SRESULT PKG_STD.TSTRING; -- Наименование доп. свойства begin - /* Определяем рег. номер свойства документа по формату "DP_<РЕГ_НОМЕР>" */ - NRN := TO_NUMBER(SUBSTR(SFIELD, INSTR(SFIELD, '_') + 1)); - /* Считываем наименование из записи свойства документа */ - begin - select T.NAME into SRESULT from DOCS_PROPS T where T.RN = NRN; - exception - when NO_DATA_FOUND then - P_EXCEPTION(0, - 'Ошибка считывания записи свойства документа с рег. номером (%s).'); - when others then - P_EXCEPTION(0, - 'Ошибка считывания наименования свойства документа с рег. номером (%s).'); - end; + /* Если переданный код свойства соответствует формату */ + if (INSTR(SFIELD, 'DP_') <> 0) then + /* Определяем рег. номер свойства документа по формату "DP_<РЕГ_НОМЕР>" */ + NRN := TO_NUMBER(SUBSTR(SFIELD, INSTR(SFIELD, '_') + 1)); + /* Считываем наименование из записи свойства документа */ + begin + select T.NAME into SRESULT from DOCS_PROPS T where T.RN = NRN; + exception + when NO_DATA_FOUND then + P_EXCEPTION(0, + 'Ошибка считывания записи свойства документа с рег. номером (%s).'); + when others then + P_EXCEPTION(0, + 'Ошибка считывания наименования свойства документа с рег. номером (%s).'); + end; + end if; /* Возвращаем результат */ return SRESULT; end DOCS_PROPS_NAME_GET; @@ -2307,11 +2329,12 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as /* Считывание профиля пользователя для раздела "События" */ function USERPROFILES_GET ( - NCOMPANY in number, -- Рег. номер организации - SAUTHID in varchar2 -- Мнемокод пользователя - ) return blob -- Профиль пользователя для раздела "События" + NCOMPANY in number, -- Рег. номер организации + SAPPCODE in varchar2, -- Код приложения + SAUTHID in varchar2 -- Мнемокод пользователя + ) return blob -- Профиль пользователя для раздела "События" is - BRESULT blob; -- Профиль пользователя для раздела "События" + BRESULT blob; -- Профиль пользователя для раздела "События" begin /* Считываем профиль пользователя для раздела "События" */ begin @@ -2322,7 +2345,12 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as and U.AUTHID = SAUTHID and U.REC_TYPE = 1 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 when others then return null; @@ -2332,7 +2360,7 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as end USERPROFILES_GET; begin /* Считываем профиль пользователя для раздела "События" */ - BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAUTHID => SAUTHID); + BXML := USERPROFILES_GET(NCOMPANY => NCOMPANY, SAPPCODE => SAPPCODE, SAUTHID => SAUTHID); /* Проверим, что профиль не пустой */ if (BXML is null) then return; @@ -2359,71 +2387,60 @@ create or replace package body PKG_P8PANELS_CLNTTSKBRD as SFIELD := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'field'); SCOLOR := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'color'); SDATA_TYPE := PKG_XPATH.ATTRIBUTE(RNODE => RNODE_RULE, SNAME => 'dataType'); - PKG_XFAST.DOWN_NODE(SNAME => 'XRULES'); - /* Код правила */ - PKG_XFAST.DOWN_NODE(SNAME => 'SFIELD'); - PKG_XFAST.VALUE(SVALUE => SFIELD); - PKG_XFAST.UP(); /* Считываем наименование свойства документа */ SDP_NAME := DOCS_PROPS_NAME_GET(SFIELD => SFIELD); - /* Наименование доп. свойства */ - PKG_XFAST.DOWN_NODE(SNAME => 'SDP_NAME'); - PKG_XFAST.VALUE(SVALUE => SDP_NAME); - PKG_XFAST.UP(); - /* Код цвета */ - PKG_XFAST.DOWN_NODE(SNAME => 'SCOLOR'); - PKG_XFAST.VALUE(SVALUE => SCOLOR); - PKG_XFAST.UP(); - /* Тип значения */ - PKG_XFAST.DOWN_NODE(SNAME => 'STYPE'); - PKG_XFAST.VALUE(SVALUE => SDATA_TYPE); - PKG_XFAST.UP(); - /* Исходим от типа данных */ - case SDATA_TYPE - /* Число */ - when 'number' then - NFROM_VALUE := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, - SPATTERN => 'fromValue')); - NTO_VALUE := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, - SPATTERN => 'toValue')); - /* Число с */ - PKG_XFAST.DOWN_NODE(SNAME => 'NFROM'); - PKG_XFAST.VALUE(NVALUE => NFROM_VALUE); - PKG_XFAST.UP(); - /* Число по */ - PKG_XFAST.DOWN_NODE(SNAME => 'NTO'); - PKG_XFAST.VALUE(NVALUE => NTO_VALUE); - PKG_XFAST.UP(); - /* Строка */ - when 'string' then - SFROM_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, - SPATTERN => 'fromValue')); - STO_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, - SPATTERN => 'toValue')); - /* Строка с */ - PKG_XFAST.DOWN_NODE(SNAME => 'SFROM'); - PKG_XFAST.VALUE(SVALUE => SFROM_VALUE); - PKG_XFAST.UP(); - /* Строка по */ - PKG_XFAST.DOWN_NODE(SNAME => 'STO'); - PKG_XFAST.VALUE(SVALUE => STO_VALUE); - 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; - PKG_XFAST.UP(); + /* Если это правило по доп. свойству и типа "строка" или "число" */ + if (SDP_NAME is not null) and (SDATA_TYPE in ('number', 'string')) then + PKG_XFAST.DOWN_NODE(SNAME => 'XRULES'); + /* Код правила */ + PKG_XFAST.DOWN_NODE(SNAME => 'SFIELD'); + PKG_XFAST.VALUE(SVALUE => SFIELD); + PKG_XFAST.UP(); + /* Наименование доп. свойства */ + PKG_XFAST.DOWN_NODE(SNAME => 'SDP_NAME'); + PKG_XFAST.VALUE(SVALUE => SDP_NAME); + PKG_XFAST.UP(); + /* Код цвета */ + PKG_XFAST.DOWN_NODE(SNAME => 'SCOLOR'); + PKG_XFAST.VALUE(SVALUE => SCOLOR); + PKG_XFAST.UP(); + /* Тип значения */ + PKG_XFAST.DOWN_NODE(SNAME => 'STYPE'); + PKG_XFAST.VALUE(SVALUE => SDATA_TYPE); + PKG_XFAST.UP(); + /* Исходим от типа данных */ + case SDATA_TYPE + /* Число */ + when 'number' then + NFROM_VALUE := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, + SPATTERN => 'fromValue')); + NTO_VALUE := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, + SPATTERN => 'toValue')); + /* Число с */ + PKG_XFAST.DOWN_NODE(SNAME => 'NFROM'); + PKG_XFAST.VALUE(NVALUE => NFROM_VALUE); + PKG_XFAST.UP(); + /* Число по */ + PKG_XFAST.DOWN_NODE(SNAME => 'NTO'); + PKG_XFAST.VALUE(NVALUE => NTO_VALUE); + PKG_XFAST.UP(); + /* Строка */ + when 'string' then + SFROM_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, + SPATTERN => 'value')); + STO_VALUE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RNODE_RULE, + SPATTERN => 'value')); + /* Строка с */ + PKG_XFAST.DOWN_NODE(SNAME => 'SFROM'); + PKG_XFAST.VALUE(SVALUE => SFROM_VALUE); + PKG_XFAST.UP(); + /* Строка по */ + PKG_XFAST.DOWN_NODE(SNAME => 'STO'); + PKG_XFAST.VALUE(SVALUE => STO_VALUE); + PKG_XFAST.UP(); + end case; + PKG_XFAST.UP(); + end if; end loop; PKG_XPATH.FREE(RDOCUMENT => RDOC); PKG_XFAST.UP();