ЦИТК-784 - Добавление панели "Производственная программа"

This commit is contained in:
Mikhail Chechnev 2024-02-07 18:23:20 +03:00 committed by GitHub
commit fd6e38dbcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1110 additions and 84 deletions

View File

@ -59,7 +59,8 @@ const P8P_GANTT_TASK_SHAPE = PropTypes.shape({
readOnlyDates: PropTypes.bool,
readOnlyProgress: PropTypes.bool,
bgColor: PropTypes.string,
textColor: PropTypes.string
textColor: PropTypes.string,
bgProgressColor: PropTypes.string
});
//Структура динамического атрибута задачи
@ -72,6 +73,7 @@ const P8P_GANTT_TASK_ATTRIBUTE_SHAPE = PropTypes.shape({
const P8P_GANTT_TASK_COLOR_SHAPE = PropTypes.shape({
bgColor: PropTypes.string,
textColor: PropTypes.string,
bgProgressColor: PropTypes.string,
desc: PropTypes.string.isRequired
});
@ -126,14 +128,24 @@ const P8PGanttTaskEditor = ({
//Описание легенды для задачи
let legend = null;
if (Array.isArray(taskColors)) {
const colorDesc = taskColors.find(color => task.bgColor === color.bgColor && task.textColor === color.textColor);
const colorDesc = taskColors.find(
color => task.bgColor === color.bgColor && task.textColor === color.textColor && task.bgProgressColor === color.bgProgressColor
);
if (colorDesc)
legend = (
<ListItemText
secondaryTypographyProps={{
p: 1,
sx: {
...(colorDesc.bgColor ? { backgroundColor: colorDesc.bgColor } : {}),
...(colorDesc.bgProgressColor
? {
background: `linear-gradient(to right, ${colorDesc.bgProgressColor} ,${
colorDesc.bgColor ? colorDesc.bgColor : "transparent"
})}`
}
: colorDesc.bgColor
? { backgroundColor: colorDesc.bgColor }
: {}),
...(colorDesc.textColor ? { color: colorDesc.textColor } : {})
}
}}

View File

@ -0,0 +1,9 @@
import React from "react";
export const useFilteredPlans = (plans, filter) => {
const filteredPlans = React.useMemo(() => {
return plans.filter(project => project.SDOC_INFO.toLowerCase().includes(filter));
}, [plans, filter]);
return filteredPlans;
};

View File

@ -0,0 +1,16 @@
/*
Парус 8 - Панели мониторинга - ПУП - Производственная программа
Панель мониторинга: Точка входа
*/
//---------------------
//Подключение библиотек
//---------------------
import { MechRecCostProdPlans } from "./mech_rec_cost_prod_plans"; //Корневая панель производственной программы
//----------------
//Интерфейс модуля
//----------------
export const RootClass = MechRecCostProdPlans;

View File

@ -0,0 +1,332 @@
/*
Парус 8 - Панели мониторинга - ПУП - Производственная программа
Панель мониторинга: Корневая панель производственной программы
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Drawer, Fab, Box, List, ListItemButton, ListItemText, Typography, Grid, TextField, Select, MenuItem, InputLabel } from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { P8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта
import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции
import { useFilteredPlans } from "./hooks"; //Вспомогательные хуки
import { XMLParser } from "fast-xml-parser";
//---------
//Константы
//---------
//Высота диаграммы Ганта
const GANTT_HEIGHT = "650px";
//Ширина диаграммы Ганта
const GANTT_WIDTH = "98vw";
//Стили
const STYLES = {
PROJECTS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
PROJECTS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
PROJECTS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.5rem", textTransform: "uppercase" },
PROJECTS_LIST_ITEM_SECONDARY_NOJOBS: { color: "red" },
PROJECTS_LIST_ITEM_SECONDARY_NOEDIT: { color: "gray" },
PROJECTS_LIST_ITEM_SECONDARY_CHANGED: { color: "green" },
PROJECTS_BUTTON: { position: "absolute" },
PROJECTS_DRAWER: {
minWidth: "250px",
display: "inline-block",
flexShrink: 0,
[`& .MuiDrawer-paper`]: { minWidth: "250px", display: "inline-block", boxSizing: "border-box" }
},
GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH },
GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" },
PERIODS_BUTTON: { position: "absolute", right: "20px" },
PERIODS_DRAWER: { width: "1000px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "1000px", boxSizing: "border-box" } }
};
//Список проектов
const ProjectsList = ({ plans = [], selectedPlan, filter, setFilter, onClick } = {}) => {
//Генерация содержимого
return (
<div>
<TextField
sx={STYLES.PROJECTS_FINDER}
name="planFilter"
label="План"
value={filter}
variant="standard"
fullWidth
onChange={event => {
setFilter(event.target.value);
}}
></TextField>
<List>
{plans.map(p => (
<ListItemButton key={p.NRN} selected={p.NRN === selectedPlan} onClick={() => (onClick ? onClick(p) : null)}>
<ListItemText
primary={<Typography sx={STYLES.PROJECTS_LIST_ITEM_PRIMARY}>{p.SDOC_INFO}</Typography>}
secondary={
<Typography
sx={{
...STYLES.PROJECTS_LIST_ITEM_SECONDARY,
...(p.NJOBS == 0
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOJOBS
: p.NCHANGED == 1
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_CHANGED
: STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOEDIT)
}}
></Typography>
}
/>
</ListItemButton>
))}
</List>
</div>
);
};
//Контроль свойств - Список проектов
ProjectsList.propTypes = {
plans: PropTypes.array,
selectedPlan: PropTypes.number,
onClick: PropTypes.func,
filter: PropTypes.string,
setFilter: PropTypes.func
};
//-----------
//Тело модуля
//-----------
//Разбор XML
const parseXML = (xmlDoc, attributeValueProcessor) => {
return new Promise((resolve, reject) => {
try {
let opts = {
ignoreDeclaration: true,
ignoreAttributes: false,
parseAttributeValue: true,
attributeNamePrefix: ""
};
if (attributeValueProcessor) opts.attributeValueProcessor = attributeValueProcessor;
const parser = new XMLParser(opts);
const data = parser.parse(xmlDoc);
resolve(data.XDATA);
} catch (e) {
reject(e);
}
});
};
//Корневая панель производственной программы
const MechRecCostProdPlans = () => {
//Собственное состояние
let [state, setState] = useState({
init: false,
showPlanList: false,
plans: [],
plansLoaded: false,
selectedPlanSpecsLoaded: false,
selectedPlan: null,
selectedPlanMaxLevel: null,
selectedPlanLevel: null,
selectedPlanMenuItems: null,
selectedPlanGanttDef: {},
selectedPlanSpecs: []
});
const [filter, setFilter] = useState("");
const filteredPlans = useFilteredPlans(state.plans, filter);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
// Инициализация планов
const initPlans = useCallback(async () => {
if (!state.init) {
const data = await executeStored({
stored: "PKG_P8PANELS_MECHREC.PRODPLAN_INIT",
args: {},
respArg: "COUT"
});
setState(pv => ({
...pv,
init: true,
plans: [...(data?.XFCPRODPLANS || [])],
plansLoaded: true
}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state.init, executeStored]);
//Выбор плана
const selectPlan = project => {
setState(pv => ({
...pv,
selectedPlan: project,
selectedPlanSpecsLoaded: false,
selectedPlanMaxLevel: null,
selectedPlanLevel: null,
selectedPlanMenuItems: null,
selectedPlanSpecs: [],
selectedPlanGanttDef: {},
showPlanList: false
}));
};
//Сброс выбора плана
const unselectPlan = () =>
setState(pv => ({
...pv,
selectedPlanSpecsLoaded: false,
selectedPlan: null,
selectedPlanMaxLevel: null,
selectedPlanLevel: null,
selectedPlanMenuItems: null,
selectedPlanSpecs: [],
selectedPlanGanttDef: {},
showPlanList: false
}));
//Загрузка списка спецификаций плана
const loadPlanSpecs = useCallback(
async (level = null) => {
const data = await executeStored({
stored: "PKG_P8PANELS_MECHREC.FCPRODPLANSP_GET",
args: { NFCPRODPLAN: state.selectedPlan, NLEVEL: level }
});
let doc = await parseXML(data.COUT, (name, val) =>
name == "numb" ? undefined : ["start", "end"].includes(name) ? formatDateJSONDateOnly(val) : val
);
console.log(doc.XGANTT_DEF);
console.log(doc.XGANTT_TASKS);
setState(pv => ({
...pv,
selectedPlanMaxLevel: data.NMAX_LEVEL,
selectedPlanLevel: level || level === 0 ? level : data.NMAX_LEVEL,
selectedPlanMenuItems: state.selectedPlanMenuItems
? state.selectedPlanMenuItems
: [...Array(data.NMAX_LEVEL).keys()].map(el => el + 1),
selectedPlanSpecsLoaded: true,
selectedPlanGanttDef: doc.XGANTT_DEF ? { ...doc.XGANTT_DEF } : {},
selectedPlanSpecs: [...(doc?.XGANTT_TASKS || [])]
}));
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[executeStored, state.ident, state.selectedPlan]
);
//Обработка нажатия на элемент в списке планов
const handleProjectClick = project => {
if (state.selectedPlan != project.NRN) selectPlan(project.NRN);
else unselectPlan();
};
//Отработка нажатия на заголовок плана
const handleTitleClick = () => {
state.selectedPlan ? pOnlineShowDocument({ unitCode: "CostProductPlans", document: state.selectedPlan }) : null;
};
//При подключении компонента к странице
useEffect(() => {
initPlans();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//При смене выбранного плана
useEffect(() => {
if (state.selectedPlan) loadPlanSpecs();
}, [state.selectedPlan, loadPlanSpecs]);
//Выбор уровня
const handleChangeSelectList = selectedLevel => {
loadPlanSpecs(selectedLevel);
setState(pv => ({ ...pv, selectedPlanLevel: selectedLevel }));
};
//Генерация содержимого
return (
<Box p={2}>
<Fab variant="extended" sx={STYLES.PROJECTS_BUTTON} onClick={() => setState(pv => ({ ...pv, showPlanList: !pv.showPlanList }))}>
Планы
</Fab>
<Drawer
anchor={"left"}
open={state.showPlanList}
onClose={() => setState(pv => ({ ...pv, showPlanList: false }))}
sx={STYLES.PROJECTS_DRAWER}
>
<ProjectsList
plans={filteredPlans}
selectedPlan={state.selectedPlan}
filter={filter}
setFilter={setFilter}
onClick={handleProjectClick}
/>
</Drawer>
{state.init == true ? (
<Grid container spacing={1}>
<Grid item xs={12}>
{state.selectedPlanSpecsLoaded ? (
state.selectedPlanSpecs.length === 0 ? (
<InlineMsgInfo okBtn={false} text={"В плане отсутствуют записи спецификации"} />
) : (
<Box sx={STYLES.GANTT_CONTAINER} p={1}>
{state.selectedPlanMaxLevel ? (
<Box sx={{ float: "right" }}>
<InputLabel id="demo-simple-select-label">Уровень</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={state.selectedPlanLevel}
label="Уровень"
onChange={event => {
handleChangeSelectList(event.target.value);
}}
defaultValue={state.selectedPlanLevel}
>
{state.selectedPlanMenuItems.map(el => (
<MenuItem value={el} key={el}>
{el}
</MenuItem>
))}
</Select>
</Box>
) : null}
<P8PGantt
{...P8P_GANTT_CONFIG_PROPS}
{...state.selectedPlanGanttDef}
height={GANTT_HEIGHT}
onTitleClick={handleTitleClick}
titleStyle={STYLES.GANTT_TITLE}
tasks={state.selectedPlanSpecs}
/>
</Box>
)
) : !state.selectedPlan ? (
<InlineMsgInfo okBtn={false} text={"Укажите план для отображения его спецификации"} />
) : null}
</Grid>
</Grid>
) : null}
</Box>
);
};
//----------------
//Интерфейс модуля
//----------------
export { MechRecCostProdPlans };

426
db/PKG_P8PANELS_MECHREC.pck Normal file
View File

@ -0,0 +1,426 @@
create or replace package PKG_P8PANELS_MECHREC as
/* Получение списка спецификаций планов и отчетов производства изделий для диаграммы Ганта */
procedure FCPRODPLANSP_GET
(
NFCPRODPLAN in number, -- Рег. номер родителя
NLEVEL in number := null, -- Уровень отбора
COUT out clob, -- Список проектов
NMAX_LEVEL out number -- Максимальный уровень иерархии
);
/* Инициализация планов и отчетов производства изделий */
procedure PRODPLAN_INIT
(
COUT out clob -- Список планов и отчетов производства изделий
);
end PKG_P8PANELS_MECHREC;
/
create or replace package body PKG_P8PANELS_MECHREC as
/* Константы - цвета отображения */
SBG_COLOR_RED constant PKG_STD.TSTRING := 'red'; -- Цвет заливки красный (Дефицит запуска != 0)
SBG_COLOR_YELLOW constant PKG_STD.TSTRING := '#e0db44'; -- Цвет заливки желтый (Дефицит» запуска = 0 и Выпуск факт = 0)
SBG_COLOR_GREEN constant PKG_STD.TSTRING := 'lightgreen'; -- Цвет заливки зеленый (Дефицит выпуска = 0)
SBG_COLOR_BLACK constant PKG_STD.TSTRING := 'black'; -- Цвет заливки черный (Нет дат и связей)
STEXT_COLOR_ORANGE constant PKG_STD.TSTRING := '#FF8C00'; -- Цвет текста для черной заливки (оранжевый)
/* Константы - параметры отборов планов */
NFCPRODPLAN_CATEGORY constant PKG_STD.TNUMBER := 1; -- Категория планов "Производственная программа"
NFCPRODPLAN_STATUS constant PKG_STD.TNUMBER := 2; -- Статус планов "Утвержден"
SFCPRODPLAN_TYPE constant PKG_STD.TSTRING := 'План'; -- Тип планов (мнемокод состояния)
/* Константы - дополнительные атрибуты */
STASK_ATTR_DEFRESLIZ constant PKG_STD.TSTRING := 'defresliz'; -- Дефицит запуска
STASK_ATTR_REL_FACT constant PKG_STD.TSTRING := 'rel_fact'; -- Выпуск факт
STASK_ATTR_DEFSTART constant PKG_STD.TSTRING := 'defstart'; -- Дефицит выпуска
STASK_ATTR_LEVEL constant PKG_STD.TSTRING := 'level'; -- Уровень
/* Формирование характеристик спецификации в Ганте */
procedure MAKE_GANT_ITEM
(
NDEFRESLIZ in number, -- Дефицит запуска
NREL_FACT in number, -- Выпуск факт
NDEFSTART in number, -- Дефицит выпуска
STASK_BG_COLOR out varchar2, -- Цвет заливки спецификации
STASK_BG_PROGRESS_COLOR out varchar2, -- Цвет заливки прогресса спецификации
NTASK_PROGRESS out number -- Прогресс спецификации
)
is
begin
/* Если дефицит запуска <> 0 */
if (NDEFRESLIZ <> 0) then
/* Полностью красный */
STASK_BG_COLOR := SBG_COLOR_RED;
STASK_BG_PROGRESS_COLOR := null;
NTASK_PROGRESS := null;
else
/* Если дефицит выпуска = 0 */
if (NDEFSTART = 0) then
/* Полностью зеленый */
STASK_BG_COLOR := SBG_COLOR_GREEN;
STASK_BG_PROGRESS_COLOR := null;
NTASK_PROGRESS := null;
else
/* Если дефицит запуска = 0 и выпуск факт = 0 */
if ((NDEFRESLIZ = 0) and (NREL_FACT = 0)) then
/* Полностью жёлтый */
STASK_BG_COLOR := SBG_COLOR_YELLOW;
STASK_BG_PROGRESS_COLOR := null;
NTASK_PROGRESS := null;
end if;
/* Если дефицит запуска = 0 и выпуск факт <> 0 */
if ((NDEFRESLIZ = 0) and (NREL_FACT <> 0)) then
/* Частично зелёный, прогресс жёлтый */
STASK_BG_COLOR := SBG_COLOR_GREEN;
STASK_BG_PROGRESS_COLOR := SBG_COLOR_YELLOW;
NTASK_PROGRESS := 50;
end if;
end if;
end if;
end MAKE_GANT_ITEM;
/* Считывание заголовка документа */
function TITLE_GET
(
NRN in number -- Рег. номер плана и отчета производства изделий
) return varchar2 -- Заголовок для отображения
is
SRESULT PKG_STD.TSTRING; -- Заголовок для отображения
SDOC_INFO PKG_STD.TSTRING; -- Информация о документе
SJURPERSONS_CODE PKG_STD.TSTRING; -- Мнемокод принадлежности
SINS_DEPARTMENT_CODE PKG_STD.TSTRING; -- Мнемокод подразделения
begin
/* Считываем информацию из плана */
begin
select D.DOCCODE || ', ' || trim(T.PREFIX) || '/' || trim(T.NUMB) || ', от ' || TO_CHAR(T.DOCDATE, 'dd.mm.yyyy') DOC_INFO,
J.CODE,
SD.CODE
into SDOC_INFO,
SJURPERSONS_CODE,
SINS_DEPARTMENT_CODE
from FCPRODPLAN T,
DOCTYPES D,
JURPERSONS J,
INS_DEPARTMENT SD
where T.RN = NRN
and D.RN = T.DOCTYPE
and J.RN = T.JUR_PERS
and SD.RN = T.SUBDIV;
exception
when others then
return 'Нет информации.';
end;
/* Формируем заголовок */
SRESULT := 'План и отчет производства изделия "' || SDOC_INFO || '", принадлежность "' || SJURPERSONS_CODE ||
'", подразделение "' || SINS_DEPARTMENT_CODE || '"';
/* Возвращаем результат */
return SRESULT;
end TITLE_GET;
/* Считывание максимального уровня иерархии плана */
function PRODPLAN_MAX_LEVEL_GET
(
NPRODPLAN in number -- Рег. номер плана
) return number -- Максимальный уровень иерархии
is
NRESULT PKG_STD.TNUMBER; -- Максимальный уровень иерархии
begin
/* Считываем максимальный уровень */
begin
select max(level)
into NRESULT
from (select T.RN,
T.UP_LEVEL
from FCPRODPLANSP T
where T.PRN = NPRODPLAN) TMP
connect by prior TMP.RN = TMP.UP_LEVEL
start with TMP.UP_LEVEL is null;
exception
when others then
NRESULT := null;
end;
/* Возвращаем результат */
return NRESULT;
end PRODPLAN_MAX_LEVEL_GET;
/* Определение дат спецификации плана */
procedure FCPRODPLANSP_DATES_GET
(
DREP_DATE in date, -- Дата запуска спецификации
DREP_DATE_TO in date, -- Дата выпуска спецификации
DINCL_DATE in date, -- Дата включения в план спецификации
NHAVE_LINK in number := 0, -- Наличие связей с "Маршрутный лист" или "Приход из подразделения"
DDATE_FROM out date, -- Итоговая дата запуска спецификации
DDATE_TO out date, -- Итоговая дата выпуска спецификации
STASK_BG_COLOR out varchar2, -- Цвет элемента (черный, если даты не заданы и нет связи, иначе null)
STASK_TEXT_COLOR out varchar2, -- Цвет текста элемента (хаки, если даты не заданы и нет связи, иначе null)
NTASK_PROGRESS out number -- Прогресс элемента (проинициализирует null, если даты не заданы и нет связи)
)
is
begin
/* Проициниализируем цвет и прогресс */
STASK_BG_COLOR := null;
NTASK_PROGRESS := null;
STASK_TEXT_COLOR := null;
/* Если даты запуска и выпуска пусты */
if ((DREP_DATE is null) and (DREP_DATE_TO is null)) then
/* Указываем дату включения в план */
DDATE_FROM := DINCL_DATE;
DDATE_TO := DINCL_DATE;
else
/* Указываем даты исходя из дат запуска/выпуска */
DDATE_FROM := COALESCE(DREP_DATE, DREP_DATE_TO);
DDATE_TO := COALESCE(DREP_DATE_TO, DREP_DATE);
end if;
/* Если одна из дат не указана */
if ((DREP_DATE is null) or (DREP_DATE_TO is null)) then
/* Если спецификация также не имеет связей */
if (NHAVE_LINK = 0) then
/* Закрашиваем в черный */
STASK_BG_COLOR := SBG_COLOR_BLACK;
STASK_TEXT_COLOR := STEXT_COLOR_ORANGE;
NTASK_PROGRESS := null;
end if;
end if;
end FCPRODPLANSP_DATES_GET;
/* Получение списка спецификаций планов и отчетов производства изделий для диаграммы Ганта */
procedure FCPRODPLANSP_GET
(
NFCPRODPLAN in number, -- Рег. номер родителя
NLEVEL in number := null, -- Уровень отбора
COUT out clob, -- Список проектов
NMAX_LEVEL out number -- Максимальный уровень иерархии
)
is
/* Переменные */
RG PKG_P8PANELS_VISUAL.TGANTT; -- Описание диаграммы Ганта
RGT PKG_P8PANELS_VISUAL.TGANTT_TASK; -- Описание задачи для диаграммы
BREAD_ONLY_DATES boolean := false; -- Флаг доступности дат проекта только для чтения
STASK_BG_COLOR PKG_STD.TSTRING; -- Цвет заливки задачи
STASK_TEXT_COLOR PKG_STD.TSTRING; -- Цвет текста задачи
STASK_BG_PROGRESS_COLOR PKG_STD.TSTRING; -- Цвет заливки прогресса задачи
NTASK_PROGRESS PKG_STD.TNUMBER; -- Прогресс выполнения задачи
DDATE_FROM PKG_STD.TLDATE; -- Дата запуска спецификации
DDATE_TO PKG_STD.TLDATE; -- Дата выпуска спецификации
begin
/* Инициализируем диаграмму Ганта */
RG := PKG_P8PANELS_VISUAL.TGANTT_MAKE(STITLE => TITLE_GET(NRN => NFCPRODPLAN),
NZOOM => PKG_P8PANELS_VISUAL.NGANTT_ZOOM_DAY,
BREAD_ONLY_DATES => BREAD_ONLY_DATES,
BREAD_ONLY_PROGRESS => true);
/* Добавим динамические атрибуты к спецификациям */
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_ATTR(RGANTT => RG,
SNAME => STASK_ATTR_DEFRESLIZ,
SCAPTION => 'Дефицит запуска');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_ATTR(RGANTT => RG,
SNAME => STASK_ATTR_REL_FACT,
SCAPTION => 'Выпуск факт');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_ATTR(RGANTT => RG,
SNAME => STASK_ATTR_DEFSTART,
SCAPTION => 'Дефицит выпуска');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_ATTR(RGANTT => RG, SNAME => STASK_ATTR_LEVEL, SCAPTION => 'Уровень');
/* Добавим описание цветов */
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_COLOR(RGANTT => RG,
SBG_COLOR => SBG_COLOR_RED,
SDESC => 'Для спецификаций планов и отчетов производства изделий с «Дефицит запуска» != 0.');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_COLOR(RGANTT => RG,
SBG_COLOR => SBG_COLOR_YELLOW,
SDESC => 'Для спецификаций планов и отчетов производства изделий с «Дефицит запуска» = 0 и «Выпуск факт» = 0.');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_COLOR(RGANTT => RG,
SBG_COLOR => SBG_COLOR_GREEN,
SDESC => 'Для спецификаций планов и отчетов производства изделий с «Дефицит выпуска» = 0.');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_COLOR(RGANTT => RG,
SBG_COLOR => SBG_COLOR_GREEN,
SBG_PROGRESS_COLOR => SBG_COLOR_YELLOW,
SDESC => 'Для спецификаций планов и отчетов производства изделий с «Дефицит запуска» = 0 и «Выпуск факт» != 0. ');
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK_COLOR(RGANTT => RG,
SBG_COLOR => SBG_COLOR_BLACK,
STEXT_COLOR => STEXT_COLOR_ORANGE,
SDESC => 'Для спецификаций планов и отчетов производства изделий с пустыми «Дата запуска» и «Дата выпуска» и не имеющих связей с разделами «Маршрутный лист» или «Приход из подразделения».');
/* Определяем максимальный уровень иерархии */
NMAX_LEVEL := PRODPLAN_MAX_LEVEL_GET(NPRODPLAN => NFCPRODPLAN);
/* Цикл по спецификации плана с учетом иерархии */
for REC in (select TMP.*,
level
from (select T.RN,
T.REP_DATE,
T.REP_DATE_TO,
T.INCL_DATE,
T.ROUTE,
D.NOMEN_NAME,
(T.QUANT_REST - T.START_FACT) DEFRESLIZ,
T.REL_FACT,
(T.MAIN_QUANT - T.REL_FACT) DEFSTART,
(select 1
from DUAL
where exists
(select null
from DOCLINKS L
where L.IN_DOCUMENT = T.RN
and L.IN_UNITCODE = 'CostProductPlansSpecs'
and (L.OUT_UNITCODE = 'CostRouteLists' or L.OUT_UNITCODE = 'IncomFromDeps')
and ROWNUM = 1)) HAVE_LINK,
T.UP_LEVEL
from FCPRODPLANSP T,
FCMATRESOURCE FM,
DICNOMNS D
where T.PRN = NFCPRODPLAN
and ((T.REP_DATE is not null) or (T.REP_DATE_TO is not null) or (T.INCL_DATE is not null))
and FM.RN = T.MATRES
and D.RN = FM.NOMENCLATURE) TMP
where ((NLEVEL is null) or ((NLEVEL is not null) and (level <= NLEVEL)))
connect by prior TMP.RN = TMP.UP_LEVEL
start with TMP.UP_LEVEL is null)
loop
/* Инициализируем даты и цвет (если необходимо) */
FCPRODPLANSP_DATES_GET(DREP_DATE => REC.REP_DATE,
DREP_DATE_TO => REC.REP_DATE_TO,
DINCL_DATE => REC.INCL_DATE,
NHAVE_LINK => COALESCE(REC.HAVE_LINK, 0),
DDATE_FROM => DDATE_FROM,
DDATE_TO => DDATE_TO,
STASK_BG_COLOR => STASK_BG_COLOR,
STASK_TEXT_COLOR => STASK_TEXT_COLOR,
NTASK_PROGRESS => NTASK_PROGRESS);
/* Если цвет изначально не указан и требуется анализирование */
if (STASK_BG_COLOR is null) then
/* Формирование характеристик элемента ганта */
MAKE_GANT_ITEM(NDEFRESLIZ => REC.DEFRESLIZ,
NREL_FACT => REC.REL_FACT,
NDEFSTART => REC.DEFSTART,
STASK_BG_COLOR => STASK_BG_COLOR,
STASK_BG_PROGRESS_COLOR => STASK_BG_PROGRESS_COLOR,
NTASK_PROGRESS => NTASK_PROGRESS);
end if;
/* Сформируем основную спецификацию */
RGT := PKG_P8PANELS_VISUAL.TGANTT_TASK_MAKE(NRN => REC.RN,
SNUMB => COALESCE(REC.ROUTE, 'Отсутствует'),
SCAPTION => REC.NOMEN_NAME,
SNAME => REC.NOMEN_NAME,
DSTART => DDATE_FROM,
DEND => DDATE_TO,
NPROGRESS => NTASK_PROGRESS,
SBG_COLOR => STASK_BG_COLOR,
STEXT_COLOR => STASK_TEXT_COLOR,
SBG_PROGRESS_COLOR => STASK_BG_PROGRESS_COLOR,
BREAD_ONLY => true,
BREAD_ONLY_DATES => true,
BREAD_ONLY_PROGRESS => true);
/* Добавим доп. атрибуты */
PKG_P8PANELS_VISUAL.TGANTT_TASK_ADD_ATTR_VAL(RGANTT => RG,
RTASK => RGT,
SNAME => STASK_ATTR_DEFRESLIZ,
SVALUE => TO_CHAR(REC.DEFRESLIZ),
BCLEAR => true);
PKG_P8PANELS_VISUAL.TGANTT_TASK_ADD_ATTR_VAL(RGANTT => RG,
RTASK => RGT,
SNAME => STASK_ATTR_REL_FACT,
SVALUE => TO_CHAR(REC.REL_FACT));
PKG_P8PANELS_VISUAL.TGANTT_TASK_ADD_ATTR_VAL(RGANTT => RG,
RTASK => RGT,
SNAME => STASK_ATTR_DEFSTART,
SVALUE => TO_CHAR(REC.DEFSTART));
PKG_P8PANELS_VISUAL.TGANTT_TASK_ADD_ATTR_VAL(RGANTT => RG,
RTASK => RGT,
SNAME => STASK_ATTR_LEVEL,
SVALUE => REC.LEVEL);
/* Собираем зависимости */
for LINK in (select T.RN
from FCPRODPLANSP T
where T.PRN = NFCPRODPLAN
and T.UP_LEVEL = REC.RN
and ((NLEVEL is null) or ((NLEVEL is not null) and (NLEVEL >= REC.LEVEL + 1))))
loop
/* Добавляем зависимости */
PKG_P8PANELS_VISUAL.TGANTT_TASK_ADD_DEPENDENCY(RTASK => RGT, NDEPENDENCY => LINK.RN);
end loop;
/* Добавляем основную спецификацию в диаграмму */
PKG_P8PANELS_VISUAL.TGANTT_ADD_TASK(RGANTT => RG, RTASK => RGT);
end loop;
/* Формируем список */
COUT := PKG_P8PANELS_VISUAL.TGANTT_TO_XML(RGANTT => RG);
end FCPRODPLANSP_GET;
/* Инициализация планов и отчетов производства изделий */
procedure PRODPLAN_INIT
(
COUT out clob -- Список планов и отчетов производства изделий
)
is
begin
/* Начинаем формирование XML */
PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);
/* Открываем корень */
PKG_XFAST.DOWN_NODE(SNAME => 'XDATA');
/* Цикл по планам и отчетам производства изделий */
for REC in (select T.RN NRN,
D.DOCCODE || ', ' || trim(T.PREFIX) || '/' || trim(T.NUMB) || ', ' ||
TO_CHAR(T.DOCDATE, 'dd.mm.yyyy') SDOC_INFO
from FCPRODPLAN T,
DOCTYPES D,
FINSTATE FS
where T.CATEGORY = NFCPRODPLAN_CATEGORY
and T.STATUS = NFCPRODPLAN_STATUS
and D.RN = T.DOCTYPE
and FS.RN = T.TYPE
and FS.CODE = SFCPRODPLAN_TYPE
and exists (select /*+ INDEX(UP I_USERPRIV_CATALOG_ROLEID) */
null
from USERPRIV UP
where UP.CATALOG = T.CRN
and UP.ROLEID in (select /*+ INDEX(UR I_USERROLES_AUTHID_FK) */
UR.ROLEID
from USERROLES UR
where UR.AUTHID = UTILIZER)
union all
select /*+ INDEX(UP I_USERPRIV_CATALOG_AUTHID) */
null
from USERPRIV UP
where UP.CATALOG = T.CRN
and UP.AUTHID = UTILIZER)
and exists (select /*+ INDEX(UP I_USERPRIV_JUR_PERS_ROLEID) */
null
from USERPRIV UP
where UP.JUR_PERS = T.JUR_PERS
and UP.UNITCODE = 'CostProductPlans'
and UP.ROLEID in (select /*+ INDEX(UR I_USERROLES_AUTHID_FK) */
UR.ROLEID
from USERROLES UR
where UR.AUTHID = UTILIZER)
union all
select /*+ INDEX(UP I_USERPRIV_JUR_PERS_AUTHID) */
null
from USERPRIV UP
where UP.JUR_PERS = T.JUR_PERS
and UP.UNITCODE = 'CostProductPlans'
and UP.AUTHID = UTILIZER)
order by T.DOCDATE desc)
loop
/* Открываем план */
PKG_XFAST.DOWN_NODE(SNAME => 'XFCPRODPLANS');
/* Описываем план */
PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => REC.NRN);
PKG_XFAST.ATTR(SNAME => 'SDOC_INFO', SVALUE => REC.SDOC_INFO);
/* Закрываем план */
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 PRODPLAN_INIT;
end PKG_P8PANELS_MECHREC;
/

View File

@ -2019,6 +2019,9 @@ text="Формат data_grid и gant как в chart"
if (RGANTT.RTASK_COLORS(I).STEXT_COLOR is not null) then
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_TASK_TEXT_COLOR, SVALUE => RGANTT.RTASK_COLORS(I).STEXT_COLOR);
end if;
if (RGANTT.RTASK_COLORS(I).SBG_PROGRESS_COLOR is not null) then
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_TASK_BG_PRG_COLOR, SVALUE => RGANTT.RTASK_COLORS(I).SBG_PROGRESS_COLOR);
end if;
PKG_XFAST.ATTR(SNAME => SRESP_ATTR_DESC, SVALUE => RGANTT.RTASK_COLORS(I).SDESC);
/* Закрываем описание цвета задачи */
PKG_XFAST.UP();

367
dist/p8-panels.js vendored

File diff suppressed because one or more lines are too long

View File

@ -473,6 +473,9 @@ var Gantt = (function () {
class: 'bar-progress',
append_to: this.bar_group,
});
//ЦИТК
if (this.task.bgProgressColor) this.$bar_progress.style.fill = this.task.bgProgressColor;
//ЦИТК
animateSVG(this.$bar_progress, 'width', 0, this.progress_width);
}

View File

@ -12,10 +12,16 @@
</App>
<App name="EquipSrv">
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowEqsPanelsRoot" caption="Панели мониторинга" url="modules/p8-panels/"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowEqsPanelsRoot" caption="Панели мониторинга" url="Modules/p8-panels/"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowEqsPrfrm" caption="Выполнение работ по ТОиР" panelName="EqsPrfrm"/>
</App>
<App name="MechanicalRecords">
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelsRoot" caption="Панели мониторинга" url="Modules/P8-Panels/"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" separator="true"/>
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowMechRecPanelCostProdPlans" caption="Производственная программа" panelName="MechRecCostProdPlans"/>
</App>
</MenuItems>
<Panels urlBase="Modules/p8-panels/#/">
<Panel
@ -68,6 +74,16 @@
icon="build"
showInPanelsList="true"
preview="./img/eqs_prfrm.jpg"/>
<Panel
name="MechRecCostProdPlans"
group="Планирование и учёт в дискретном производстве"
caption="Производственная программа"
desc="Контроль исполнения производственной программы по срокам и количеству запуска и выпуска ДСЕ"
url="mech_rec_cost_prod_plans"
path="mech_rec_cost_prod_plans"
icon="calendar_month"
showInPanelsList="true"
preview="./img/default_preview.png"/>
<Panel
name="Samples"
group=""