ЦИТК-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"
|
||||
showInPanelsList="true"
|
||||
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
|
||||
name="MechRecDeptCostJobs"
|
||||
group="Планирование и учёт в дискретном производстве"
|
||||
|
Loading…
x
Reference in New Issue
Block a user