/* Парус 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 };