432 lines
20 KiB
JavaScript
432 lines
20 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга - УДП - Доски задач
|
||
Пользовательские хуки: Хуки событий
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import { useState, useContext, useEffect, useCallback } from "react"; //Классы React
|
||
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
|
||
import { object2Base64XML } from "../../../core/utils"; //Вспомогательные функции
|
||
import { convertFilterValuesToArray } from "../layouts"; //Вспомогательные функции
|
||
import { useDictionary } from "./dict_hooks"; //Состояние открытия разделов
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Хук обработки перехода события
|
||
const useTasksFunctions = () => {
|
||
//Состояние открытия раздела
|
||
const { handleEventRoutesPointExecutersOpen, handleEventRoutesPointsPassessOpen } = useDictionary();
|
||
|
||
//Подключение к контексту взаимодействия с сервером
|
||
const { executeStored } = useContext(BackEndСtx);
|
||
|
||
//Выполнение направления события
|
||
const handleSendExec = useCallback(
|
||
//Выполняем финальное перенаправление события
|
||
async ({ mainArgs, onReload = null }) => {
|
||
await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SEND",
|
||
args: { ...mainArgs }
|
||
});
|
||
//Если требуется перезагрузить данные
|
||
onReload ? onReload() : null;
|
||
},
|
||
[executeStored]
|
||
);
|
||
|
||
//При направлении события
|
||
const handleSend = useCallback(
|
||
async ({ mainArgs, onReload = null, onNoteOpen = null }) => {
|
||
//Если требуется добавить примечание
|
||
if (onNoteOpen) {
|
||
//Открываем примечание с коллбэком на направление события
|
||
onNoteOpen(async note => {
|
||
//Выполняем изменение статуса
|
||
handleSendExec({ mainArgs: { ...mainArgs, SNOTE_HEADER: note.header, SNOTE: note.text }, onReload });
|
||
});
|
||
} else {
|
||
//Выполняем изменение статуса
|
||
handleSendExec({ mainArgs, onReload });
|
||
}
|
||
},
|
||
[handleSendExec]
|
||
);
|
||
|
||
//По нажатию действия "Направить"
|
||
const handleTaskSend = useCallback(
|
||
async ({ nEvent, onReload = null, onNoteOpen = null }) => {
|
||
//Выполняем инициализацию параметров
|
||
const firstStep = await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SEND",
|
||
args: {
|
||
NSTEP: 1,
|
||
NEVENT: nEvent
|
||
}
|
||
});
|
||
if (firstStep) {
|
||
//Открываем раздел "Маршруты событий (исполнители в точках)" для выбора исполнителя
|
||
handleEventRoutesPointExecutersOpen({
|
||
inputParameters: [
|
||
{ name: "in_IDENT", value: firstStep.NIDENT },
|
||
{ name: "in_EVENT", value: nEvent },
|
||
{ name: "in_PERSON_CODE", value: firstStep.SSEND_PERSON },
|
||
{ name: "in_USER_NAME", value: firstStep.SSEND_USER_NAME },
|
||
{ name: "in_EVENT_TYPE", value: firstStep.SEVENT_TYPE },
|
||
{ name: "in_EVENT_STAT", value: firstStep.SEVENT_STAT },
|
||
{ name: "in_INIT_PERSON", value: firstStep.SINIT_PERSON },
|
||
{ name: "in_INIT_AUTHNAME", value: firstStep.SINIT_AUTHNAME },
|
||
{ name: "in_CLIENT_CLIENT", value: firstStep.SCLIENT_CLIENT },
|
||
{ name: "in_CLIENT_PERSON", value: firstStep.SCLIENT_PERSON }
|
||
],
|
||
callBack: sendPrms => {
|
||
//Собираем основные параметры направления события
|
||
const mainArgs = {
|
||
NIDENT: firstStep.NIDENT,
|
||
NSTEP: 2,
|
||
NEVENT: nEvent,
|
||
SSEND_CLIENT: sendPrms.outParameters.out_CLIENT_CODE,
|
||
SSEND_DIVISION: sendPrms.outParameters.out_DIVISION_CODE,
|
||
SSEND_POST: sendPrms.outParameters.out_POST_CODE,
|
||
SSEND_PERFORM: sendPrms.outParameters.out_POST_IN_DIV_CODE,
|
||
SSEND_PERSON: sendPrms.outParameters.out_PERSON_CODE,
|
||
SSEND_STAFFGRP: sendPrms.outParameters.out_STAFFGRP_CODE,
|
||
SSEND_USER_GROUP: sendPrms.outParameters.out_USER_GROUP_CODE,
|
||
SSEND_USER_NAME: sendPrms.outParameters.out_USER_NAME,
|
||
NSEND_PREDEFINED_EXEC: sendPrms.outParameters.out_PREDEFINED_EXEC,
|
||
NSEND_PREDEFINED_PROC: sendPrms.outParameters.out_PREDEFINED_PROC
|
||
};
|
||
//Перенаправляем событие
|
||
handleSend({ nEvent, mainArgs, onReload, onNoteOpen });
|
||
}
|
||
});
|
||
}
|
||
},
|
||
[executeStored, handleEventRoutesPointExecutersOpen, handleSend]
|
||
);
|
||
|
||
//Выполнение изменения статуса события
|
||
const handleStateChangeExec = useCallback(
|
||
async ({ mainArgs, onReload = null }) => {
|
||
await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
|
||
args: { ...mainArgs }
|
||
});
|
||
//Если требуется перезагрузить данные
|
||
onReload ? onReload() : null;
|
||
},
|
||
[executeStored]
|
||
);
|
||
|
||
//При изменении статуса события
|
||
const handleStateChange = useCallback(
|
||
async ({ mainArgs, onReload = null, onNoteOpen = null }) => {
|
||
//Если необходимо добавить примечание
|
||
if (onNoteOpen) {
|
||
//Открываем примечание с коллбэком на изменение статуса
|
||
onNoteOpen(async note => {
|
||
//Выполняем изменение статуса
|
||
handleStateChangeExec({ mainArgs: { ...mainArgs, SNOTE_HEADER: note.header, SNOTE: note.text }, onReload });
|
||
});
|
||
} else {
|
||
//Выполняем изменение статуса
|
||
handleStateChangeExec({ mainArgs, onReload });
|
||
}
|
||
},
|
||
[handleStateChangeExec]
|
||
);
|
||
|
||
//При выборе исполнителя
|
||
const handleExecuterSelect = useCallback(
|
||
async ({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => {
|
||
//Если требуется выбрать получателя
|
||
if (pointInfo.NSELECT_EXEC === 1) {
|
||
//Открываем раздел "Маршруты событий (исполнители в точках)" для выбора исполнителя
|
||
handleEventRoutesPointExecutersOpen({
|
||
inputParameters: [
|
||
{ name: "in_IDENT", value: pointInfo.NIDENT },
|
||
{ name: "in_EVENT", value: nEvent },
|
||
{ name: "in_EVENT_TYPE", value: pointInfo.SEVENT_TYPE },
|
||
{ name: "in_EVENT_STAT", value: pointInfo.SEVENT_STAT },
|
||
{ name: "in_INIT_PERSON", value: pointInfo.SINIT_PERSON },
|
||
{ name: "in_INIT_AUTHNAME", value: pointInfo.SINIT_AUTHNAME },
|
||
{ name: "in_CLIENT_CLIENT", value: pointInfo.SCLIENT_CLIENT },
|
||
{ name: "in_CLIENT_PERSON", value: pointInfo.SCLIENT_PERSON }
|
||
],
|
||
callBack: sendPrms => {
|
||
const mainArgs = {
|
||
NIDENT: pointInfo.NIDENT,
|
||
NSTEP: 3,
|
||
NEVENT: nEvent,
|
||
SEVENT_STAT: pointInfo.SEVENT_STAT,
|
||
SSEND_CLIENT: sendPrms.outParameters.out_CLIENT_CODE,
|
||
SSEND_DIVISION: sendPrms.outParameters.out_DIVISION_CODE,
|
||
SSEND_POST: sendPrms.outParameters.out_POST_CODE,
|
||
SSEND_PERFORM: sendPrms.outParameters.out_POST_IN_DIV_CODE,
|
||
SSEND_PERSON: sendPrms.outParameters.out_PERSON_CODE,
|
||
SSEND_STAFFGRP: sendPrms.outParameters.out_STAFFGRP_CODE,
|
||
SSEND_USER_GROUP: sendPrms.outParameters.out_USER_GROUP_CODE,
|
||
SSEND_USER_NAME: sendPrms.outParameters.out_USER_NAME,
|
||
NSEND_PREDEFINED_EXEC: sendPrms.outParameters.out_PREDEFINED_EXEC,
|
||
NSEND_PREDEFINED_PROC: sendPrms.outParameters.out_PREDEFINED_PROC
|
||
};
|
||
//Выполняем изменение статуса
|
||
handleStateChange({ mainArgs, onReload, onNoteOpen });
|
||
}
|
||
});
|
||
} else {
|
||
//Общие аргументы
|
||
const mainArgs = {
|
||
NIDENT: pointInfo.NIDENT,
|
||
NSTEP: 3,
|
||
NEVENT: nEvent,
|
||
SEVENT_STAT: pointInfo.SEVENT_STAT
|
||
};
|
||
//Выполняем изменение статуса
|
||
handleStateChange({ mainArgs, onReload, onNoteOpen });
|
||
}
|
||
},
|
||
[handleEventRoutesPointExecutersOpen, handleStateChange]
|
||
);
|
||
|
||
//При выполнении второго шага
|
||
const handleMakeSecondStep = useCallback(
|
||
async ({ nIdent, nPass }) => {
|
||
//Выполняем переход на следующий шаг
|
||
const secondStep = await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
|
||
args: {
|
||
NIDENT: nIdent,
|
||
NSTEP: 2,
|
||
NPASS: nPass
|
||
}
|
||
});
|
||
//Возвращаем параметры выполнения
|
||
return secondStep;
|
||
},
|
||
[executeStored]
|
||
);
|
||
|
||
//При выборе следующей точки события
|
||
const handleNextPointSelect = useCallback(
|
||
({ nEvent, pointInfo, onReload = null, onNoteOpen = null }) => {
|
||
//Открываем раздел "Маршруты событий (точки перехода)" для выбора следующей точки
|
||
handleEventRoutesPointsPassessOpen({
|
||
sEventType: pointInfo.SEVENT_TYPE,
|
||
sEventStatus: pointInfo.SEVENT_STAT,
|
||
nPoint: pointInfo.NPOINT,
|
||
callBack: async point => {
|
||
//Выполняем второй шаг
|
||
let secondStep = await handleMakeSecondStep({ nIdent: pointInfo.NIDENT, nPass: point.outParameters.out_RN });
|
||
//Выполняем выбор исполнителя
|
||
handleExecuterSelect({
|
||
nEvent,
|
||
pointInfo: { ...pointInfo, SEVENT_STAT: point.outParameters.out_NEXT_POINT, NSELECT_EXEC: secondStep.NSELECT_EXEC },
|
||
onReload,
|
||
onNoteOpen
|
||
});
|
||
}
|
||
});
|
||
},
|
||
[handleEventRoutesPointsPassessOpen, handleMakeSecondStep, handleExecuterSelect]
|
||
);
|
||
|
||
//По нажатию действия "Перейти"
|
||
const handleTaskStateChange = useCallback(
|
||
async ({ nEvent, sNextStat = null, onReload = null, onNoteOpen = null }) => {
|
||
//Выполняем инициализацию параметров
|
||
const eventInfo = await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
|
||
args: {
|
||
NSTEP: 1,
|
||
NEVENT: nEvent,
|
||
SNEXT_STAT: sNextStat
|
||
}
|
||
});
|
||
//Если информация о события проинициализирована
|
||
if (eventInfo) {
|
||
//Если следующий статус неопределен
|
||
if (!sNextStat) {
|
||
//Выполнение перехода с выбором точки
|
||
handleNextPointSelect({
|
||
nEvent,
|
||
pointInfo: eventInfo,
|
||
onReload,
|
||
onNoteOpen
|
||
});
|
||
} else {
|
||
//Выполняем перехода без выбора точки
|
||
handleExecuterSelect({
|
||
nEvent,
|
||
pointInfo: eventInfo,
|
||
onReload,
|
||
onNoteOpen
|
||
});
|
||
}
|
||
}
|
||
},
|
||
[executeStored, handleExecuterSelect, handleNextPointSelect]
|
||
);
|
||
|
||
return { handleTaskStateChange, handleTaskSend };
|
||
};
|
||
|
||
//Хук получения событий
|
||
const useTasks = (filterValues, ordersValues) => {
|
||
//Состояние событий
|
||
const [tasks, setTasks] = useState({
|
||
loaded: false,
|
||
rows: [],
|
||
reload: false,
|
||
accountsReload: false,
|
||
loadedAccounts: []
|
||
});
|
||
|
||
//Состояние вспомогательных функций событий
|
||
const { handleTaskStateChange } = useTasksFunctions();
|
||
|
||
//Подключение к контексту взаимодействия с сервером
|
||
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||
|
||
//Инициализация параметров события
|
||
const initTask = (id, task, avatar = null) => {
|
||
//Фильтруем доп. свойства
|
||
let newDocProps = Object.keys(task)
|
||
.filter(key => key.includes("DP_"))
|
||
.reduce((prev, key) => ({ ...prev, [key]: task[key] }), {});
|
||
//Возвращаем структуру события
|
||
return {
|
||
id: id,
|
||
avatar: avatar,
|
||
name: task.SPREF_NUMB,
|
||
nRn: task.NRN,
|
||
sCrn: "",
|
||
sPrefix: task.SEVPREF,
|
||
sNumber: task.SEVNUMB,
|
||
sType: task.SEVTYPE_CODE,
|
||
sStatus: task.SEVSTAT_NAME,
|
||
sDescription: task.SEVDESCR,
|
||
sClntClients: "",
|
||
sClntClnperson: "",
|
||
dchange_date: task.DCHANGE_DATE,
|
||
dStartDate: task.DREG_DATE,
|
||
dExpireDate: task.DEXPIRE_DATE,
|
||
dPlanDate: task.DPLAN_DATE,
|
||
sInitClnperson: task.SINIT_PERSON,
|
||
sInitUser: "",
|
||
sInitReason: "",
|
||
sToCompany: "",
|
||
sToDepartment: task.SSEND_DIVISION,
|
||
sToClnpost: "",
|
||
sToClnpsdep: "",
|
||
sToClnperson: task.SSEND_PERSON,
|
||
sToFcstaffgrp: "",
|
||
sToUser: "",
|
||
sToUsergrp: task.SSEND_USRGRP,
|
||
sSender: task.SSENDER,
|
||
sCurrentUser: "",
|
||
sLinkedUnit: task.SLINKED_UNIT,
|
||
nLinkedRn: task.NLINKED_RN,
|
||
docProps: newDocProps
|
||
};
|
||
};
|
||
|
||
//Взаимодействие с событием (через перенос)
|
||
const onDragEnd = useCallback(
|
||
({ path, eventPoints, openNoteDialog, destCode }) => {
|
||
//Определяем нужные параметры
|
||
const { source, destination } = path;
|
||
//Если путь не указан
|
||
if (!destination) {
|
||
return;
|
||
}
|
||
//Если происходит изменение статуса
|
||
if (destination.droppableId !== source.droppableId) {
|
||
//Конвертим ID переносимого события
|
||
let nDraggableTaskId = parseInt(path.draggableId);
|
||
//Считываем строку, у которой изменяется статус
|
||
let task = tasks.rows.find(r => r.id === nDraggableTaskId);
|
||
//Изменяем статус у события
|
||
task.statusId = parseInt(path.destination.droppableId);
|
||
//Получение настройки точки назначения
|
||
const pointSettings = eventPoints.find(eventPoint => eventPoint.SEVPOINT === destCode);
|
||
//Изменяем статус события с добавлением примечания
|
||
handleTaskStateChange({
|
||
nEvent: task.nRn,
|
||
sNextStat: destCode,
|
||
onReload: () => setTasks(pv => ({ ...pv, reload: true, accountsReload: true })),
|
||
onNoteOpen: pointSettings.ADDNOTE_ONCHST ? openNoteDialog : null
|
||
});
|
||
}
|
||
},
|
||
[handleTaskStateChange, tasks.rows]
|
||
);
|
||
|
||
//При необходимости перезагрузки данных
|
||
useEffect(() => {
|
||
//Считывание данных с учетом фильтрации
|
||
let getTasks = async () => {
|
||
const data = await executeStored({
|
||
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_LOAD",
|
||
args: {
|
||
CFILTERS: {
|
||
VALUE: object2Base64XML(convertFilterValuesToArray(filterValues), { arrayNodeName: "filters" }),
|
||
SDATA_TYPE: SERV_DATA_TYPE_CLOB
|
||
},
|
||
CORDERS: { VALUE: object2Base64XML(ordersValues, { arrayNodeName: "orders" }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
|
||
NINCLUDE_ACCOUNTS: tasks.accountsReload ? 1 : 0
|
||
},
|
||
isArray: name => name === "XAGENTS",
|
||
respArg: "COUT"
|
||
});
|
||
//Считываем информацию о событиях
|
||
let events = data.XCLNEVENTS.XDATA.XDATA_GRID;
|
||
//Считываем иноформацию о контрагентах
|
||
let accounts = tasks.accountsReload ? [...(data.XAGENTS_WITH_IMG.XAGENTS || [])] : tasks.loadedAccounts;
|
||
//Инициализируем события
|
||
let newRows = [];
|
||
//Если есть события
|
||
if (events.rows) {
|
||
//Формируем структуру событий
|
||
newRows = [...(events.rows || [])].reduce(
|
||
(prev, cur) => [...prev, initTask(prev.length, cur, accounts.find(agent => agent.SAGNABBR === cur.SSENDER)?.BIMAGE)],
|
||
[]
|
||
);
|
||
}
|
||
//Возвращаем информацию
|
||
return { rows: [...newRows], loadedAccounts: accounts };
|
||
};
|
||
//Считывание данных
|
||
let getData = async () => {
|
||
//Считываем информацию о задачах
|
||
let eventTasks = await getTasks();
|
||
//Загружаем данные
|
||
setTasks(pv => ({
|
||
...pv,
|
||
loaded: true,
|
||
rows: eventTasks.rows,
|
||
loadedAccounts: eventTasks.loadedAccounts,
|
||
reload: false,
|
||
accountsReload: false
|
||
}));
|
||
};
|
||
//Если необходимо загрузить данные и указан тип событий и загружены все необходимые вспомогательные данные
|
||
if (tasks.reload) {
|
||
//Загружаем данные
|
||
getData();
|
||
}
|
||
}, [SERV_DATA_TYPE_CLOB, executeStored, filterValues, ordersValues, tasks.accountsReload, tasks.loadedAccounts, tasks.reload]);
|
||
|
||
return [tasks, setTasks, onDragEnd];
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export { useTasksFunctions, useTasks };
|