diff --git a/app/panels/mech_rec_cost_jobs_manage_mp/hooks.js b/app/panels/mech_rec_cost_jobs_manage_mp/hooks.js new file mode 100644 index 0000000..5d319a7 --- /dev/null +++ b/app/panels/mech_rec_cost_jobs_manage_mp/hooks.js @@ -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 }; diff --git a/app/panels/mech_rec_cost_jobs_manage_mp/index.js b/app/panels/mech_rec_cost_jobs_manage_mp/index.js new file mode 100644 index 0000000..704e3e2 --- /dev/null +++ b/app/panels/mech_rec_cost_jobs_manage_mp/index.js @@ -0,0 +1,16 @@ +/* + Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания на участок + Панель мониторинга: Точка входа +*/ + +//--------------------- +//Подключение библиотек +//--------------------- + +import { MechRecCostJobs } from "./mech_rec_cost_jobs_manage_mp"; //Корневая панель выдачи сменного задания на участок + +//---------------- +//Интерфейс модуля +//---------------- + +export const RootClass = MechRecCostJobs; diff --git a/app/panels/mech_rec_cost_jobs_manage_mp/mech_rec_cost_jobs_manage_mp.js b/app/panels/mech_rec_cost_jobs_manage_mp/mech_rec_cost_jobs_manage_mp.js new file mode 100644 index 0000000..806da82 --- /dev/null +++ b/app/panels/mech_rec_cost_jobs_manage_mp/mech_rec_cost_jobs_manage_mp.js @@ -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: ( + + handleSelectChange({ NRN: row["NRN"], SUNIT: sUnit, BFULL_LOADED: row["NLOADING"] >= 100 })} + /> + + ) + }; + } + //Отформатированная колонка + 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: ( + + + 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"] + }) + } + /> + + ) + }; + } + //Отформатированная колонка + 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: done + }; + } 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 ( + + {state.loaded ? ( + + {`Сменное задание №${state.jobInfo.SDOC_NUMB} на ${state.jobInfo.SPERIOD}`} + {`${state.jobInfo.SSUBDIV}`} + + + + + Сменное задание + + {costJobsWorkers.dataLoaded ? ( + <> + + + + + + + + + + + + + + + dataCellRender({ + ...prms, + handleSelectChange, + sUnit: UNIT_COST_JOBS_SPECS, + selectedJobSpec: costJobsSpecs.selectedRow + }) + } + headCellRender={prms => headCellRender({ ...prms })} + fixedHeader={true} + /> + + + ) : null} + + + + Рабочие + + {costJobsWorkers.dataLoaded ? ( + <> + + + + + + + + + dataCellRender({ + ...prms, + handleSelectChange, + sUnit: UNIT_WORKERS, + selectedWorkerRows: costJobsWorkers.selectedRows, + selectedJobSpec: costJobsSpecs.selectedRow + }) + } + headCellRender={prms => headCellRender({ ...prms })} + fixedHeader={true} + /> + + + ) : null} + + + + + ) : null} + {showInclude ? ( + + ) : null} + + ); +}; + +//---------------- +//Интерфейс модуля +//---------------- + +export { MechRecCostJobs }; diff --git a/app/panels/mech_rec_cost_jobs_manage_mp/worker_include_dialog.js b/app/panels/mech_rec_cost_jobs_manage_mp/worker_include_dialog.js new file mode 100644 index 0000000..2fef5f2 --- /dev/null +++ b/app/panels/mech_rec_cost_jobs_manage_mp/worker_include_dialog.js @@ -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 ( + handlePriorEditClose()}> + Включить в задание + + + { + var value = parseInt(event.target.value, 10); + if (value > includePrms.NQUANT_PLAN) { + value = includePrms.NQUANT_PLAN; + } + if (value < 0) { + value = 0; + } + setState(value); + }} + /> + + + + + + + + + ); +}; + +//Контроль свойств - Диалог включения рабочего в сменное задание +CostJobsSpecsInclude.propTypes = { + includePrms: PropTypes.object.isRequired, + setShowInclude: PropTypes.func.isRequired, + setCostJobsSpecs: PropTypes.func.isRequired, + setCostJobsWorkers: PropTypes.func.isRequired, + includeWorker: PropTypes.func.isRequired +}; + +//---------------- +//Интерфейс модуля +//---------------- + +export { CostJobsSpecsInclude }; diff --git a/db/PKG_P8PANELS_MECHREC.pck b/db/PKG_P8PANELS_MECHREC.pck index ce4dcf8..e9d53be 100644 --- a/db/PKG_P8PANELS_MECHREC.pck +++ b/db/PKG_P8PANELS_MECHREC.pck @@ -279,6 +279,56 @@ create or replace package PKG_P8PANELS_MECHREC as NFCPRODPLANSP in number, -- Рег. номер строки плана COUT out clob -- Сериализованная таблица данных ); + + /* Выдать задания сменного задания */ + procedure FCJOBSSP_MP_ISSUE + ( + NFCJOBS in number, -- Рег. номер сменного задания + NCOEFF in number := 1.1 -- Коэффициент выполнения норм + ); + + /* Исключение исполнителя из операции сменного задания */ + procedure FCJOBSSP_MP_EXC_PERFORM + ( + NFCJOBSSP in number -- Рег. номер строки сменного задания + ); + + /* Включение исполнителя в строку сменного задания */ + procedure FCJOBSSP_MP_INC_PERFORM + ( + NFCJOBSSP in number, -- Рег. номер строки сменного задания + SPERFORM_LIST in clob, -- Список отмеченных исполнителей (разделитель - ";") + NQUANT_PLAN in number -- Включаемое количество + ); + + /* Получение спецификации сменного задания */ + procedure FCJOBSSP_MP_DG_GET + ( + NFCJOBS in number, -- Рег. номер сменного задания + NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) + NPAGE_SIZE in number, -- Количество записей на странице (0 - все) + CORDERS in clob, -- Сортировки + NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ + COUT out clob -- Сериализованная таблица данных + ); + + /* Получение рабочих подразделения */ + procedure WORKERS_MP_DG_GET + ( + NFCJOBS in number, -- Рег. номер сменного задания + NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) + NPAGE_SIZE in number, -- Количество записей на странице (0 - все) + CORDERS in clob, -- Сортировки + NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ + COUT out clob -- Сериализованная таблица данных + ); + + /* Инициализация записей раздела "Сменные задания" */ + procedure FCJOBS_MP_INIT + ( + NFCJOBS in number, -- Рег. номер записи сменного задания + COUT out clob -- Информация о записи сменного задания + ); end PKG_P8PANELS_MECHREC; / @@ -6607,6 +6657,1153 @@ create or replace package body PKG_P8PANELS_MECHREC as PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end FCPRODCMP_DETAILS_GET; + + /* + Процедуры панели "Выдача сменного задания на участок" + */ + + /* Выдать задания сменного задания */ + procedure FCJOBSSP_MP_ISSUE + ( + NFCJOBS in number, -- Рег. номер сменного задания + NCOEFF in number := 1.1 -- Коэффициент выполнения норм + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + NDICMUNTS PKG_STD.TREF; -- Рег. номер ед. изм. дня + DSTART_DATE PKG_STD.TLDATE; -- Дата начала строки плана + DEND_DATE PKG_STD.TLDATE; -- Дата окончания строки плана + begin + /* Если сменное задание не указано */ + if (NFCJOBS is null) then + P_EXCEPTION(0, 'Сменное задание не определено.'); + end if; + /* Считываем единицу измерения минут */ + FIND_DICMUNTS_CODE(NFLAG_SMART => 0, + NFLAG_OPTION => 0, + NCOMPANY => NCOMPANY, + SMEAS_MNEMO => SDICMUNTS_DAY, + NRN => NDICMUNTS); + /* Отбираем строки с пустым исполнителем факт */ + for REC in (select T.RN + from FCJOBSSP T + where T.PRN = NFCJOBS + and T.PERFORM_FACT is null) + loop + /* Удаляем строку */ + P_FCJOBSSP_BASE_DELETE(NRN => REC.RN, NCOMPANY => NCOMPANY); + end loop; + /* Цикл по исполнителям строк */ + for PF in (select T.PERFORM_FACT from FCJOBSSP T where T.PRN = NFCJOBS group by T.PERFORM_FACT) + loop + /* Цикл по строкам с текущим исполнителем */ + for REC in (select TMP.*, + DECODE(B.RN, null, TMP.DDOC_DATE, TMP.DDOC_DATE + B.BEG_TIME) DSTART, + F_DICMUNTS_BASE_RECALC_QUANT(0, TMP.COMPANY, TMP.MUNIT, TMP.LABOUR_PLAN, NDICMUNTS) NLABOUR, + ROWNUM RNUM + from (select T.*, + J.DOCDATE DDOC_DATE, + COALESCE(T.TBOPERMODESP, J.TBOPERMODESP) NTBOPERMODESP + from FCJOBS J, + FCJOBSSP T + where J.RN = NFCJOBS + and T.PRN = J.RN + and T.PERFORM_FACT = PF.PERFORM_FACT + order by T.PRIOR_PARTY asc) TMP, + TBOPERMODESP B + where B.RN = TMP.NTBOPERMODESP) + loop + /* Если это первая строка - устанавливаем по смене */ + if (REC.RNUM = 1) then + DSTART_DATE := REC.DSTART; + DEND_DATE := DSTART_DATE + REC.NLABOUR / NCOEFF; + else + DSTART_DATE := DEND_DATE; + DEND_DATE := DSTART_DATE + REC.NLABOUR / NCOEFF; + end if; + /* Обновляем запись строки */ + P_FCJOBSSP_BASE_UPDATE(NRN => REC.RN, + NCOMPANY => REC.COMPANY, + SNUMB => REC.NUMB, + NTBOPERMODESP => REC.TBOPERMODESP, + SBARCODE => REC.BARCODE, + NFACEACC => REC.FACEACC, + NMATRES => REC.MATRES, + NNOMCLASSIF => REC.NOMCLASSIF, + NARTICLE => REC.ARTICLE, + NFCROUTSHTSP => REC.FCROUTSHTSP, + SOPER_NUMB => REC.OPER_NUMB, + NOPER_TPS => REC.OPER_TPS, + SOPER_UK => REC.OPER_UK, + NSIGN_CONTRL => REC.SIGN_CONTRL, + NMANPOWER => REC.MANPOWER, + NCATEGORY => REC.CATEGORY, + DBEG_PLAN => DSTART_DATE, + DEND_PLAN => DEND_DATE, + DBEG_FACT => REC.BEG_FACT, + DEND_FACT => REC.END_FACT, + NQUANT_PLAN => REC.QUANT_PLAN, + NQUANT_FACT => REC.QUANT_FACT, + NNORM => REC.NORM, + NT_SHT_FACT => REC.T_SHT_FACT, + NT_PZ_PLAN => REC.T_PZ_PLAN, + NT_PZ_FACT => REC.T_PZ_FACT, + NT_VSP_PLAN => REC.T_VSP_PLAN, + NT_VSP_FACT => REC.T_VSP_FACT, + NT_O_PLAN => REC.T_O_PLAN, + NT_O_FACT => REC.T_O_FACT, + NNORM_TYPE => REC.NORM_TYPE, + NSIGN_P_R => REC.SIGN_P_R, + NLABOUR_PLAN => REC.LABOUR_PLAN, + NLABOUR_FACT => REC.LABOUR_FACT, + NCOST_PLAN => REC.COST_PLAN, + NCOST_FACT => REC.COST_FACT, + NCOST_FOR => REC.COST_FOR, + NCURNAMES => REC.CURNAMES, + NPERFORM_PLAN => REC.PERFORM_PLAN, + NPERFORM_FACT => REC.PERFORM_FACT, + NSTAFFGRP_PLAN => REC.STAFFGRP_PLAN, + NSTAFFGRP_FACT => REC.STAFFGRP_FACT, + NEQUIP_PLAN => REC.EQUIP_PLAN, + NEQUIP_FACT => REC.EQUIP_FACT, + NLOSTTYPE => REC.LOSTTYPE, + NLOSTDEFL => REC.LOSTDEFL, + NFOREMAN => REC.FOREMAN, + NINSPECTOR => REC.INSPECTOR, + DOTK_DATE => REC.OTK_DATE, + NSUBDIV => REC.SUBDIV, + NEQCONFIG => REC.EQCONFIG, + SNOTE => 'Задание выдано ' || TO_CHAR(sysdate, 'dd.mm.yyyy hh24:mi:ss'), + NMUNIT => REC.MUNIT); + end loop; + end loop; + end FCJOBSSP_MP_ISSUE; + + /* Исключение исполнителя из операции сменного задания */ + procedure FCJOBSSP_MP_EXC_PERFORM + ( + NFCJOBSSP in number -- Рег. номер строки сменного задания + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + RFCJOBSSP FCJOBSSP%rowtype; -- Запись строки сменного задания + begin + /* Если рег. номер строки не указан */ + if (NFCJOBSSP is null) then + P_EXCEPTION(0, 'Строка сменного задания не определена.'); + end if; + /* Считываем запись строки сменного задания */ + RFCJOBSSP := UTL_FCJOBSSP_GET(NCOMPANY => NCOMPANY, NFCJOBSSP => NFCJOBSSP); + /* Если дата начала факт указана */ + if (RFCJOBSSP.BEG_FACT is not null) then + P_EXCEPTION(0, 'Указанная строка сменного задания исполняется.'); + end if; + /* Исключаем исполнителя */ + P_FCJOBSSP_BASE_UPDATE(NRN => RFCJOBSSP.RN, + NCOMPANY => RFCJOBSSP.COMPANY, + SNUMB => RFCJOBSSP.NUMB, + NTBOPERMODESP => RFCJOBSSP.TBOPERMODESP, + SBARCODE => RFCJOBSSP.BARCODE, + NFACEACC => RFCJOBSSP.FACEACC, + NMATRES => RFCJOBSSP.MATRES, + NNOMCLASSIF => RFCJOBSSP.NOMCLASSIF, + NARTICLE => RFCJOBSSP.ARTICLE, + NFCROUTSHTSP => RFCJOBSSP.FCROUTSHTSP, + SOPER_NUMB => RFCJOBSSP.OPER_NUMB, + NOPER_TPS => RFCJOBSSP.OPER_TPS, + SOPER_UK => RFCJOBSSP.OPER_UK, + NSIGN_CONTRL => RFCJOBSSP.SIGN_CONTRL, + NMANPOWER => RFCJOBSSP.MANPOWER, + NCATEGORY => RFCJOBSSP.CATEGORY, + DBEG_PLAN => RFCJOBSSP.BEG_PLAN, + DEND_PLAN => RFCJOBSSP.END_PLAN, + DBEG_FACT => RFCJOBSSP.BEG_FACT, + DEND_FACT => RFCJOBSSP.END_FACT, + NQUANT_PLAN => RFCJOBSSP.QUANT_PLAN, + NQUANT_FACT => RFCJOBSSP.QUANT_FACT, + NNORM => RFCJOBSSP.NORM, + NT_SHT_FACT => RFCJOBSSP.T_SHT_FACT, + NT_PZ_PLAN => RFCJOBSSP.T_PZ_PLAN, + NT_PZ_FACT => RFCJOBSSP.T_PZ_FACT, + NT_VSP_PLAN => RFCJOBSSP.T_VSP_PLAN, + NT_VSP_FACT => RFCJOBSSP.T_VSP_FACT, + NT_O_PLAN => RFCJOBSSP.T_O_PLAN, + NT_O_FACT => RFCJOBSSP.T_O_FACT, + NNORM_TYPE => RFCJOBSSP.NORM_TYPE, + NSIGN_P_R => RFCJOBSSP.SIGN_P_R, + NLABOUR_PLAN => RFCJOBSSP.LABOUR_PLAN, + NLABOUR_FACT => RFCJOBSSP.LABOUR_FACT, + NCOST_PLAN => RFCJOBSSP.COST_PLAN, + NCOST_FACT => RFCJOBSSP.COST_FACT, + NCOST_FOR => RFCJOBSSP.COST_FOR, + NCURNAMES => RFCJOBSSP.CURNAMES, + NPERFORM_PLAN => RFCJOBSSP.PERFORM_PLAN, + NPERFORM_FACT => null, + NSTAFFGRP_PLAN => RFCJOBSSP.STAFFGRP_PLAN, + NSTAFFGRP_FACT => RFCJOBSSP.STAFFGRP_FACT, + NEQUIP_PLAN => RFCJOBSSP.EQUIP_PLAN, + NEQUIP_FACT => RFCJOBSSP.EQUIP_FACT, + NLOSTTYPE => RFCJOBSSP.LOSTTYPE, + NLOSTDEFL => RFCJOBSSP.LOSTDEFL, + NFOREMAN => RFCJOBSSP.FOREMAN, + NINSPECTOR => RFCJOBSSP.INSPECTOR, + DOTK_DATE => RFCJOBSSP.OTK_DATE, + NSUBDIV => RFCJOBSSP.SUBDIV, + NEQCONFIG => RFCJOBSSP.EQCONFIG, + SNOTE => RFCJOBSSP.NOTE, + NMUNIT => RFCJOBSSP.MUNIT); + /* Очищаем строки дополнительных ресурсов */ + for REC in (select T.* from FCJOBSSPAR T where T.PRN = RFCJOBSSP.RN) + loop + /* Очищаем исполнителя дополнительного ресурса */ + P_FCJOBSSPAR_BASE_UPDATE(NRN => REC.RN, + NCOMPANY => REC.COMPANY, + NROUTSHTSPAR => REC.ROUTSHTSPAR, + NEQUIPMENT => REC.EQUIPMENT, + NMANPOWER => REC.MANPOWER, + NCATEGORY => REC.CATEGORY, + NNORM => REC.NORM, + NNORM_TYPE => REC.NORM_TYPE, + NSIGN_P_R => REC.SIGN_P_R, + NLABOUR_PLAN => REC.LABOUR_PLAN, + NLABOUR_FACT => REC.LABOUR_FACT, + NCOST_PLAN => REC.COST_PLAN, + NCOST_FACT => REC.COST_FACT, + NCOST_FOR => REC.COST_FOR, + NCURNAMES => REC.CURNAMES, + NPERFORM_PLAN => REC.PERFORM_PLAN, + NPERFORM_FACT => null, + NMUNIT => REC.MUNIT, + NPROCTYPE => REC.PROCTYPE); + end loop; + end FCJOBSSP_MP_EXC_PERFORM; + + /* Включение исполнителя в строку сменного задания */ + procedure FCJOBSSP_MP_INC_PERFORM + ( + NFCJOBSSP in number, -- Рег. номер строки сменного задания + SPERFORM_LIST in clob, -- Список отмеченных исполнителей (разделитель - ";") + NQUANT_PLAN in number -- Включаемое количество + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + NQUANT_REMN PKG_STD.TLNUMBER; -- Остаток количества + RFCJOBSSP FCJOBSSP%rowtype; -- Запись строки сменного задания + NNEW_FCJOBSSP PKG_STD.TREF; -- Рег. номер новой строки сменного задания + NNEW_FCJOBSSPAR PKG_STD.TREF; -- Рег. номер нового дополнительного ресурса строки сменного задания + NROUTLST PKG_STD.TREF; -- Рег. номер связанного МЛ + NROUTLSTSP PKG_STD.TREF; -- Рег. номер связанной строки МЛ + NCLNPSPFM PKG_STD.TREF; -- Рег. номер исполнения должности + + /* Проверка наличия состава оборудования */ + procedure CLNPSPFM_EXISTS + ( + NCLNPSPFM in number, -- Рег. номер исполнения должности + NCOMPANY in number -- Рег. номер организации + ) + is + NEXISTS PKG_STD.TNUMBER; -- Буфер + begin + /* Проверяем наличие оборудования */ + begin + select T.RN + into NEXISTS + from CLNPSPFM T + where T.RN = NCLNPSPFM + and T.COMPANY = NCOMPANY; + exception + when others then + P_EXCEPTION(0, 'Рабочее место не найдено.'); + end; + end CLNPSPFM_EXISTS; + + /* Пересчет "Трудоемкость план" строки сменного задания */ + procedure LABOUR_PLAN_RECALC + ( + RFCJOBSSP in out FCJOBSSP%rowtype, -- Запись строки сменного задания + NQUANT_PLAN in number -- Количество план + ) + is + begin + /* Если не установлен признак "То план" */ + if ((RFCJOBSSP.T_O_PLAN is null) or ((RFCJOBSSP.T_O_PLAN is not null) and (RFCJOBSSP.T_O_PLAN = 0))) then + /* Если установлен признак "На партию выпуска" */ + if (RFCJOBSSP.SIGN_P_R = 1) then + RFCJOBSSP.LABOUR_PLAN := RFCJOBSSP.NORM; + else + RFCJOBSSP.LABOUR_PLAN := RFCJOBSSP.NORM * NQUANT_PLAN; + end if; + else + /* Если установлен признак "На партию выпуска" */ + if (RFCJOBSSP.SIGN_P_R = 1) then + RFCJOBSSP.LABOUR_PLAN := RFCJOBSSP.T_O_PLAN + COALESCE(RFCJOBSSP.T_PZ_PLAN, 0) + + COALESCE(RFCJOBSSP.T_VSP_PLAN, 0); + else + RFCJOBSSP.LABOUR_PLAN := RFCJOBSSP.T_O_PLAN * NQUANT_PLAN + COALESCE(RFCJOBSSP.T_PZ_PLAN, 0) + + COALESCE(RFCJOBSSP.T_VSP_PLAN, 0); + end if; + end if; + end LABOUR_PLAN_RECALC; + begin + /* Если включаемое количество меньше 0 или пустое */ + if ((NQUANT_PLAN is null) or ((NQUANT_PLAN is not null) and (NQUANT_PLAN <= 0))) then + P_EXCEPTION(0, 'Невозможно включить указанное количество.'); + end if; + /* Если рег. номер строки не указан */ + if (NFCJOBSSP is null) then + P_EXCEPTION(0, 'Строка сменного задания не определена.'); + end if; + /* Считываем запись строки сменного задания */ + RFCJOBSSP := UTL_FCJOBSSP_GET(NCOMPANY => NCOMPANY, NFCJOBSSP => NFCJOBSSP); + /* Если дата начала факт указана */ + if (RFCJOBSSP.BEG_FACT is not null) then + P_EXCEPTION(0, 'Указанная строка сменного задания исполняется.'); + end if; + /* Если включаемое количество больше текущего */ + if (NQUANT_PLAN > RFCJOBSSP.QUANT_PLAN) then + P_EXCEPTION(0, + 'Указанное количество превышает текущее "Количество план" строки.'); + end if; + /* Если список исполнителей пуст */ + if (SPERFORM_LIST is null) then + P_EXCEPTION(0, 'Список исполнителей пуст.'); + end if; + /* Рассчитываем остаточное количество */ + NQUANT_REMN := RFCJOBSSP.QUANT_PLAN - NQUANT_PLAN; + /* Пересчитываем "Количество план" */ + LABOUR_PLAN_RECALC(RFCJOBSSP => RFCJOBSSP, NQUANT_PLAN => NQUANT_PLAN); + /* Обходим исполнителей */ + for I in 1 .. STRCNT(source => SPERFORM_LIST, DELIMETER => ';') + loop + /* Считываем рег. номер исполнения должности */ + NCLNPSPFM := TO_NUMBER(STRTOK(source => SPERFORM_LIST, DELIMETER => ';', ITEM => I)); + /* Проверяем наличие исполнения должности */ + CLNPSPFM_EXISTS(NCLNPSPFM => NCLNPSPFM, NCOMPANY => NCOMPANY); + /* Если это первый отмеченный */ + if (I = 1) then + /* Включаем исполнителя */ + P_FCJOBSSP_BASE_UPDATE(NRN => RFCJOBSSP.RN, + NCOMPANY => RFCJOBSSP.COMPANY, + SNUMB => RFCJOBSSP.NUMB, + NTBOPERMODESP => RFCJOBSSP.TBOPERMODESP, + SBARCODE => RFCJOBSSP.BARCODE, + NFACEACC => RFCJOBSSP.FACEACC, + NMATRES => RFCJOBSSP.MATRES, + NNOMCLASSIF => RFCJOBSSP.NOMCLASSIF, + NARTICLE => RFCJOBSSP.ARTICLE, + NFCROUTSHTSP => RFCJOBSSP.FCROUTSHTSP, + SOPER_NUMB => RFCJOBSSP.OPER_NUMB, + NOPER_TPS => RFCJOBSSP.OPER_TPS, + SOPER_UK => RFCJOBSSP.OPER_UK, + NSIGN_CONTRL => RFCJOBSSP.SIGN_CONTRL, + NMANPOWER => RFCJOBSSP.MANPOWER, + NCATEGORY => RFCJOBSSP.CATEGORY, + DBEG_PLAN => RFCJOBSSP.BEG_PLAN, + DEND_PLAN => RFCJOBSSP.END_PLAN, + DBEG_FACT => RFCJOBSSP.BEG_FACT, + DEND_FACT => RFCJOBSSP.END_FACT, + NQUANT_PLAN => NQUANT_PLAN, + NQUANT_FACT => RFCJOBSSP.QUANT_FACT, + NNORM => RFCJOBSSP.NORM, + NT_SHT_FACT => RFCJOBSSP.T_SHT_FACT, + NT_PZ_PLAN => RFCJOBSSP.T_PZ_PLAN, + NT_PZ_FACT => RFCJOBSSP.T_PZ_FACT, + NT_VSP_PLAN => RFCJOBSSP.T_VSP_PLAN, + NT_VSP_FACT => RFCJOBSSP.T_VSP_FACT, + NT_O_PLAN => RFCJOBSSP.T_O_PLAN, + NT_O_FACT => RFCJOBSSP.T_O_FACT, + NNORM_TYPE => RFCJOBSSP.NORM_TYPE, + NSIGN_P_R => RFCJOBSSP.SIGN_P_R, + NLABOUR_PLAN => RFCJOBSSP.LABOUR_PLAN, + NLABOUR_FACT => RFCJOBSSP.LABOUR_FACT, + NCOST_PLAN => RFCJOBSSP.COST_PLAN, + NCOST_FACT => RFCJOBSSP.COST_FACT, + NCOST_FOR => RFCJOBSSP.COST_FOR, + NCURNAMES => RFCJOBSSP.CURNAMES, + NPERFORM_PLAN => RFCJOBSSP.PERFORM_PLAN, + NPERFORM_FACT => NCLNPSPFM, + NSTAFFGRP_PLAN => RFCJOBSSP.STAFFGRP_PLAN, + NSTAFFGRP_FACT => RFCJOBSSP.STAFFGRP_FACT, + NEQUIP_PLAN => RFCJOBSSP.EQUIP_PLAN, + NEQUIP_FACT => RFCJOBSSP.EQUIP_FACT, + NLOSTTYPE => RFCJOBSSP.LOSTTYPE, + NLOSTDEFL => RFCJOBSSP.LOSTDEFL, + NFOREMAN => RFCJOBSSP.FOREMAN, + NINSPECTOR => RFCJOBSSP.INSPECTOR, + DOTK_DATE => RFCJOBSSP.OTK_DATE, + NSUBDIV => RFCJOBSSP.SUBDIV, + NEQCONFIG => RFCJOBSSP.EQCONFIG, + SNOTE => RFCJOBSSP.NOTE, + NMUNIT => RFCJOBSSP.MUNIT); + /* Если есть остаток */ + if (NQUANT_REMN <> 0) then + /* Обнуляем дату отработки */ + RFCJOBSSP.WORK_DATE := null; + /* Получаем новый номер */ + P_FCJOBSSP_GETNEXTNUMB(NCOMPANY => NCOMPANY, NPRN => RFCJOBSSP.PRN, SNUMB => RFCJOBSSP.NUMB); + /* Если штрихкод был указан */ + if (RFCJOBSSP.BARCODE is not null) then + /* Получаем новый штрихкод */ + P_FCJOBSSP_GET_BARCODE(NCOMPANY => NCOMPANY, NRN => RFCJOBSSP.RN, SBARCODE => RFCJOBSSP.BARCODE); + end if; + /* Пересчитываем "Количество план" */ + LABOUR_PLAN_RECALC(RFCJOBSSP => RFCJOBSSP, NQUANT_PLAN => NQUANT_REMN); + /* Размножаем запись */ + P_FCJOBSSP_BASE_INSERT(NCOMPANY => RFCJOBSSP.COMPANY, + NPRN => RFCJOBSSP.PRN, + SNUMB => RFCJOBSSP.NUMB, + NTBOPERMODESP => RFCJOBSSP.TBOPERMODESP, + SBARCODE => RFCJOBSSP.BARCODE, + NFACEACC => RFCJOBSSP.FACEACC, + NMATRES => RFCJOBSSP.MATRES, + NNOMCLASSIF => RFCJOBSSP.NOMCLASSIF, + NARTICLE => RFCJOBSSP.ARTICLE, + NFCROUTSHTSP => RFCJOBSSP.FCROUTSHTSP, + SOPER_NUMB => RFCJOBSSP.OPER_NUMB, + NOPER_TPS => RFCJOBSSP.OPER_TPS, + SOPER_UK => RFCJOBSSP.OPER_UK, + NSIGN_CONTRL => RFCJOBSSP.SIGN_CONTRL, + NMANPOWER => RFCJOBSSP.MANPOWER, + NCATEGORY => RFCJOBSSP.CATEGORY, + DBEG_PLAN => RFCJOBSSP.BEG_PLAN, + DEND_PLAN => RFCJOBSSP.END_PLAN, + DBEG_FACT => RFCJOBSSP.BEG_FACT, + DEND_FACT => RFCJOBSSP.END_FACT, + NQUANT_PLAN => NQUANT_REMN, + NQUANT_FACT => RFCJOBSSP.QUANT_FACT, + NNORM => RFCJOBSSP.NORM, + NT_SHT_FACT => RFCJOBSSP.T_SHT_FACT, + NT_PZ_PLAN => RFCJOBSSP.T_PZ_PLAN, + NT_PZ_FACT => RFCJOBSSP.T_PZ_FACT, + NT_VSP_PLAN => RFCJOBSSP.T_VSP_PLAN, + NT_VSP_FACT => RFCJOBSSP.T_VSP_FACT, + NT_O_PLAN => RFCJOBSSP.T_O_PLAN, + NT_O_FACT => RFCJOBSSP.T_O_FACT, + NNORM_TYPE => RFCJOBSSP.NORM_TYPE, + NSIGN_P_R => RFCJOBSSP.SIGN_P_R, + NLABOUR_PLAN => RFCJOBSSP.LABOUR_PLAN, + NLABOUR_FACT => RFCJOBSSP.LABOUR_FACT, + NCOST_PLAN => RFCJOBSSP.COST_PLAN, + NCOST_FACT => RFCJOBSSP.COST_FACT, + NCOST_FOR => RFCJOBSSP.COST_FOR, + NCURNAMES => RFCJOBSSP.CURNAMES, + NPERFORM_PLAN => RFCJOBSSP.PERFORM_PLAN, + NPERFORM_FACT => RFCJOBSSP.PERFORM_FACT, + NSTAFFGRP_PLAN => RFCJOBSSP.STAFFGRP_PLAN, + NSTAFFGRP_FACT => RFCJOBSSP.STAFFGRP_FACT, + NEQUIP_PLAN => RFCJOBSSP.EQUIP_PLAN, + NEQUIP_FACT => RFCJOBSSP.EQUIP_FACT, + NLOSTTYPE => RFCJOBSSP.LOSTTYPE, + NLOSTDEFL => RFCJOBSSP.LOSTDEFL, + NFOREMAN => RFCJOBSSP.FOREMAN, + NINSPECTOR => RFCJOBSSP.INSPECTOR, + DOTK_DATE => RFCJOBSSP.OTK_DATE, + NSUBDIV => RFCJOBSSP.SUBDIV, + NEQCONFIG => null, + NSIGN_AR => 1, + SNOTE => RFCJOBSSP.NOTE, + NMUNIT => RFCJOBSSP.MUNIT, + NPRIOR_ORDER => RFCJOBSSP.PRIOR_ORDER, + NPRIOR_PARTY => RFCJOBSSP.PRIOR_PARTY, + DEXEC_DATE => RFCJOBSSP.EXEC_DATE, + DREL_DATE => RFCJOBSSP.REL_DATE, + NRN => NNEW_FCJOBSSP); + /* Переносим дополнительные ресурсы */ + for AR in (select T.* from FCJOBSSPAR T where T.PRN = RFCJOBSSP.RN) + loop + /* Добавляем дополнительный ресурс */ + P_FCJOBSSPAR_BASE_INSERT(NCOMPANY => AR.COMPANY, + NPRN => NNEW_FCJOBSSP, + NROUTSHTSPAR => AR.ROUTSHTSPAR, + NEQUIPMENT => AR.EQUIPMENT, + NMANPOWER => AR.MANPOWER, + NCATEGORY => AR.CATEGORY, + NNORM => AR.NORM, + NNORM_TYPE => AR.NORM_TYPE, + NSIGN_P_R => AR.SIGN_P_R, + NLABOUR_PLAN => AR.LABOUR_PLAN, + NLABOUR_FACT => AR.LABOUR_FACT, + NCOST_PLAN => AR.COST_PLAN, + NCOST_FACT => AR.COST_FACT, + NCOST_FOR => AR.COST_FOR, + NCURNAMES => AR.CURNAMES, + NPERFORM_PLAN => AR.PERFORM_PLAN, + NPERFORM_FACT => null, + NMUNIT => AR.MUNIT, + NPROCTYPE => AR.PROCTYPE, + NRN => NNEW_FCJOBSSPAR); + end loop; + /* Связанные маршрутный лист и строка маршрутного листа */ + NROUTLST := F_DOCLINKS_LINK_IN_DOC(SOUT_UNITCODE => 'CostJobsSpecs', + NOUT_DOCUMENT => RFCJOBSSP.RN, + SIN_UNITCODE => 'CostRouteLists'); + NROUTLSTSP := F_DOCLINKS_LINK_IN_DOC(SOUT_UNITCODE => 'CostJobsSpecs', + NOUT_DOCUMENT => RFCJOBSSP.RN, + SIN_UNITCODE => 'CostRouteListsSpecs'); + /* Связывание с новой строкой сменного задания */ + if (NROUTLST is not null) and (NROUTLSTSP is not null) then + /* Создаем связь с заголовоком МЛ */ + P_LINKSALL_LINK_DIRECT(NCOMPANY => NCOMPANY, + SIN_UNITCODE => 'CostRouteLists', + NIN_DOCUMENT => NROUTLST, + NIN_PRN_DOCUMENT => null, + DIN_IN_DATE => sysdate, + NIN_STATUS => 0, + SOUT_UNITCODE => 'CostJobsSpecs', + NOUT_DOCUMENT => NNEW_FCJOBSSP, + NOUT_PRN_DOCUMENT => RFCJOBSSP.PRN, + DOUT_IN_DATE => sysdate, + NOUT_STATUS => 0); + /* Создаем связь со спецификацией МЛ */ + P_LINKSALL_LINK_DIRECT(NCOMPANY => NCOMPANY, + SIN_UNITCODE => 'CostRouteListsSpecs', + NIN_DOCUMENT => NROUTLSTSP, + NIN_PRN_DOCUMENT => NROUTLST, + DIN_IN_DATE => sysdate, + NIN_STATUS => 0, + SOUT_UNITCODE => 'CostJobsSpecs', + NOUT_DOCUMENT => NNEW_FCJOBSSP, + NOUT_PRN_DOCUMENT => RFCJOBSSP.PRN, + DOUT_IN_DATE => sysdate, + NOUT_STATUS => 0); + end if; + end if; + else + /* Отбираем строку дополнительного ресурса */ + for AR in (select TMP.* + from (select ROWNUM as RNUM, + R.* + from (select T.* from FCJOBSSPAR T where T.PRN = RFCJOBSSP.RN order by T.RN asc) R) TMP + where TMP.RNUM = I - 1) + loop + /* Обновляем её */ + P_FCJOBSSPAR_BASE_UPDATE(NRN => AR.RN, + NCOMPANY => AR.COMPANY, + NROUTSHTSPAR => AR.ROUTSHTSPAR, + NEQUIPMENT => AR.EQUIPMENT, + NMANPOWER => AR.MANPOWER, + NCATEGORY => AR.CATEGORY, + NNORM => AR.NORM, + NNORM_TYPE => AR.NORM_TYPE, + NSIGN_P_R => AR.SIGN_P_R, + NLABOUR_PLAN => AR.LABOUR_PLAN, + NLABOUR_FACT => AR.LABOUR_FACT, + NCOST_PLAN => AR.COST_PLAN, + NCOST_FACT => AR.COST_FACT, + NCOST_FOR => AR.COST_FOR, + NCURNAMES => AR.CURNAMES, + NPERFORM_PLAN => AR.PERFORM_PLAN, + NPERFORM_FACT => NCLNPSPFM, + NMUNIT => AR.MUNIT, + NPROCTYPE => AR.PROCTYPE); + end loop; + end if; + end loop; + end FCJOBSSP_MP_INC_PERFORM; + + /* Получение спецификации сменного задания */ + procedure FCJOBSSP_MP_DG_GET + ( + NFCJOBS in number, -- Рег. номер сменного задания + NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) + NPAGE_SIZE in number, -- Количество записей на странице (0 - все) + CORDERS in clob, -- Сортировки + NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ + COUT out clob -- Сериализованная таблица данных + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + RO PKG_P8PANELS_VISUAL.TDG_ORDERS; -- Сортировки + RDG PKG_P8PANELS_VISUAL.TDG; -- Описание таблицы + RDG_ROW PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы + NROW_FROM PKG_STD.TREF; -- Номер строки с + NROW_TO PKG_STD.TREF; -- Номер строки по + CSQL clob; -- Буфер для запроса + ICURSOR integer; -- Курсор для исполнения запроса + NVERSION PKG_STD.TREF; -- Версия контрагентов + SWORKERS_LIST PKG_STD.TSTRING; -- Список исполнителей строки сменного задания + NFCJOBSSP PKG_STD.TREF; -- Рег. номер строки сменного задания + + /* Функция формирования списка всех исполнителей строки сменного задания */ + function FCJOBSSP_WORKERS_LIST_GET + ( + NFCJOBSSP in number -- Рег. номер строки сменного задания + ) return varchar2 -- Список исполнителей + is + SWORKERS_LIST PKG_STD.TSTRING; -- Список исполнителей + begin + /* Обходим исполнителей строки сменного задания */ + for REC in (select T.PERFORM_FACT + from FCJOBSSP T + where T.RN = NFCJOBSSP + union + select S.PERFORM_FACT + from FCJOBSSPAR S + where S.PRN = NFCJOBSSP) + loop + SWORKERS_LIST := SWORKERS_LIST || REC.PERFORM_FACT || ','; + end loop; + /* Если есть исполнители */ + SWORKERS_LIST := RTRIM(SWORKERS_LIST, ','); + /* Возвращаем список исполнителей */ + return SWORKERS_LIST; + end FCJOBSSP_WORKERS_LIST_GET; + begin + /* Читем сортировки */ + RO := PKG_P8PANELS_VISUAL.TDG_ORDERS_FROM_XML(CORDERS => CORDERS); + /* Считываем версию контрагентов */ + FIND_VERSION_BY_COMPANY(NCOMPANY => NCOMPANY, SUNITCODE => 'AGNLIST', NVERSION => NVERSION); + /* Преобразуем номер и размер страницы в номер строк с и по */ + PKG_P8PANELS_VISUAL.UTL_ROWS_LIMITS_CALC(NPAGE_NUMBER => NPAGE_NUMBER, + NPAGE_SIZE => NPAGE_SIZE, + NROW_FROM => NROW_FROM, + NROW_TO => NROW_TO); + /* Инициализируем таблицу данных */ + RDG := PKG_P8PANELS_VISUAL.TDG_MAKE(BFIXED_HEADER => true, NFIXED_COLUMNS => 8); + /* Описываем колонки таблицы данных */ + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NRN', + SCAPTION => 'Рег. номер', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BVISIBLE => false); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NSELECT', + SCAPTION => 'Выбран', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SFCROUTLST', + SCAPTION => 'МЛ', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SMATRES', + SCAPTION => 'ДСЕ', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SOPER', + SCAPTION => 'Операция', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SMANPOWER', + SCAPTION => 'Профессия', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NQUANT_PLAN', + SCAPTION => 'Количество', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NRESOURCE_NUMB', + SCAPTION => 'Численность', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NLABOUR_PLAN', + SCAPTION => 'Трудоемкость', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SFIO', + SCAPTION => 'ФИО', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NPERFORM_FACT', + SCAPTION => 'Рег. номер исполнителя факт', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BVISIBLE => false); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'DBEG_FACT', + SCAPTION => 'Дата начала факт', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_DATE, + BVISIBLE => false); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SWORKERS_LIST', + SCAPTION => 'Список исполнителей', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BVISIBLE => false); + /* Обходим данные */ + begin + /* Добавляем подсказку совместимости */ + CSQL := PKG_SQL_BUILD.COMPATIBLE(SSQL => CSQL); + /* Формируем запрос */ + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => 'select *'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select D.*,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.SQLROWNUM() || ' NROW'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select T.RN NRN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' (select ' || PKG_SQL_BUILD.SET_HINT(SHINT => 'INDEX(L I_DOCLINKS_OUT_DOCUMENT)')); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' TRIM(D.DOCNUMB) || '' '' || to_char(D.DOCDATE, ''dd.mm.yyyy'')'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from DOCLINKS L,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' FCROUTLST D'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where L.OUT_DOCUMENT = T.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and L.OUT_UNITCODE = ' || PKG_SQL_BUILD.WRAP_STR(SVALUE => 'CostJobsSpecs')); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and L.IN_DOCUMENT = D.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and L.IN_UNITCODE = ' || PKG_SQL_BUILD.WRAP_STR(SVALUE => 'CostRouteLists')); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' ' || PKG_SQL_BUILD.ROWLIMIT(NLIMIT => 1, BAND => true) || ') SFCROUTLST,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' MR.CODE || '' '' || MR."NAME" SMATRES,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' TRIM(T.OPER_NUMB) || '' '' || ( select coalesce(O."NAME", T.OPER_UK) from FCOPERTYPES O where T.OPER_TPS = O.RN ) SOPER,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' (select MP.CODE from FCMANPOWER MP where T.MANPOWER = MP.RN) SMANPOWER,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' T.QUANT_PLAN NQUANT_PLAN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' COALESCE((select COUNT(SP.RN)'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from FCJOBSSPAR SP'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where SP.PRN = T.RN), 0) + 1 NRESOURCE_NUMB,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' T.LABOUR_PLAN NLABOUR_PLAN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' (select AG.AGNFAMILYNAME'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from CLNPSPFM C,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' CLNPERSONS P,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' AGNLIST AG'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where C.RN = T.PERFORM_FACT'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.PERSRN = P.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and P.PERS_AGENT = AG.RN) SFIO,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' T.PERFORM_FACT NPERFORM_FACT,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' T.BEG_FACT DBEG_FACT'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from FCJOBSSP T,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' FCMATRESOURCE MR'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where T.PRN = :NFCJOBS'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and T.COMPANY = :NCOMPANY'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and T.SIGN_CONTRL = ' || PKG_SQL_BUILD.WRAP_NUM(NVALUE => 0)); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and MR.RN = T.MATRES'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' %ORDER_BY%) D) F'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where F.NROW between :NROW_FROM and :NROW_TO'); + /* Если сортировки не указаны */ + if (CORDERS is not null) then + /* Учтём сортировки */ + PKG_P8PANELS_VISUAL.TDG_ORDERS_SET_QUERY(RDATA_GRID => RDG, + RORDERS => RO, + SPATTERN => '%ORDER_BY%', + CSQL => CSQL); + else + /* Устанавливаем стандартную сортировку */ + CSQL := replace(CSQL, '%ORDER_BY%', 'order by T.PRIOR_PARTY asc, T.BEG_PLAN asc'); + end if; + /* Разбираем его */ + ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); + PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => CSQL); + /* Делаем подстановку параметров */ + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NFCJOBS', NVALUE => NFCJOBS); + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NCOMPANY', NVALUE => NCOMPANY); + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_FROM', NVALUE => NROW_FROM); + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_TO', NVALUE => NROW_TO); + /* Описываем структуру записи курсора */ + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 1); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 2); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 3); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 4); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 5); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 6); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 7); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 8); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 9); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 10); + PKG_SQL_DML.DEFINE_COLUMN_DATE(ICURSOR => ICURSOR, IPOSITION => 11); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 12); + /* Делаем выборку */ + if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then + null; + end if; + /* Обходим выбранные записи */ + while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0) + loop + /* Читаем данные из курсора рег. номер исполнения */ + PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => 1, NVALUE => NFCJOBSSP); + /* Считываем список исполнителей строки сменного задания */ + SWORKERS_LIST := FCJOBSSP_WORKERS_LIST_GET(NFCJOBSSP => NFCJOBSSP); + /* Добавляем колонки с данными */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => NFCJOBSSP, BCLEAR => true); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSELECT', NVALUE => 0); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, + SNAME => 'SFCROUTLST', + ICURSOR => ICURSOR, + NPOSITION => 2); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, + SNAME => 'SMATRES', + ICURSOR => ICURSOR, + NPOSITION => 3); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SOPER', ICURSOR => ICURSOR, NPOSITION => 4); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, + SNAME => 'SMANPOWER', + ICURSOR => ICURSOR, + NPOSITION => 5); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW, + SNAME => 'NQUANT_PLAN', + ICURSOR => ICURSOR, + NPOSITION => 6); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW, + SNAME => 'NRESOURCE_NUMB', + ICURSOR => ICURSOR, + NPOSITION => 7); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW, + SNAME => 'NLABOUR_PLAN', + ICURSOR => ICURSOR, + NPOSITION => 8); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SFIO', ICURSOR => ICURSOR, NPOSITION => 9); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW, + SNAME => 'NPERFORM_FACT', + ICURSOR => ICURSOR, + NPOSITION => 10); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLD(RROW => RDG_ROW, + SNAME => 'DBEG_FACT', + ICURSOR => ICURSOR, + NPOSITION => 11); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SWORKERS_LIST', SVALUE => SWORKERS_LIST); + /* Добавляем строку в таблицу */ + PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); + end loop; + exception + when others then + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); + raise; + end; + /* Сериализуем описание */ + COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => NINCLUDE_DEF); + end FCJOBSSP_MP_DG_GET; + + /* Получение рабочих подразделения */ + procedure WORKERS_MP_DG_GET + ( + NFCJOBS in number, -- Рег. номер сменного задания + NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) + NPAGE_SIZE in number, -- Количество записей на странице (0 - все) + CORDERS in clob, -- Сортировки + NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ + COUT out clob -- Сериализованная таблица данных + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + RO PKG_P8PANELS_VISUAL.TDG_ORDERS; -- Сортировки + RDG PKG_P8PANELS_VISUAL.TDG; -- Описание таблицы + RDG_ROW PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы + NROW_FROM PKG_STD.TREF; -- Номер строки с + NROW_TO PKG_STD.TREF; -- Номер строки по + CSQL clob; -- Буфер для запроса + ICURSOR integer; -- Курсор для исполнения запроса + NSUBDIV PKG_STD.TNUMBER; -- Рег. номер подразделения пользователя + DDOC_DATE PKG_STD.TLDATE; -- Дата сменного задания + NSUM_LABOUR PKG_STD.TLNUMBER; -- Сумма трудоемкости + NSUM_WORK_TIME PKG_STD.TLNUMBER; -- Сумма рабочего времени + NLOADING PKG_STD.TLNUMBER; -- Загрузка оборудования + NDICMUNTS_MIN PKG_STD.TREF; -- Рег. номер ед. изм. минут + NDICMUNTS_WD PKG_STD.TREF; -- Рег. номер ед. изм. нормочасов + NCLNPSPFM PKG_STD.TREF; -- Рег. номер исполнения должности + + /* Считывание параметров сменного задания */ + procedure FCJOBS_PARAMS_GET + ( + NFCJOBS in number, -- Рег. номер сменного задания + NSUBDIV out number, -- Рег. номер подразделения + DDOC_DATE out date -- Дата сменного задания + ) + is + begin + /* Считываем параметры сменного задания */ + begin + select T.SUBDIV, + T.DOCDATE + into NSUBDIV, + DDOC_DATE + from FCJOBS T + where T.RN = NFCJOBS; + exception + when others then + P_EXCEPTION(0, 'Ошибка считывания сменного задания.'); + end; + end FCJOBS_PARAMS_GET; + begin + /* Читем сортировки */ + RO := PKG_P8PANELS_VISUAL.TDG_ORDERS_FROM_XML(CORDERS => CORDERS); + /* Преобразуем номер и размер страницы в номер строк с и по */ + PKG_P8PANELS_VISUAL.UTL_ROWS_LIMITS_CALC(NPAGE_NUMBER => NPAGE_NUMBER, + NPAGE_SIZE => NPAGE_SIZE, + NROW_FROM => NROW_FROM, + NROW_TO => NROW_TO); + /* Инициализируем таблицу данных */ + RDG := PKG_P8PANELS_VISUAL.TDG_MAKE(BFIXED_HEADER => true, NFIXED_COLUMNS => 4); + /* Описываем колонки таблицы данных */ + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NRN', + SCAPTION => 'Рег. номер', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BVISIBLE => false); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NSELECT', + SCAPTION => 'Выбран', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SFIO', + SCAPTION => 'ФИО', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'SPROFESSION', + SCAPTION => 'Профессия', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NSUM_LABOUR', + SCAPTION => 'Загрузка в н/ч', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NLOADING', + SCAPTION => 'Загрузка в %', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BORDER => true); + PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG, + SNAME => 'NEQUIPMENT', + SCAPTION => 'Рег. номер оборудования', + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, + BVISIBLE => false); + /* Считываем единицу измерения минут */ + FIND_DICMUNTS_CODE(NFLAG_SMART => 0, + NFLAG_OPTION => 0, + NCOMPANY => NCOMPANY, + SMEAS_MNEMO => SDICMUNTS_MIN, + NRN => NDICMUNTS_MIN); + /* Считываем единицу измерения минут */ + FIND_DICMUNTS_CODE(NFLAG_SMART => 0, + NFLAG_OPTION => 0, + NCOMPANY => NCOMPANY, + SMEAS_MNEMO => SDICMUNTS_WD, + NRN => NDICMUNTS_WD); + /* Считываем параметры сменного задания */ + FCJOBS_PARAMS_GET(NFCJOBS => NFCJOBS, NSUBDIV => NSUBDIV, DDOC_DATE => DDOC_DATE); + /* Если подразделение считано */ + if (NSUBDIV is not null) then + /* Обходим данные */ + begin + /* Добавляем подсказку совместимости */ + CSQL := PKG_SQL_BUILD.COMPATIBLE(SSQL => CSQL); + /* Формируем запрос */ + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => 'select *'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select D.*,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.SQLROWNUM() || ' NROW'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select C.RN NRN,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' (select AG.AGNFAMILYNAME||'' ''||AG.AGNFIRSTNAME||'' ''||AG.AGNLASTNAME from AGNLIST AG where AG.RN = PR.PERS_AGENT) SFIO,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' D.PSDEP_CODE SPROFESSION'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from SUBDIVSMP T,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' CLNPSDEP D,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' CLNPSPFM C,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' CLNPSPFMTYPES CT,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' CLNPERSONS PR'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where T.PRN = :NSUBDIV'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and T.CLNPSDEP is not null'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and exists (select null'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from SUBDIVSMPFC F,'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' ENPERIOD E'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where F.PRN = T.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and E.RN = F.PERIOD'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and E.STARTDATE <= :DDOC_DATE'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and E.ENDDATE >= :DDOC_DATE'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' ' || PKG_SQL_BUILD.ROWLIMIT(NLIMIT => 1, BAND => true) || ')'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and D.RN = T.CLNPSDEP'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.PSDEPRN = D.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.BEGENG <= :DDOC_DATE'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and (C.ENDENG >= :DDOC_DATE or C.ENDENG is null)'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.CLNPSPFMTYPES = CT.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and CT.IS_PRIMARY = ' || PKG_SQL_BUILD.WRAP_NUM(NVALUE => 1)); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.PERSRN = PR.RN'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' %ORDER_BY%) D) F'); + PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where F.NROW between :NROW_FROM and :NROW_TO'); + /* Учтём сортировки */ + PKG_P8PANELS_VISUAL.TDG_ORDERS_SET_QUERY(RDATA_GRID => RDG, + RORDERS => RO, + SPATTERN => '%ORDER_BY%', + CSQL => CSQL); + /* Разбираем его */ + ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); + PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => CSQL); + /* Делаем подстановку параметров */ + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NSUBDIV', NVALUE => NSUBDIV); + PKG_SQL_DML.BIND_VARIABLE_DATE(ICURSOR => ICURSOR, SNAME => 'DDOC_DATE', DVALUE => DDOC_DATE); + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_FROM', NVALUE => NROW_FROM); + PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_TO', NVALUE => NROW_TO); + /* Описываем структуру записи курсора */ + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 1); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 2); + PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 3); + PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 4); + /* Делаем выборку */ + if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then + null; + end if; + /* Обходим выбранные записи */ + while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0) + loop + /* Читаем данные из курсора рег. номер исполнения */ + PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => 1, NVALUE => NCLNPSPFM); + /* Обнуляем сумму рабочего времени и трудоемкости */ + NSUM_LABOUR := 0; + NSUM_WORK_TIME := 0; + /* Цикл по различным сменам данного оборудования */ + for REC in (select TMP.TBOPERMODESP, + sum(TMP.NLABOUR) NLABOUR + from (select COALESCE(T.TBOPERMODESP, J.TBOPERMODESP) TBOPERMODESP, + F_DICMUNTS_BASE_RECALC_QUANT(0, T.COMPANY, T.MUNIT, T.LABOUR_PLAN, NDICMUNTS_MIN) NLABOUR + from FCJOBS J, + FCJOBSSP T + where J.RN = NFCJOBS + and T.PRN = J.RN + and T.PERFORM_FACT = NCLNPSPFM + union all + select COALESCE(TS.TBOPERMODESP, JS.TBOPERMODESP), + F_DICMUNTS_BASE_RECALC_QUANT(0, RS.COMPANY, RS.MUNIT, RS.LABOUR_PLAN, NDICMUNTS_MIN) + from FCJOBS JS, + FCJOBSSP TS, + FCJOBSSPAR RS + where JS.RN = NFCJOBS + and TS.PRN = JS.RN + and RS.PRN = TS.RN + and RS.PERFORM_FACT = NCLNPSPFM) TMP + group by TMP.TBOPERMODESP) + loop + /* Рассчитываем суммы */ + NSUM_LABOUR := NSUM_LABOUR + REC.NLABOUR; + NSUM_WORK_TIME := NSUM_WORK_TIME + UTL_WORK_TIME_GET(NTBOPERMODESP => REC.TBOPERMODESP); + end loop; + /* Если оборудование не участвует в сменном задании */ + if (NSUM_WORK_TIME = 0) then + NLOADING := 0; + else + NLOADING := ROUND(NSUM_LABOUR / NSUM_WORK_TIME * 100, 0); + /* Если трудоемкость не равна 0 */ + if (NSUM_LABOUR <> 0) then + /* Переводим суммарную трудоемкость в нормочасы */ + NSUM_LABOUR := ROUND(F_DICMUNTS_BASE_RECALC_QUANT(0, NCOMPANY, NDICMUNTS_MIN, NSUM_LABOUR, NDICMUNTS_WD), + 2); + end if; + end if; + /* Добавляем колонки с данными */ + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => NCLNPSPFM, BCLEAR => true); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSELECT', NVALUE => 0); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSUM_LABOUR', NVALUE => NSUM_LABOUR); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, + SNAME => 'SFIO', + ICURSOR => ICURSOR, + NPOSITION => 2); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NLOADING', NVALUE => NLOADING); + PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, + SNAME => 'SPROFESSION', + ICURSOR => ICURSOR, + NPOSITION => 3); + /* Добавляем строку в таблицу */ + PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); + end loop; + exception + when others then + PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); + raise; + end; + end if; + /* Сериализуем описание */ + COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => NINCLUDE_DEF); + end WORKERS_MP_DG_GET; + + /* Инициализация записей раздела "Планы и отчеты производства изделий" */ + procedure FCJOBS_MP_INIT + ( + NFCJOBS in number, -- Рег. номер записи сменного задания + COUT out clob -- Информация о записи сменного задания + ) + is + NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса + NVERSION PKG_STD.TREF; -- Версия контрагентов + SDOC_INFO PKG_STD.TSTRING; -- Информация о документе + + /* Проверка доступности действия над выбранным сменным заданием */ + procedure ACTION_AVAILABLE + ( + NFCJOBS in number -- Рег. номер записи сменного задания + ) + is + NAVAILABLE PKG_STD.TNUMBER; -- Признак доступности действия (0 - нет, 1 - да) + begin + /* Если "Состояние" <> "Не отработано" и дата документа < текущей даты - действие недоступно */ + begin + select 0 + into NAVAILABLE + from FCJOBS T + where T.RN = NFCJOBS + and ((T.STATE <> 0) or (T.DOCDATE < TRUNC(sysdate))); + exception + when others then + /* Действие доступно */ + NAVAILABLE := 1; + end; + /* Если действие недоступно - выводим ошибку */ + if (NAVAILABLE = 0) then + P_EXCEPTION(0, + 'Действие "Выдача сменного задания на участок" недоступно для сменного задания с состоянием отличным от "Не отработано" или датой документа ранее текущей даты.'); + end if; + end ACTION_AVAILABLE; + begin + /* Проверяем доступность действия */ + ACTION_AVAILABLE(NFCJOBS => NFCJOBS); + /* Считываем версию контрагентов */ + FIND_VERSION_BY_COMPANY(NCOMPANY => NCOMPANY, SUNITCODE => 'AGNLIST', NVERSION => NVERSION); + /* Начинаем формирование XML */ + PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_); + /* Открываем корень */ + PKG_XFAST.DOWN_NODE(SNAME => 'XDATA'); + /* Цикл по планам и отчетам производства изделий */ + for REC in (select T.RN NRN, + trim(T.DOCNUMB) SDOC_NUMB, + DT.DOCCODE || ', ' || trim(T.DOCPREF) || '-' || trim(T.DOCNUMB) || ', ' || + TO_CHAR(T.DOCDATE, 'dd.mm.yyyy') SDOC_INFO, + INS.NAME SSUBDIV, + case + when PER.RN is not null then + TO_CHAR(T.DOCDATE, 'dd.mm.yyyy') || ' ' || TN2S(PER.BEG_TIME) || ' - ' || TN2S(PER.END_TIME) + else + TO_CHAR(T.DOCDATE, 'dd.mm.yyyy') + end SPERIOD, + (select trim(T2.NUMB) from TBOPERMODESP T2 where T.TBOPERMODESP = T2.RN) STBOPERMODESP, + (select 1 + from FCJOBSSP S + where S.PRN = T.RN + and S.NOTE is not null + and ROWNUM = 1) NHAVE_NOTE + from FCJOBS T, + DOCTYPES DT, + INS_DEPARTMENT INS, + TBOPERMODESP PER + where T.RN = NFCJOBS + and DT.RN = T.DOCTYPE + and T.SUBDIV = INS.RN(+) + and T.TBOPERMODESP = PER.RN(+) + order by SDOC_INFO) + loop + /* Если указана смена */ + if (REC.STBOPERMODESP is not null) then + /* Указываем информацию документа со сменой */ + SDOC_INFO := REC.SDOC_INFO || ', смена ' || REC.STBOPERMODESP; + else + /* Указываем информацию документа без смены */ + SDOC_INFO := REC.SDOC_INFO; + end if; + /* Открываем план */ + PKG_XFAST.DOWN_NODE(SNAME => 'XFCJOBS'); + /* Описываем план */ + PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => REC.NRN); + PKG_XFAST.ATTR(SNAME => 'SDOC_INFO', SVALUE => SDOC_INFO); + PKG_XFAST.ATTR(SNAME => 'SDOC_NUMB', SVALUE => REC.SDOC_NUMB); + PKG_XFAST.ATTR(SNAME => 'SSUBDIV', SVALUE => REC.SSUBDIV); + PKG_XFAST.ATTR(SNAME => 'SPERIOD', SVALUE => REC.SPERIOD); + PKG_XFAST.ATTR(SNAME => 'NHAVE_NOTE', NVALUE => COALESCE(REC.NHAVE_NOTE, 0)); + /* Закрываем план */ + PKG_XFAST.UP(); + end loop; + /* Закрываем корень */ + PKG_XFAST.UP(); + /* Сериализуем */ + COUT := PKG_XFAST.SERIALIZE_TO_CLOB(); + /* Завершаем формирование XML */ + PKG_XFAST.EPILOGUE(); + exception + when others then + /* Завершаем формирование XML */ + PKG_XFAST.EPILOGUE(); + /* Вернем ошибку */ + PKG_STATE.DIAGNOSTICS_STACKED(); + P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); + end FCJOBS_MP_INIT; end PKG_P8PANELS_MECHREC; / diff --git a/p8panels.config b/p8panels.config index 2f6647b..2a1970b 100644 --- a/p8panels.config +++ b/p8panels.config @@ -109,6 +109,16 @@ icon="psychology" showInPanelsList="true" preview="./img/mech_rec_cost_jobs_manage.jpg"/> +