From 13170ab591e21e86dd883f6f142eb52e65717ce2 Mon Sep 17 00:00:00 2001 From: Mikhail Chechnev Date: Sat, 21 Oct 2023 03:51:10 +0300 Subject: [PATCH] =?UTF-8?q?WEB=20APP:=20=D0=9F=D0=B0=D0=BD=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=20"=D0=A4=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D1=8B=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0"=20-=20=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D0=B8,=20%=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=D1=81=D1=82=D0=B8,=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=20=D0=BA=20=D0=A0=D0=9D=D0=9E=D0=9F=D0=BE?= =?UTF-8?q?=D1=82=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/panels/prj_fin/layouts.js | 3 + app/panels/prj_fin/projects.js | 178 ++++++++++++++++++++++++++------- app/panels/prj_fin/stages.js | 14 ++- 3 files changed, 158 insertions(+), 37 deletions(-) diff --git a/app/panels/prj_fin/layouts.js b/app/panels/prj_fin/layouts.js index 7af1108..0984959 100644 --- a/app/panels/prj_fin/layouts.js +++ b/app/panels/prj_fin/layouts.js @@ -255,6 +255,7 @@ export const rowExpandRender = ({ showCostNotes, showPaymentAccountsIn, showIncomingInvoices, + showGoodsTransInvoicesToConsumers, showStageArts, showContracts }) => { @@ -333,6 +334,8 @@ export const rowExpandRender = ({ ? showPayNotes({ sender: row, direction: row[`NLNK_DOCUMENT_${cardColumn.name}`] }) : cardColumn.name == "NCOST_FACT" ? showCostNotes({ sender: row }) + : cardColumn.name == "NSUMM_REALIZ" + ? showGoodsTransInvoicesToConsumers({ sender: row }) : cardColumn.name == "NPAY_IN" ? showPaymentAccountsIn({ sender: row }) : cardColumn.name == "NCOEXEC_IN" diff --git a/app/panels/prj_fin/projects.js b/app/panels/prj_fin/projects.js index 3f38b84..ba4c6fb 100644 --- a/app/panels/prj_fin/projects.js +++ b/app/panels/prj_fin/projects.js @@ -8,11 +8,12 @@ //--------------------- import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React -import { Box } from "@mui/material"; //Интерфейсные компоненты +import { Box, Grid, Paper, Fab, Icon } from "@mui/material"; //Интерфейсные компоненты import { object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог +import { P8PChart } from "../../components/p8p_chart"; //График import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером import { ApplicationСtx } from "../../context/application"; //Контекст приложения import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений @@ -20,6 +21,17 @@ import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подкл import { PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов import { Stages } from "./stages"; //Список этапов проекта +//--------- +//Константы +//--------- + +//Стили +const STYLES = { + CHART: { maxHeight: "300px", display: "flex", justifyContent: "center" }, + CHART_PAPER: { height: "100%" }, + CHART_FAB: { position: "absolute", top: 80, left: 16 } +}; + //----------- //Тело модуля //----------- @@ -40,6 +52,12 @@ const Projects = () => { stagesFilters: [] }); + //Состояния графиков + const [showCharts, setShowCharts] = useState(true); + const [problemsChart, setProblemsChart] = useState({ loaded: false, labels: [], datasets: [] }); + const [customersChart, setCustomersChart] = useState({ loaded: false, labels: [], datasets: [] }); + const [costNotesChart, setCostNotesChart] = useState({ loaded: false, labels: [], datasets: [] }); + //Подключение к контексту взаимодействия с сервером const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx); @@ -84,6 +102,37 @@ const Projects = () => { SERV_DATA_TYPE_CLOB ]); + //Получение данных графиков + const loadChartData = async () => { + const problemsChart = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.CHART_PROBLEMS", + respArg: "COUT" + }); + setProblemsChart(pv => ({ + ...pv, + loaded: true, + ...problemsChart.XCHART + })); + const customersChart = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.CHART_CUSTOMERS", + respArg: "COUT" + }); + setCustomersChart(pv => ({ + ...pv, + loaded: true, + ...customersChart.XCHART + })); + const costNotesChart = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.CHART_FCCOSTNOTES", + respArg: "COUT" + }); + setCostNotesChart(pv => ({ + ...pv, + loaded: true, + ...costNotesChart.XCHART + })); + }; + //Отображение журнала платежей по этапу проекта const showPayNotes = async ({ sender, direction }) => { const data = await executeStored({ @@ -94,6 +143,16 @@ const Projects = () => { else showMsgErr(TEXTS.NO_DATA_FOUND); }; + //Отображение детализации точки графика затрат + const showCostNotesChartDetail = async ({ unitCode, year, month }) => { + const data = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.CHART_FCCOSTNOTES_SELECT_COST", + args: { NYEAR: year, NMONTH: month } + }); + if (data.NIDENT) pOnlineShowUnit({ unitCode, inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] }); + else showMsgErr(TEXTS.NO_DATA_FOUND); + }; + //Отображение этапов проекта const showStages = ({ sender, filters = [] } = {}) => setProjectsDataGrid(pv => ({ ...pv, selectedProject: { ...sender }, stagesFilters: [...filters] })); @@ -110,48 +169,95 @@ const Projects = () => { //При закрытии списка этапов проекта const handleStagesClose = () => setProjectsDataGrid(pv => ({ ...pv, selectedProject: null, stagesFilters: [] })); + //Отработка нажатия на график + const handleChartClick = ({ item }) => { + if (item.SFILTER && item.SFILTER_VALUE) + setProjectsDataGrid(pv => ({ + ...pv, + filters: [{ name: item.SFILTER, from: item.SFILTER_VALUE }], + pageNumber: 1, + reload: true + })); + if (item.SUNITCODE && item.NYEAR && item.NMONTH) showCostNotesChartDetail({ unitCode: item.SUNITCODE, year: item.NYEAR, month: item.NMONTH }); + }; + //При необходимости обновить данные useEffect(() => { loadProjects(); }, [projectsDataGrid.reload, loadProjects]); + //При подключении к странице + useEffect(() => { + loadChartData(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + //Генерация содержимого return ( - - {projectsDataGrid.dataLoaded ? ( - dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECTS, showStages })} - rowExpandRender={prms => - rowExpandRender({ - ...prms, - panelUnit: PANEL_UNITS.PROJECTS, - pOnlineShowDocument, - showPayNotes, - showStages - }) - } - valueFormatter={prms => valueFormatter({ ...prms, panelUnit: PANEL_UNITS.PROJECTS })} - onOrderChanged={handleOrderChanged} - onFilterChanged={handleFilterChanged} - onPagesCountChanged={handlePagesCountChanged} - /> - ) : null} - {projectsDataGrid.selectedProject ? ( - - - + + + {showCharts ? ( + <> + + + {problemsChart.loaded ? : null} + + + + + {customersChart.loaded ? : null} + + + + + {costNotesChart.loaded ? : null} + + + + ) : null} + + {projectsDataGrid.dataLoaded ? ( + dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECTS, showStages })} + rowExpandRender={prms => + rowExpandRender({ + ...prms, + panelUnit: PANEL_UNITS.PROJECTS, + pOnlineShowDocument, + showPayNotes, + showStages + }) + } + valueFormatter={prms => valueFormatter({ ...prms, panelUnit: PANEL_UNITS.PROJECTS })} + onOrderChanged={handleOrderChanged} + onFilterChanged={handleFilterChanged} + onPagesCountChanged={handlePagesCountChanged} + /> + ) : null} + {projectsDataGrid.selectedProject ? ( + + + + ) : null} + + + {problemsChart.loaded || customersChart.loaded || costNotesChart.loaded ? ( + setShowCharts(!showCharts)}> + {showCharts ? "expand_less" : "expand_more"} + ) : null} ); diff --git a/app/panels/prj_fin/stages.js b/app/panels/prj_fin/stages.js index aef5dad..32b836e 100644 --- a/app/panels/prj_fin/stages.js +++ b/app/panels/prj_fin/stages.js @@ -110,6 +110,17 @@ const Stages = ({ project, projectName, filters }) => { else showMsgErr(TEXTS.NO_DATA_FOUND); }; + //Отображение расходных накладных на отпуск потребителям по этапу проекта + const showGoodsTransInvoicesToConsumers = async ({ sender }) => { + const data = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.STAGES_SELECT_SUMM_REALIZ", + args: { NRN: sender.NRN } + }); + if (data.NIDENT) + pOnlineShowUnit({ unitCode: "GoodsTransInvoicesToConsumers", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] }); + else showMsgErr(TEXTS.NO_DATA_FOUND); + }; + //Отображение статей калькуляции по этапу проекта const showStageArts = ({ sender, filters = [] } = {}) => setStagesDataGrid(pv => ({ ...pv, showStageArts: sender.NRN, selectedStageNumb: sender.SNUMB, stageArtsFilters: [...filters] })); @@ -161,7 +172,8 @@ const Stages = ({ project, projectName, filters }) => { showStageArts, showContracts, showPayNotes, - showCostNotes + showCostNotes, + showGoodsTransInvoicesToConsumers }) } valueFormatter={prms => valueFormatter({ ...prms, panelUnit: PANEL_UNITS.PROJECT_STAGES })}