From a0e9be4c4ba5a515d911131f2d9bed516ae59d13 Mon Sep 17 00:00:00 2001 From: Dollerino Date: Fri, 16 Feb 2024 17:24:08 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A6=D0=98=D0=A2=D0=9A-802=20-=20=D0=98=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B1=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/panels/mech_rec_cost_prod_plans/hooks.js | 8 +- .../mech_rec_cost_prod_plans.js | 93 +++++++++++++++++-- db/PKG_P8PANELS_MECHREC.pck | 32 ++++++- 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/app/panels/mech_rec_cost_prod_plans/hooks.js b/app/panels/mech_rec_cost_prod_plans/hooks.js index 926fc8a..dd285c4 100644 --- a/app/panels/mech_rec_cost_prod_plans/hooks.js +++ b/app/panels/mech_rec_cost_prod_plans/hooks.js @@ -13,10 +13,14 @@ import React from "react"; //Классы React //Тело модуля //----------- -//Клиентский отбор загруженных планов по поисковой фразе +//Клиентский отбор каталогов по поисковой фразе и наличию планов export const useFilteredPlanCtlgs = (planCtlgs, filter) => { const filteredPlanCtlgs = React.useMemo(() => { - return planCtlgs.filter(catalog => catalog.SNAME.toString().toLowerCase().includes(filter)); + return planCtlgs.filter( + catalog => + catalog.SNAME.toString().toLowerCase().includes(filter.ctlgName) && + (filter.haveDocs ? catalog.NCOUNT_DOCS > 0 : catalog.NCOUNT_DOCS >= 0) + ); }, [planCtlgs, filter]); return filteredPlanCtlgs; diff --git a/app/panels/mech_rec_cost_prod_plans/mech_rec_cost_prod_plans.js b/app/panels/mech_rec_cost_prod_plans/mech_rec_cost_prod_plans.js index bb2a489..b4e2b01 100644 --- a/app/panels/mech_rec_cost_prod_plans/mech_rec_cost_prod_plans.js +++ b/app/panels/mech_rec_cost_prod_plans/mech_rec_cost_prod_plans.js @@ -9,7 +9,23 @@ 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 { + Drawer, + Fab, + Box, + List, + ListItemButton, + ListItemText, + Typography, + Grid, + TextField, + Select, + MenuItem, + InputLabel, + FormGroup, + FormControlLabel, + Checkbox +} from "@mui/material"; //Интерфейсные элементы import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения @@ -21,6 +37,9 @@ import { useFilteredPlanCtlgs } from "./hooks"; //Вспомогательные //Константы //--------- +//Склонения для документов +const DECLINATIONS = ["план", "плана", "планов"]; + //Поля сортировки const SORT_REP_DATE = "DREP_DATE"; const SORT_REP_DATE_TO = "DREP_DATE_TO"; @@ -34,13 +53,16 @@ const GANTT_WIDTH = "98vw"; //Стили const STYLES = { PLANS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" }, + PLANS_CHECKBOX_HAVEDOCS: { alignContent: "space-around" }, + PLANS_LIST_ITEM_ZERODOCS: { backgroundColor: "#ebecec" }, PLANS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" }, + PLANS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.6rem", textTransform: "uppercase" }, PLANS_BUTTON: { position: "absolute" }, PLANS_DRAWER: { - minWidth: "250px", + width: "350px", display: "inline-block", flexShrink: 0, - [`& .MuiDrawer-paper`]: { minWidth: "250px", display: "inline-block", boxSizing: "border-box" } + [`& .MuiDrawer-paper`]: { width: "350px", display: "inline-block", boxSizing: "border-box" } }, GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH }, GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" } @@ -59,6 +81,26 @@ const parseProdPlanSpXML = async xmlDoc => { return data.XDATA; }; +//Форматирование для отображения количества документов +const formatCountDocs = nCountDocs => { + //Получаем последнюю цифру в значении + let num = (nCountDocs % 100) % 10; + //Документов + if (nCountDocs > 10 && nCountDocs < 20) { + return `${nCountDocs} ${DECLINATIONS[2]}`; + } + //Документа + if (num > 1 && num < 5) { + return `${nCountDocs} ${DECLINATIONS[1]}`; + } + //Документ + if (num == 1) { + return `${nCountDocs} ${DECLINATIONS[0]}`; + } + //Документов + return `${nCountDocs} ${DECLINATIONS[2]}`; +}; + //Список каталогов планов const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, onClick } = {}) => { //Генерация содержимого @@ -67,18 +109,48 @@ const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, on { - setFilter(event.target.value); + setFilter(pv => ({ ...pv, ctlgName: event.target.value })); }} > + + { + setFilter(pv => ({ ...pv, haveDocs: event.target.checked })); + }} + /> + } + label="Только с планами" + labelPlacement="end" + /> + {planCtlgs.map(p => ( - (onClick ? onClick(p) : null)}> - {p.SNAME}} /> + (onClick ? onClick(p) : null)} + > + {p.SNAME}} + secondary={ + + {formatCountDocs(p.NCOUNT_DOCS)} + + } + /> ))} @@ -116,9 +188,10 @@ const MechRecCostProdPlans = () => { selectedPlanCtlgGanttDef: {}, selectedPlanCtlgSpecs: [] }); + //Состояние для фильтра каталогов + const [filter, setFilter] = useState({ ctlgName: "", haveLinks: false }); - const [filter, setFilter] = useState(""); - + //Массив отфильтрованных каталогов const filteredPlanCtgls = useFilteredPlanCtlgs(state.planCtlgs, filter); //Подключение к контексту сообщений diff --git a/db/PKG_P8PANELS_MECHREC.pck b/db/PKG_P8PANELS_MECHREC.pck index 5ce95c9..4f733a8 100644 --- a/db/PKG_P8PANELS_MECHREC.pck +++ b/db/PKG_P8PANELS_MECHREC.pck @@ -207,8 +207,8 @@ create or replace package body PKG_P8PANELS_MECHREC as CSQL clob; -- Буфер для запроса ICURSOR integer; -- Курсор для исполнения запроса /* Значения спецификации */ - NTASK_RN PKG_STD.TREF; -- Рег. номер спецификации - NTASK_PRN PKG_STD.TREF; -- Рег. номер родителя спецификации + NTASK_RN PKG_STD.TREF; -- Рег. номер спецификации + NTASK_PRN PKG_STD.TREF; -- Рег. номер родителя спецификации STASK_PROD_ORDER PKG_STD.TSTRING; -- Заказ DTASK_REP_DATE PKG_STD.TLDATE; -- Дата запуска DTASK_REP_DATE_TO PKG_STD.TLDATE; -- Дата выпуска @@ -557,7 +557,32 @@ create or replace package body PKG_P8PANELS_MECHREC as PKG_XFAST.DOWN_NODE(SNAME => 'XDATA'); /* Цикл по планам и отчетам производства изделий */ for REC in (select T.RN as NRN, - T.NAME as SNAME + T.NAME as SNAME, + (select count(P.RN) + from FCPRODPLAN P, + FINSTATE FS + where P.CRN = T.RN + and P.CATEGORY = NFCPRODPLAN_CATEGORY + and P.STATUS = NFCPRODPLAN_STATUS + and FS.RN = P.TYPE + and FS.CODE = SFCPRODPLAN_TYPE + and exists + (select /*+ INDEX(UP I_USERPRIV_JUR_PERS_ROLEID) */ + null + from USERPRIV UP + where UP.JUR_PERS = P.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 = P.JUR_PERS + and UP.UNITCODE = 'CostProductPlans' + and UP.AUTHID = UTILIZER)) as NCOUNT_DOCS from ACATALOG T, UNITLIST UL where T.DOCNAME = 'CostProductPlans' @@ -577,6 +602,7 @@ create or replace package body PKG_P8PANELS_MECHREC as /* Описываем план */ PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => REC.NRN); PKG_XFAST.ATTR(SNAME => 'SNAME', SVALUE => REC.SNAME); + PKG_XFAST.ATTR(SNAME => 'NCOUNT_DOCS', NVALUE => REC.NCOUNT_DOCS); /* Закрываем план */ PKG_XFAST.UP(); end loop;