forked from CITKParus/P8-Panels
WEB APP: Панель "Финансы проекта" - графики, % готовности, переход к РНОПотр
This commit is contained in:
parent
6176387826
commit
13170ab591
@ -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"
|
||||
|
@ -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 (
|
||||
<Box p={2}>
|
||||
{projectsDataGrid.dataLoaded ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
columnsDef={projectsDataGrid.columnsDef}
|
||||
rows={projectsDataGrid.rows}
|
||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||
morePages={projectsDataGrid.morePages}
|
||||
reloading={projectsDataGrid.reload}
|
||||
expandable={true}
|
||||
headCellRender={headCellRender}
|
||||
dataCellRender={prms => 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 ? (
|
||||
<P8PFullScreenDialog title={`Этапы проекта "${projectsDataGrid.selectedProject.SNAME_USL}"`} onClose={handleStagesClose}>
|
||||
<Stages
|
||||
project={projectsDataGrid.selectedProject.NRN}
|
||||
projectName={projectsDataGrid.selectedProject.SNAME_USL}
|
||||
filters={projectsDataGrid.stagesFilters}
|
||||
/>
|
||||
</P8PFullScreenDialog>
|
||||
<Box p={1}>
|
||||
<Grid container spacing={1}>
|
||||
{showCharts ? (
|
||||
<>
|
||||
<Grid item xs={4}>
|
||||
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
|
||||
{problemsChart.loaded ? <P8PChart {...problemsChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
|
||||
{customersChart.loaded ? <P8PChart {...customersChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
|
||||
{costNotesChart.loaded ? <P8PChart {...costNotesChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
|
||||
</Paper>
|
||||
</Grid>
|
||||
</>
|
||||
) : null}
|
||||
<Grid item xs={12}>
|
||||
{projectsDataGrid.dataLoaded ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
columnsDef={projectsDataGrid.columnsDef}
|
||||
rows={projectsDataGrid.rows}
|
||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||
filtersInitial={projectsDataGrid.filters}
|
||||
morePages={projectsDataGrid.morePages}
|
||||
reloading={projectsDataGrid.reload}
|
||||
expandable={true}
|
||||
headCellRender={headCellRender}
|
||||
dataCellRender={prms => 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 ? (
|
||||
<P8PFullScreenDialog title={`Этапы проекта "${projectsDataGrid.selectedProject.SNAME_USL}"`} onClose={handleStagesClose}>
|
||||
<Stages
|
||||
project={projectsDataGrid.selectedProject.NRN}
|
||||
projectName={projectsDataGrid.selectedProject.SNAME_USL}
|
||||
filters={projectsDataGrid.stagesFilters}
|
||||
/>
|
||||
</P8PFullScreenDialog>
|
||||
) : null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
{problemsChart.loaded || customersChart.loaded || costNotesChart.loaded ? (
|
||||
<Fab size="small" color="secondary" sx={STYLES.CHART_FAB} onClick={() => setShowCharts(!showCharts)}>
|
||||
<Icon>{showCharts ? "expand_less" : "expand_more"}</Icon>
|
||||
</Fab>
|
||||
) : null}
|
||||
</Box>
|
||||
);
|
||||
|
@ -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 })}
|
||||
|
Loading…
x
Reference in New Issue
Block a user