forked from CITKParus/P8-Panels
ЦИТК-945 - Добавлена панель "Выдача сменного задания на участок"
This commit is contained in:
commit
d06f3a2db1
279
app/panels/mech_rec_cost_jobs_manage_mp/hooks.js
Normal file
279
app/panels/mech_rec_cost_jobs_manage_mp/hooks.js
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания на участок
|
||||||
|
Кастомные хуки
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import { useState, useCallback, useEffect, useContext } from "react"; //Классы React
|
||||||
|
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||||
|
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
|
||||||
|
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Размер страницы данных
|
||||||
|
const DATA_GRID_PAGE_SIZE = 50;
|
||||||
|
|
||||||
|
//---------------------------------------------
|
||||||
|
//Вспомогательные функции форматирования данных
|
||||||
|
//---------------------------------------------
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Хук для основной таблицы
|
||||||
|
const useCostJobs = () => {
|
||||||
|
//Собственное состояние - таблица данных
|
||||||
|
const [state, setState] = useState({
|
||||||
|
init: false,
|
||||||
|
loaded: false,
|
||||||
|
jobInfo: {},
|
||||||
|
haveNote: false,
|
||||||
|
coeff: "1.0"
|
||||||
|
});
|
||||||
|
|
||||||
|
//Подключение к контексту взаимодействия с сервером
|
||||||
|
const { executeStored } = useContext(BackEndСtx);
|
||||||
|
//Подключение к контексту навигации
|
||||||
|
const { getNavigationSearch } = useContext(NavigationCtx);
|
||||||
|
|
||||||
|
//При подключении компонента к странице
|
||||||
|
useEffect(() => {
|
||||||
|
const initJob = async fcJob => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.FCJOBS_MP_INIT",
|
||||||
|
args: { NFCJOBS: parseInt(fcJob) },
|
||||||
|
respArg: "COUT",
|
||||||
|
attributeValueProcessor: (name, val) => (["NHAVE_NOTE"].includes(name) ? val == 1 : val)
|
||||||
|
});
|
||||||
|
setState(pv => ({
|
||||||
|
...pv,
|
||||||
|
init: true,
|
||||||
|
jobInfo: data.XFCJOBS ? data.XFCJOBS : {},
|
||||||
|
loaded: true
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
if (!state.init) {
|
||||||
|
//Считаем параметры, переданные из действия
|
||||||
|
const actionPrms = getNavigationSearch();
|
||||||
|
//Иницализируем сменное задание
|
||||||
|
initJob(actionPrms.NRN);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return [state, setState];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Хук для таблицы операций
|
||||||
|
const useCostJobsSpecs = task => {
|
||||||
|
//Собственное состояние - таблица данных
|
||||||
|
const [costJobsSpecs, setCostJobsSpecs] = useState({
|
||||||
|
task: null,
|
||||||
|
dataLoaded: false,
|
||||||
|
columnsDef: [],
|
||||||
|
orders: null,
|
||||||
|
rows: [],
|
||||||
|
selectedRow: {},
|
||||||
|
reload: true,
|
||||||
|
pageNumber: 1,
|
||||||
|
morePages: true
|
||||||
|
});
|
||||||
|
|
||||||
|
//Подключение к контексту взаимодействия с сервером
|
||||||
|
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||||||
|
|
||||||
|
//Выдача задания
|
||||||
|
const issueCostJobsSpecs = useCallback(
|
||||||
|
async prms => {
|
||||||
|
try {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.FCJOBSSP_MP_ISSUE",
|
||||||
|
args: { NFCJOBS: prms.NFCJOBS, NCOEFF: parseFloat(prms.NCOEFF) }
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[executeStored]
|
||||||
|
);
|
||||||
|
|
||||||
|
//При необходимости обновить данные таблицы
|
||||||
|
useEffect(() => {
|
||||||
|
//Если изменилось сменное задание - обновляем состояние
|
||||||
|
if (costJobsSpecs.dataLoaded && costJobsSpecs.task !== task) {
|
||||||
|
setCostJobsSpecs(pv => ({
|
||||||
|
...pv,
|
||||||
|
dataLoaded: false,
|
||||||
|
columnsDef: [],
|
||||||
|
orders: null,
|
||||||
|
rows: [],
|
||||||
|
selectedRow: {},
|
||||||
|
reload: true,
|
||||||
|
pageNumber: 1,
|
||||||
|
morePages: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
//Если необходимо перезагрузить
|
||||||
|
if (costJobsSpecs.reload && task) {
|
||||||
|
const loadData = async () => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.FCJOBSSP_MP_DG_GET",
|
||||||
|
args: {
|
||||||
|
NFCJOBS: task,
|
||||||
|
NPAGE_NUMBER: costJobsSpecs.pageNumber,
|
||||||
|
NPAGE_SIZE: DATA_GRID_PAGE_SIZE,
|
||||||
|
CORDERS: { VALUE: object2Base64XML(costJobsSpecs.orders, { arrayNodeName: "orders" }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
|
||||||
|
NINCLUDE_DEF: costJobsSpecs.dataLoaded ? 0 : 1
|
||||||
|
},
|
||||||
|
respArg: "COUT",
|
||||||
|
attributeValueProcessor: (name, val) =>
|
||||||
|
name === "NSELECT" ? val === 1 : name === "SWORKERS_LIST" ? (val ? val.split(",").map(Number) : []) : val
|
||||||
|
});
|
||||||
|
setCostJobsSpecs(pv => ({
|
||||||
|
...pv,
|
||||||
|
...data.XDATA_GRID,
|
||||||
|
task: task,
|
||||||
|
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef,
|
||||||
|
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...pv.rows, ...(data.XDATA_GRID.rows || [])],
|
||||||
|
dataLoaded: true,
|
||||||
|
reload: false,
|
||||||
|
morePages: (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
SERV_DATA_TYPE_CLOB,
|
||||||
|
costJobsSpecs.dataLoaded,
|
||||||
|
costJobsSpecs.orders,
|
||||||
|
costJobsSpecs.pageNumber,
|
||||||
|
costJobsSpecs.reload,
|
||||||
|
costJobsSpecs.task,
|
||||||
|
executeStored,
|
||||||
|
task
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [costJobsSpecs, setCostJobsSpecs, issueCostJobsSpecs];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Хук для рабочих
|
||||||
|
const useCostJobsWorkers = task => {
|
||||||
|
//Собственное состояние - таблица данных
|
||||||
|
const [costJobsWorkers, setCostJobsWorkers] = useState({
|
||||||
|
task: null,
|
||||||
|
dataLoaded: false,
|
||||||
|
columnsDef: [],
|
||||||
|
orders: null,
|
||||||
|
rows: [],
|
||||||
|
selectedRows: [],
|
||||||
|
reload: true,
|
||||||
|
pageNumber: 1,
|
||||||
|
morePages: true
|
||||||
|
});
|
||||||
|
|
||||||
|
//Подключение к контексту взаимодействия с сервером
|
||||||
|
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||||||
|
|
||||||
|
//Включение рабочего в строку сменного задания
|
||||||
|
const includeWorker = useCallback(
|
||||||
|
async prms => {
|
||||||
|
try {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.FCJOBSSP_MP_INC_PERFORM",
|
||||||
|
args: {
|
||||||
|
NFCJOBSSP: prms.NFCJOBSSP,
|
||||||
|
SPERFORM_LIST: {
|
||||||
|
VALUE: Array.isArray(prms.SELECTED_WORKERS) ? prms.SELECTED_WORKERS.join(";") : prms.SELECTED_WORKERS,
|
||||||
|
SDATA_TYPE: SERV_DATA_TYPE_CLOB
|
||||||
|
},
|
||||||
|
NQUANT_PLAN: prms.NQUANT_PLAN
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[SERV_DATA_TYPE_CLOB, executeStored]
|
||||||
|
);
|
||||||
|
|
||||||
|
//Исключение рабочего из строки сменного задания
|
||||||
|
const excludeWorker = useCallback(
|
||||||
|
async prms => {
|
||||||
|
try {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.FCJOBSSP_MP_EXC_PERFORM",
|
||||||
|
args: { NFCJOBSSP: prms.NFCJOBSSP }
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[executeStored]
|
||||||
|
);
|
||||||
|
|
||||||
|
//При необходимости обновить данные таблицы
|
||||||
|
useEffect(() => {
|
||||||
|
//Если изменилось сменное задание - обновляем состояние
|
||||||
|
if (costJobsWorkers.dataLoaded && costJobsWorkers.task !== task) {
|
||||||
|
setCostJobsWorkers(pv => ({
|
||||||
|
...pv,
|
||||||
|
dataLoaded: false,
|
||||||
|
columnsDef: [],
|
||||||
|
orders: null,
|
||||||
|
rows: [],
|
||||||
|
selectedRows: [],
|
||||||
|
reload: true,
|
||||||
|
pageNumber: 1,
|
||||||
|
morePages: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
//Если необходимо перезагрузить
|
||||||
|
if (costJobsWorkers.reload && task) {
|
||||||
|
const loadData = async () => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_MECHREC.WORKERS_MP_DG_GET",
|
||||||
|
args: {
|
||||||
|
NFCJOBS: task,
|
||||||
|
NPAGE_NUMBER: costJobsWorkers.pageNumber,
|
||||||
|
NPAGE_SIZE: DATA_GRID_PAGE_SIZE,
|
||||||
|
CORDERS: { VALUE: object2Base64XML(costJobsWorkers.orders, { arrayNodeName: "orders" }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
|
||||||
|
NINCLUDE_DEF: costJobsWorkers.dataLoaded ? 0 : 1
|
||||||
|
},
|
||||||
|
respArg: "COUT",
|
||||||
|
attributeValueProcessor: (name, val) => (["NSELECT"].includes(name) ? val === 1 : val)
|
||||||
|
});
|
||||||
|
setCostJobsWorkers(pv => ({
|
||||||
|
...pv,
|
||||||
|
...data.XDATA_GRID,
|
||||||
|
task: task,
|
||||||
|
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef,
|
||||||
|
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...pv.rows, ...(data.XDATA_GRID.rows || [])],
|
||||||
|
dataLoaded: true,
|
||||||
|
reload: false,
|
||||||
|
morePages: (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
SERV_DATA_TYPE_CLOB,
|
||||||
|
costJobsWorkers.dataLoaded,
|
||||||
|
costJobsWorkers.orders,
|
||||||
|
costJobsWorkers.pageNumber,
|
||||||
|
costJobsWorkers.reload,
|
||||||
|
costJobsWorkers.task,
|
||||||
|
executeStored,
|
||||||
|
task
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [costJobsWorkers, setCostJobsWorkers, includeWorker, excludeWorker];
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useCostJobs, useCostJobsSpecs, useCostJobsWorkers };
|
16
app/panels/mech_rec_cost_jobs_manage_mp/index.js
Normal file
16
app/panels/mech_rec_cost_jobs_manage_mp/index.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания на участок
|
||||||
|
Панель мониторинга: Точка входа
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import { MechRecCostJobs } from "./mech_rec_cost_jobs_manage_mp"; //Корневая панель выдачи сменного задания на участок
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export const RootClass = MechRecCostJobs;
|
@ -0,0 +1,483 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания на участок
|
||||||
|
Панель мониторинга: Корневая панель выдачи сменного задания на участок
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState } from "react"; //Классы React
|
||||||
|
import { Grid, Box, Typography, Checkbox, Icon, Stack, Button, Tooltip, TextField } from "@mui/material"; //Интерфейсные элементы
|
||||||
|
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
|
||||||
|
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
|
||||||
|
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_MORE_HEIGHT } from "../../components/p8p_data_grid"; //Таблица данных
|
||||||
|
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||||
|
import { useCostJobs, useCostJobsSpecs, useCostJobsWorkers } from "./hooks"; //Вспомогательные хуки
|
||||||
|
import { CostJobsSpecsInclude } from "./worker_include_dialog"; //Компонент диалога включения в задание
|
||||||
|
import { hasValue } from "../../core/utils"; //Вспомогательные функции
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Мнемокод раздела операций
|
||||||
|
const UNIT_COST_JOBS_SPECS = "CostJobsSpecs";
|
||||||
|
|
||||||
|
//Мнемокод раздела исполнений должности
|
||||||
|
const UNIT_WORKERS = "ClientPostPerform";
|
||||||
|
|
||||||
|
//Высота основного заголовка
|
||||||
|
const MAIN_HEADER_HEIGHT = "35px";
|
||||||
|
|
||||||
|
//Высота подзаголовка
|
||||||
|
const SUB_HEADER_HEIGHT = "35px";
|
||||||
|
|
||||||
|
//Высота заголовка таблицы
|
||||||
|
const TABLE_HEADER_HEIGHT = "35px";
|
||||||
|
|
||||||
|
//Высота панели кнопок таблицы
|
||||||
|
const TABLE_BUTTONS_HEIGHT = "35px";
|
||||||
|
|
||||||
|
//Отступ таблицы
|
||||||
|
const TABLE_PADDING_TOP = "15px";
|
||||||
|
|
||||||
|
//Формат для коэффициент выполнения норм
|
||||||
|
const issueCoeffFormat = /^(?!.*\..*\.)[0-9]{0,3}(\.[0-9]{0,1})?$/;
|
||||||
|
|
||||||
|
//Стили
|
||||||
|
const STYLES = {
|
||||||
|
MAIN_HEADER: { height: MAIN_HEADER_HEIGHT, overflow: "hidden" },
|
||||||
|
SUB_HEADER: { height: SUB_HEADER_HEIGHT, overflow: "hidden" },
|
||||||
|
CONTAINER: { textAlign: "center" },
|
||||||
|
TABLE: { paddingTop: TABLE_PADDING_TOP },
|
||||||
|
TABLE_HEADER: { height: TABLE_HEADER_HEIGHT, overflow: "hidden" },
|
||||||
|
TABLE_BUTTONS: { display: "flex", justifyContent: "flex-end", height: TABLE_BUTTONS_HEIGHT, overflow: "hidden", alignItems: "flex-end" },
|
||||||
|
DATA_GRID_CONTAINER: morePages => ({
|
||||||
|
height: `calc(100vh - ${APP_BAR_HEIGHT} - ${MAIN_HEADER_HEIGHT} - ${SUB_HEADER_HEIGHT} - ${TABLE_HEADER_HEIGHT} - ${TABLE_BUTTONS_HEIGHT} - ${TABLE_PADDING_TOP} - 32px - ${
|
||||||
|
morePages ? P8P_DATA_GRID_MORE_HEIGHT : "0px"
|
||||||
|
})`,
|
||||||
|
...APP_STYLES.SCROLL
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//Цвета
|
||||||
|
const colors = {
|
||||||
|
LINKED: "#bce0de",
|
||||||
|
UNAVAILABLE: "#949494",
|
||||||
|
WITH_WORKER: "#82df83"
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
//Вспомогательные функции и компоненты
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
//Проверка правильности значения коэффициент выполнения норм
|
||||||
|
const isValidIssueCoeff = value => {
|
||||||
|
return issueCoeffFormat.test(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Форматирование значения ячейки
|
||||||
|
const dataCellRender = ({ row, columnDef, handleSelectChange, sUnit, selectedWorkerRows = [], selectedJobSpec }) => {
|
||||||
|
//Стиль
|
||||||
|
let cellStyle = {};
|
||||||
|
//Если это рабочие
|
||||||
|
if (sUnit === UNIT_WORKERS) {
|
||||||
|
//Признак недоступности
|
||||||
|
let disabled = true;
|
||||||
|
//Если в выбранной строке смены указан исполнитель факт
|
||||||
|
if (selectedJobSpec.NPERFORM_FACT) {
|
||||||
|
//Если это текущей исполнитель
|
||||||
|
if (selectedJobSpec.SWORKERS_LIST.includes(row["NRN"])) {
|
||||||
|
//Подсвечиваем строку рабочего
|
||||||
|
cellStyle = { backgroundColor: colors.LINKED };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Если выбрана строка смены
|
||||||
|
if (selectedJobSpec.NRN) {
|
||||||
|
//Если текущий рабочий может принять задание
|
||||||
|
if (row["NLOADING"] < 100) {
|
||||||
|
//Подсвечиваем строку рабочего
|
||||||
|
cellStyle = { backgroundColor: colors.LINKED };
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Если уже выбрано достаточное количество рабочих и текущий рабочий не отмечен
|
||||||
|
if (selectedJobSpec.NRESOURCE_NUMB === selectedWorkerRows.length && !selectedWorkerRows.includes(row["NRN"])) {
|
||||||
|
//Устанавливаем признак недоступности
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
//Если загрузка рабочего больше 100
|
||||||
|
if (row["NLOADING"] >= 100) {
|
||||||
|
//Если поле не поле выбора
|
||||||
|
if (columnDef.name !== "NSELECT") {
|
||||||
|
//Указываем, что рабочее место недоступно
|
||||||
|
cellStyle = { ...cellStyle, color: colors.UNAVAILABLE };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Для колонки выбора
|
||||||
|
if (columnDef.name === "NSELECT") {
|
||||||
|
return {
|
||||||
|
cellStyle,
|
||||||
|
data: (
|
||||||
|
<Box sx={STYLES.CONTAINER}>
|
||||||
|
<Checkbox
|
||||||
|
disabled={disabled}
|
||||||
|
checked={selectedWorkerRows.includes(row["NRN"])}
|
||||||
|
onChange={() => handleSelectChange({ NRN: row["NRN"], SUNIT: sUnit, BFULL_LOADED: row["NLOADING"] >= 100 })}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//Отформатированная колонка
|
||||||
|
return {
|
||||||
|
cellStyle,
|
||||||
|
data: row[columnDef.name]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//Если это сменное задание
|
||||||
|
if (sUnit === UNIT_COST_JOBS_SPECS) {
|
||||||
|
//Если указан исполнитель факт
|
||||||
|
if (row["NPERFORM_FACT"]) {
|
||||||
|
//Подсвечиваем сменное задание зеленым
|
||||||
|
cellStyle = { ...cellStyle, backgroundColor: colors.WITH_WORKER };
|
||||||
|
}
|
||||||
|
//Для колонки выбора
|
||||||
|
if (columnDef.name === "NSELECT") {
|
||||||
|
return {
|
||||||
|
cellStyle,
|
||||||
|
data: (
|
||||||
|
<Box sx={STYLES.CONTAINER}>
|
||||||
|
<Checkbox
|
||||||
|
disabled={row["DBEG_FACT"] ? true : false}
|
||||||
|
checked={row["NRN"] === selectedJobSpec.NRN}
|
||||||
|
onChange={() =>
|
||||||
|
handleSelectChange({
|
||||||
|
NRN: row["NRN"],
|
||||||
|
SUNIT: sUnit,
|
||||||
|
NPERFORM_FACT: row["NPERFORM_FACT"],
|
||||||
|
NRESOURCE_NUMB: row["NRESOURCE_NUMB"],
|
||||||
|
NQUANT_PLAN: row["NQUANT_PLAN"],
|
||||||
|
SWORKERS_LIST: row["SWORKERS_LIST"]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//Отформатированная колонка
|
||||||
|
return {
|
||||||
|
cellStyle,
|
||||||
|
data: row[columnDef.name]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//Необрабатываемый раздел
|
||||||
|
return {
|
||||||
|
data: row[columnDef.name]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Генерация представления ячейки заголовка группы
|
||||||
|
export const headCellRender = ({ columnDef }) => {
|
||||||
|
if (columnDef.name === "NSELECT") {
|
||||||
|
return {
|
||||||
|
stackStyle: { padding: "2px", justifyContent: "space-around" },
|
||||||
|
data: <Icon>done</Icon>
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
stackStyle: { padding: "2px" },
|
||||||
|
data: columnDef.caption
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Корневая панель выдачи сменного задания на участок
|
||||||
|
const MechRecCostJobs = () => {
|
||||||
|
//Состояние диалога включения в задание
|
||||||
|
const [showInclude, setShowInclude] = useState(false);
|
||||||
|
|
||||||
|
//Состояние информации о сменном задании
|
||||||
|
const [state, setState] = useCostJobs();
|
||||||
|
|
||||||
|
//Состояние таблицы сменных заданий
|
||||||
|
const [costJobsSpecs, setCostJobsSpecs, issueCostJobsSpecs] = useCostJobsSpecs(state.jobInfo.NRN);
|
||||||
|
|
||||||
|
//Состояние таблицы рабочих
|
||||||
|
const [costJobsWorkers, setCostJobsWorkers, includeWorker, excludeWorker] = useCostJobsWorkers(state.jobInfo.NRN);
|
||||||
|
|
||||||
|
//При изменении состояния сортировки операций
|
||||||
|
const handleCostJobsSpecOrderChanged = ({ orders }) => setCostJobsSpecs(pv => ({ ...pv, orders: [...orders], pageNumber: 1, reload: true }));
|
||||||
|
|
||||||
|
//При изменении количества отображаемых страниц операций
|
||||||
|
const handleCostJobsSpecPagesCountChanged = () => setCostJobsSpecs(pv => ({ ...pv, pageNumber: pv.pageNumber + 1, reload: true }));
|
||||||
|
|
||||||
|
//При изменении состояния сортировки рабочих
|
||||||
|
const handleCostJobsWorkersOrderChanged = ({ orders }) => setCostJobsWorkers(pv => ({ ...pv, orders: [...orders], pageNumber: 1, reload: true }));
|
||||||
|
|
||||||
|
//При изменении количества отображаемых страниц рабочих
|
||||||
|
const handleCostJobsWorkersPagesCountChanged = () => setCostJobsWorkers(pv => ({ ...pv, pageNumber: pv.pageNumber + 1, reload: true }));
|
||||||
|
|
||||||
|
//При исключении рабочих из строки сменного задания
|
||||||
|
const handleCostJobsSpecExcludeWorker = () => {
|
||||||
|
//Делаем асинхронно, чтобы при ошибке ничего не обновлять
|
||||||
|
const excludeAsync = async () => {
|
||||||
|
//Исключаем рабочего из строки сменного задания
|
||||||
|
try {
|
||||||
|
await excludeWorker({
|
||||||
|
NFCJOBSSP: costJobsSpecs.selectedRow.NRN
|
||||||
|
});
|
||||||
|
//Необходимо обновить данные
|
||||||
|
setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
|
||||||
|
setCostJobsWorkers(pv => ({ ...pv, selectedRows: [], pageNumber: 1, reload: true }));
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//Исключаем рабочего асинхронно
|
||||||
|
excludeAsync();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Выдача задания операции
|
||||||
|
const handleCostJobsSpecIssue = () => {
|
||||||
|
//Делаем асинхронно, чтобы при ошибке ничего не обновлять
|
||||||
|
const issueAsync = async () => {
|
||||||
|
//Включаем рабочих в операции
|
||||||
|
try {
|
||||||
|
await issueCostJobsSpecs({ NFCJOBS: state.jobInfo.NRN, NCOEFF: state.coeff });
|
||||||
|
//Необходимо обновить данные
|
||||||
|
setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
|
||||||
|
setCostJobsWorkers(pv => ({ ...pv, selectedRows: [], pageNumber: 1, reload: true }));
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//Выдаем задание асинхронно
|
||||||
|
issueAsync();
|
||||||
|
};
|
||||||
|
|
||||||
|
//При изменение состояния выбора
|
||||||
|
const handleSelectChange = prms => {
|
||||||
|
//Выбранный элемент
|
||||||
|
let selectedRow = null;
|
||||||
|
//Буфер для выбранных рабочих
|
||||||
|
let selectedWorkers = [];
|
||||||
|
//Индекс рабочего в списке выбранных
|
||||||
|
let workerIndex = null;
|
||||||
|
//Исходим от раздела
|
||||||
|
switch (prms.SUNIT) {
|
||||||
|
//Сменное задание
|
||||||
|
case UNIT_COST_JOBS_SPECS:
|
||||||
|
//Определяем это новое отмеченное сменное задание или сброс старого
|
||||||
|
selectedRow = costJobsSpecs.selectedRow.NRN ? (costJobsSpecs.selectedRow.NRN === prms.NRN ? null : prms.NRN) : prms.NRN;
|
||||||
|
//Актуализируем строки
|
||||||
|
setCostJobsSpecs(pv => ({
|
||||||
|
...pv,
|
||||||
|
selectedRow: selectedRow
|
||||||
|
? {
|
||||||
|
NRN: selectedRow,
|
||||||
|
NPERFORM_FACT: prms.NPERFORM_FACT,
|
||||||
|
NRESOURCE_NUMB: prms.NRESOURCE_NUMB,
|
||||||
|
NQUANT_PLAN: prms.NQUANT_PLAN,
|
||||||
|
SWORKERS_LIST: prms.SWORKERS_LIST
|
||||||
|
}
|
||||||
|
: { NRN: null, NPERFORM_FACT: null, NRESOURCE_NUMB: null, NQUANT_PLAN: null, SWORKERS_LIST: [] }
|
||||||
|
}));
|
||||||
|
//Выходим
|
||||||
|
break;
|
||||||
|
//Рабочие центры
|
||||||
|
case UNIT_WORKERS:
|
||||||
|
//Инициализируем рабочими центрами
|
||||||
|
selectedWorkers = costJobsWorkers.selectedRows || [];
|
||||||
|
//Определяем индекс элемента в массиве
|
||||||
|
workerIndex = selectedWorkers.indexOf(prms.NRN);
|
||||||
|
//Если такого рег. номера нет в списке - добавляем, иначе удаляем
|
||||||
|
workerIndex > -1 ? selectedWorkers.splice(workerIndex, 1) : selectedWorkers.push(prms.NRN);
|
||||||
|
//Актуализируем строки
|
||||||
|
setCostJobsWorkers(pv => ({ ...pv, selectedRows: selectedWorkers }));
|
||||||
|
//Выходим
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//При открытии/закрытии диалога добавления
|
||||||
|
const handleShowIncludeChange = needShow => setShowInclude(needShow);
|
||||||
|
|
||||||
|
//При изменении коэффициент выполнения норм
|
||||||
|
const handleIssueCoeffChange = e => {
|
||||||
|
isValidIssueCoeff(e.target.value) ? setState(pv => ({ ...pv, coeff: e.target.value })) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box p={2}>
|
||||||
|
{state.loaded ? (
|
||||||
|
<Box sx={STYLES.CONTAINER}>
|
||||||
|
<Typography
|
||||||
|
sx={STYLES.MAIN_HEADER}
|
||||||
|
variant={"h6"}
|
||||||
|
>{`Сменное задание №${state.jobInfo.SDOC_NUMB} на ${state.jobInfo.SPERIOD}`}</Typography>
|
||||||
|
<Typography sx={STYLES.SUB_HEADER} variant={"h6"}>{`${state.jobInfo.SSUBDIV}`}</Typography>
|
||||||
|
<Box sx={STYLES.CONTAINER}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item sx={STYLES.CONTAINER} xs={6}>
|
||||||
|
<Typography sx={STYLES.TABLE_HEADER} variant={"h6"} color={"text.secondary"}>
|
||||||
|
Сменное задание
|
||||||
|
</Typography>
|
||||||
|
{costJobsWorkers.dataLoaded ? (
|
||||||
|
<>
|
||||||
|
<Box sx={STYLES.TABLE_BUTTONS}>
|
||||||
|
<Stack direction={"row"} spacing={1}>
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
state.jobInfo.NHAVE_NOTE
|
||||||
|
? "Сменное задание имеет строку с примечанием"
|
||||||
|
: "Коэффициент выполнения норм"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
name="editIssueValue"
|
||||||
|
variant="outlined"
|
||||||
|
sx={{ width: "68px" }}
|
||||||
|
inputProps={{ sx: { padding: "4.2px 14px" } }}
|
||||||
|
size="small"
|
||||||
|
value={state.coeff}
|
||||||
|
onChange={handleIssueCoeffChange}
|
||||||
|
disabled={state.jobInfo.NHAVE_NOTE}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
state.jobInfo.NHAVE_NOTE
|
||||||
|
? "Сменное задание имеет строку с примечанием"
|
||||||
|
: !hasValue(state.coeff)
|
||||||
|
? "Не указано значение коэффициент выполнения норм"
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
disabled={state.jobInfo.NHAVE_NOTE || !hasValue(state.coeff)}
|
||||||
|
onClick={handleCostJobsSpecIssue}
|
||||||
|
>
|
||||||
|
Выдать задания
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
<Box sx={STYLES.TABLE}>
|
||||||
|
<P8PDataGrid
|
||||||
|
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||||
|
containerComponentProps={{ sx: STYLES.DATA_GRID_CONTAINER(costJobsSpecs.morePages), elevation: 1 }}
|
||||||
|
columnsDef={costJobsSpecs.columnsDef}
|
||||||
|
rows={costJobsSpecs.rows}
|
||||||
|
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||||
|
morePages={costJobsSpecs.morePages}
|
||||||
|
reloading={costJobsSpecs.reload}
|
||||||
|
onOrderChanged={handleCostJobsSpecOrderChanged}
|
||||||
|
onPagesCountChanged={handleCostJobsSpecPagesCountChanged}
|
||||||
|
dataCellRender={prms =>
|
||||||
|
dataCellRender({
|
||||||
|
...prms,
|
||||||
|
handleSelectChange,
|
||||||
|
sUnit: UNIT_COST_JOBS_SPECS,
|
||||||
|
selectedJobSpec: costJobsSpecs.selectedRow
|
||||||
|
})
|
||||||
|
}
|
||||||
|
headCellRender={prms => headCellRender({ ...prms })}
|
||||||
|
fixedHeader={true}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</Grid>
|
||||||
|
<Grid item sx={STYLES.CONTAINER} xs={6}>
|
||||||
|
<Typography sx={STYLES.TABLE_HEADER} variant={"h6"} color={"text.secondary"}>
|
||||||
|
Рабочие
|
||||||
|
</Typography>
|
||||||
|
{costJobsWorkers.dataLoaded ? (
|
||||||
|
<>
|
||||||
|
<Box sx={STYLES.TABLE_BUTTONS}>
|
||||||
|
<Stack direction={"row"} spacing={1}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
disabled={!(costJobsSpecs.selectedRow.NRESOURCE_NUMB === costJobsWorkers.selectedRows.length)}
|
||||||
|
onClick={() => handleShowIncludeChange(true)}
|
||||||
|
>
|
||||||
|
Включить в задание
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
disabled={!costJobsSpecs.selectedRow.NRN || !costJobsSpecs.selectedRow.NPERFORM_FACT}
|
||||||
|
onClick={handleCostJobsSpecExcludeWorker}
|
||||||
|
>
|
||||||
|
Исключить из задания
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
<Box sx={STYLES.TABLE}>
|
||||||
|
<P8PDataGrid
|
||||||
|
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||||
|
containerComponentProps={{ sx: STYLES.DATA_GRID_CONTAINER(costJobsWorkers.morePages), elevation: 1 }}
|
||||||
|
columnsDef={costJobsWorkers.columnsDef}
|
||||||
|
rows={costJobsWorkers.rows}
|
||||||
|
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||||
|
morePages={costJobsWorkers.morePages}
|
||||||
|
reloading={costJobsWorkers.reload}
|
||||||
|
onOrderChanged={handleCostJobsWorkersOrderChanged}
|
||||||
|
onPagesCountChanged={handleCostJobsWorkersPagesCountChanged}
|
||||||
|
dataCellRender={prms =>
|
||||||
|
dataCellRender({
|
||||||
|
...prms,
|
||||||
|
handleSelectChange,
|
||||||
|
sUnit: UNIT_WORKERS,
|
||||||
|
selectedWorkerRows: costJobsWorkers.selectedRows,
|
||||||
|
selectedJobSpec: costJobsSpecs.selectedRow
|
||||||
|
})
|
||||||
|
}
|
||||||
|
headCellRender={prms => headCellRender({ ...prms })}
|
||||||
|
fixedHeader={true}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
{showInclude ? (
|
||||||
|
<CostJobsSpecsInclude
|
||||||
|
includePrms={{
|
||||||
|
NFCJOBSSP: costJobsSpecs.selectedRow.NRN,
|
||||||
|
SELECTED_WORKERS: costJobsWorkers.selectedRows,
|
||||||
|
NQUANT_PLAN: costJobsSpecs.selectedRow.NQUANT_PLAN
|
||||||
|
}}
|
||||||
|
setShowInclude={setShowInclude}
|
||||||
|
setCostJobsSpecs={setCostJobsSpecs}
|
||||||
|
setCostJobsWorkers={setCostJobsWorkers}
|
||||||
|
includeWorker={includeWorker}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export { MechRecCostJobs };
|
103
app/panels/mech_rec_cost_jobs_manage_mp/worker_include_dialog.js
Normal file
103
app/panels/mech_rec_cost_jobs_manage_mp/worker_include_dialog.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания на участок
|
||||||
|
Панель мониторинга: Диалог включения рабочего в сменное задание
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState } from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import { Box, Button, Dialog, DialogTitle, DialogContent, TextField, DialogActions } from "@mui/material"; //Интерфейсные элементы
|
||||||
|
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Диалог включения рабочего в сменное задание
|
||||||
|
const CostJobsSpecsInclude = ({ includePrms, setShowInclude, setCostJobsSpecs, setCostJobsWorkers, includeWorker }) => {
|
||||||
|
//Собственное состояние - Значение приоритета
|
||||||
|
const [state, setState] = useState(includePrms.NQUANT_PLAN);
|
||||||
|
|
||||||
|
//При закрытии включения рабочего
|
||||||
|
const handlePriorEditClose = () => setShowInclude(false);
|
||||||
|
|
||||||
|
//При включении рабочего в строку сменного задания
|
||||||
|
const costJobsSpecIncludeCostEquipment = () => {
|
||||||
|
//Делаем асинхронно, чтобы при ошибке ничего не обновлять
|
||||||
|
const includeAsync = async () => {
|
||||||
|
//Включаем рабочего в строку сменного задания
|
||||||
|
try {
|
||||||
|
await includeWorker({
|
||||||
|
NFCJOBSSP: includePrms.NFCJOBSSP,
|
||||||
|
SELECTED_WORKERS: includePrms.SELECTED_WORKERS,
|
||||||
|
NQUANT_PLAN: state
|
||||||
|
});
|
||||||
|
//Необходимо обновить все данные
|
||||||
|
setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
|
||||||
|
setCostJobsWorkers(pv => ({ ...pv, selectedRows: [], pageNumber: 1, reload: true }));
|
||||||
|
handlePriorEditClose();
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//Включаем рабочего асинхронно
|
||||||
|
includeAsync();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open onClose={() => handlePriorEditClose()}>
|
||||||
|
<DialogTitle>Включить в задание</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Box>
|
||||||
|
<TextField
|
||||||
|
name="editInculdeValue"
|
||||||
|
label="Количество"
|
||||||
|
variant="standard"
|
||||||
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
type: "number",
|
||||||
|
inputProps: {
|
||||||
|
max: includePrms.NQUANT_PLAN,
|
||||||
|
min: 0
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={state}
|
||||||
|
onChange={event => {
|
||||||
|
var value = parseInt(event.target.value, 10);
|
||||||
|
if (value > includePrms.NQUANT_PLAN) {
|
||||||
|
value = includePrms.NQUANT_PLAN;
|
||||||
|
}
|
||||||
|
if (value < 0) {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
setState(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Box></Box>
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={costJobsSpecIncludeCostEquipment}>{BUTTONS.OK}</Button>
|
||||||
|
<Button onClick={() => handlePriorEditClose(null)}>{BUTTONS.CANCEL}</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Диалог включения рабочего в сменное задание
|
||||||
|
CostJobsSpecsInclude.propTypes = {
|
||||||
|
includePrms: PropTypes.object.isRequired,
|
||||||
|
setShowInclude: PropTypes.func.isRequired,
|
||||||
|
setCostJobsSpecs: PropTypes.func.isRequired,
|
||||||
|
setCostJobsWorkers: PropTypes.func.isRequired,
|
||||||
|
includeWorker: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export { CostJobsSpecsInclude };
|
File diff suppressed because it is too large
Load Diff
@ -120,6 +120,16 @@
|
|||||||
icon="psychology"
|
icon="psychology"
|
||||||
showInPanelsList="true"
|
showInPanelsList="true"
|
||||||
preview="./img/mech_rec_cost_jobs_manage.jpg"/>
|
preview="./img/mech_rec_cost_jobs_manage.jpg"/>
|
||||||
|
<Panel
|
||||||
|
name="MechRecCostJobsManageMP"
|
||||||
|
group="Планирование и учёт в дискретном производстве"
|
||||||
|
caption="Выдача сменного задания на участок"
|
||||||
|
desc="Управление составом сменных заданий трудового ресурса"
|
||||||
|
url="mech_rec_cost_jobs_manage_mp"
|
||||||
|
path="mech_rec_cost_jobs_manage_mp"
|
||||||
|
icon=""
|
||||||
|
showInPanelsList="false"
|
||||||
|
preview=""/>
|
||||||
<Panel
|
<Panel
|
||||||
name="MechRecDeptCostJobs"
|
name="MechRecDeptCostJobs"
|
||||||
group="Планирование и учёт в дискретном производстве"
|
group="Планирование и учёт в дискретном производстве"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user