diff --git a/app/panels/prj_fin/layouts.js b/app/panels/prj_fin/layouts.js
new file mode 100644
index 0000000..07fda51
--- /dev/null
+++ b/app/panels/prj_fin/layouts.js
@@ -0,0 +1,359 @@
+/*
+ Парус 8 - Панели мониторинга - ПУП - Экономика проектов
+ Дополнительная разметка и вёрстка клиентских элементов
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import { Grid, Icon, Stack, Link, Button, Table, TableBody, TableRow, TableCell, Typography, Box, Paper, IconButton } from "@mui/material"; //Интерфейсные компоненты
+import { hasValue, formatDateRF, formatNumberRFCurrency } from "../../core/utils"; //Вспомогательные процедуры и функции
+
+//---------
+//Константы
+//---------
+
+//Разделы панелей экономики проектов
+export const PANEL_UNITS = {
+ PROJECTS: "PROJECTS",
+ PROJECT_STAGES: "PROJECT_STAGES",
+ PROJECT_STAGE_CONTRACTS: "PROJECT_STAGE_CONTRACTS",
+ PROJECT_STAGE_ARTS: "PROJECT_STAGE_ARTS"
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Формирование значения для колонки "Состояние" проекта
+const formatPrjStateValue = (value, addText = false) => {
+ const [text, icon] =
+ value == 0
+ ? ["Зарегистрирован", "app_registration"]
+ : value == 1
+ ? ["Открыт", "lock_open"]
+ : value == 2
+ ? ["Остановлен", "do_not_disturb_on"]
+ : value == 3
+ ? ["Закрыт", "lock_outline"]
+ : value == 4
+ ? ["Согласован", "thumb_up_alt"]
+ : ["Исполнение прекращено", "block"];
+ return (
+
+ {icon}
+ {addText == true ? text : null}
+
+ );
+};
+
+//Формирование значения для колонки "Состояние" этапа
+const formatStageStatusValue = (value, addText = false) => {
+ const [text, icon] =
+ value == 0
+ ? ["Зарегистрирован", "app_registration"]
+ : value == 1
+ ? ["Открыт", "lock_open"]
+ : value == 2
+ ? ["Закрыт", "lock_outline"]
+ : value == 3
+ ? ["Согласован", "thumb_up_alt"]
+ : value == 4
+ ? ["Исполнение прекращено", "block"]
+ : ["Остановлен", "do_not_disturb_on"];
+ return (
+
+ {icon}
+ {addText == true ? text : null}
+
+ );
+};
+
+//Подбор функции форматирования колонки "Состояние" по разделу панели
+const getStatusFormatter = panelUnit => (panelUnit === PANEL_UNITS.PROJECTS ? formatPrjStateValue : formatStageStatusValue);
+
+//Формирование значения для контрольных колонок
+const formatCtrlValue = (value, addText = false) => {
+ if (hasValue(value)) {
+ const [text, icon, color] = value == 0 ? ["В норме", "done", "green"] : ["Требует внимания", "error", "red"];
+ return (
+
+
+ {icon}
+
+ {addText == true ? text : null}
+
+ );
+ } else return value;
+};
+
+//Форматирование значений колонок
+export const valueFormatter = ({ panelUnit, value, columnDef }) => {
+ switch (columnDef.name) {
+ case "NSTATE":
+ return getStatusFormatter(panelUnit)(value, true);
+ case "DBEGPLAN":
+ case "DENDPLAN":
+ case "DDOC_DATE":
+ case "DCSTAGE_BEGIN_DATE":
+ case "DCSTAGE_END_DATE":
+ return formatDateRF(value);
+ case "NPLAN":
+ case "NCOST_FACT":
+ case "NCONTR":
+ return formatNumberRFCurrency(value);
+
+ case "NCTRL_FIN":
+ case "NCTRL_CONTR":
+ case "NCTRL_COEXEC":
+ case "NCTRL_PERIOD":
+ case "NCTRL_COST":
+ case "NCTRL_ACT":
+ return formatCtrlValue(value, true);
+ }
+ return value;
+};
+
+//Генерация представления ячейки заголовка
+export const headCellRender = ({ columnDef }) => {
+ switch (columnDef.name) {
+ case "NSTATE":
+ case "NCTRL_FIN":
+ case "NCTRL_CONTR":
+ case "NCTRL_COEXEC":
+ case "NCTRL_PERIOD":
+ case "NCTRL_COST":
+ case "NCTRL_ACT":
+ return {
+ stackProps: { justifyContent: "center" },
+ cellProps: { align: "center" }
+ };
+ }
+};
+
+//Генерация представления ячейки c данными
+export const dataCellRender = ({ panelUnit, row, columnDef, pOnlineShowDocument, showStages, showStageArts, showCostNotes, showContracts }) => {
+ //Подбор функции на нажатие в ячейки контрольной колонки в зависимости от контекста
+ const getCrlOnClick = () =>
+ panelUnit == PANEL_UNITS.PROJECT_STAGES ? (columnDef.name === "NCTRL_FIN" ? showContracts : showStageArts) : showStages;
+ //Подбор представления ячейки контрольной колонки в зависимости от контекста
+ const renderCtl = () => ({
+ cellProps: {
+ align:
+ (panelUnit == PANEL_UNITS.PROJECT_STAGES && columnDef.name == "NCTRL_PERIOD") ||
+ (panelUnit == PANEL_UNITS.PROJECT_STAGE_CONTRACTS && columnDef.name == "NCTRL_FIN") ||
+ (panelUnit == PANEL_UNITS.PROJECT_STAGE_ARTS && ["NCTRL_COST", "NCTRL_CONTR"].includes(columnDef.name))
+ ? "right"
+ : "center"
+ },
+ data: hasValue(row[columnDef.name]) ? (
+ panelUnit == PANEL_UNITS.PROJECT_STAGES && columnDef.name == "NCTRL_PERIOD" ? (
+
+
+ {row.NDAYS_LEFT} дн.
+
+ {formatCtrlValue(row[columnDef.name], false)}
+
+ ) : panelUnit == PANEL_UNITS.PROJECT_STAGE_CONTRACTS && columnDef.name == "NCTRL_FIN" ? (
+
+ {row[columnDef.name] === 1 ? (
+
+ {formatNumberRFCurrency(row["NPAY_IN_REST"])}
+
+ ) : null}
+ {formatCtrlValue(row[columnDef.name], false)}
+
+ ) : panelUnit == PANEL_UNITS.PROJECT_STAGES && ["NCTRL_COEXEC", "NCTRL_ACT"].includes(columnDef.name) ? (
+ formatCtrlValue(row[columnDef.name], false)
+ ) : panelUnit == PANEL_UNITS.PROJECT_STAGE_ARTS && ["NCTRL_COST", "NCTRL_CONTR"].includes(columnDef.name) ? (
+
+
+ {formatNumberRFCurrency(row[columnDef.name === "NCTRL_COST" ? "NCOST_DIFF" : "NCONTR_LEFT"])}
+
+ {formatCtrlValue(row[columnDef.name], false)}
+
+ ) : (
+ getCrlOnClick()({ sender: row, filters: [{ name: columnDef.name, from: row[columnDef.name] }] })}>
+ {formatCtrlValue(row[columnDef.name], false)}
+
+ )
+ ) : null
+ });
+ //Формирование представлений
+ switch (columnDef.name) {
+ case "SCODE":
+ case "SNAME_USL":
+ return {
+ data: (
+ showStages({ sender: row })}>
+ {row[columnDef.name]}
+
+ )
+ };
+ case "SDOC_PREF":
+ case "SDOC_NUMB":
+ return {
+ data: (
+
+ pOnlineShowDocument({ unitCode: row[`SLNK_UNIT_${columnDef.name}`], document: row[`NLNK_DOCUMENT_${columnDef.name}`] })
+ }
+ >
+ {row[columnDef.name]}
+
+ )
+ };
+ case "NCOST_FACT":
+ case "NCONTR":
+ return {
+ data: row[columnDef.name] ? (
+ (columnDef.name === "NCOST_FACT" ? showCostNotes({ sender: row }) : showContracts({ sender: row }))}
+ >
+ {formatNumberRFCurrency(row[columnDef.name])}
+
+ ) : null
+ };
+ case "NSTATE":
+ return {
+ cellProps: { align: "center" },
+ data: getStatusFormatter(panelUnit)(row[columnDef.name], false)
+ };
+ case "NCTRL_FIN":
+ case "NCTRL_CONTR":
+ case "NCTRL_COEXEC":
+ case "NCTRL_PERIOD":
+ case "NCTRL_COST":
+ case "NCTRL_ACT":
+ return renderCtl();
+ }
+};
+
+//Генерация представления расширения строки
+export const rowExpandRender = ({
+ panelUnit,
+ columnsDef,
+ row,
+ pOnlineShowDocument,
+ showStages,
+ showPayNotes,
+ showCostNotes,
+ showPaymentAccountsIn,
+ showStageArts,
+ showContracts
+}) => {
+ //Фильтруем системные атрибуты и атрибуты без значений
+ const cardColumns = columnsDef.filter(
+ columnDef =>
+ columnDef.visible == false &&
+ columnDef.name != "NRN" &&
+ !columnDef.name.startsWith("SLNK_UNIT_") &&
+ !columnDef.name.startsWith("NLNK_DOCUMENT_") &&
+ hasValue(row[columnDef.name])
+ );
+ //Автоформатирование значения (N* - число, D* - дата, всё остальное - строка)
+ const formatColumnValue = (name, value) =>
+ name.startsWith("N") ? formatNumberRFCurrency(value) : name.startsWith("D") ? formatDateRF(value) : value;
+ //Формирование кнопок переходов
+ const linkButtons = () =>
+ panelUnit === PANEL_UNITS.PROJECTS ? (
+ <>
+
+
+ >
+ ) : panelUnit === PANEL_UNITS.PROJECT_STAGES ? (
+ <>
+
+
+
+ >
+ ) : panelUnit === PANEL_UNITS.PROJECT_STAGE_CONTRACTS ? (
+
+ ) : null;
+ //Сборка содержимого
+ return (
+
+
+
+ {linkButtons()}
+
+
+
+
+
+ {cardColumns.map((cardColumn, i) => (
+
+
+
+ {cardColumn.caption}:
+
+
+
+ {(hasValue(row[`SLNK_UNIT_${cardColumn.name}`]) && hasValue(row[`NLNK_DOCUMENT_${cardColumn.name}`])) ||
+ ["NPAY_IN", "NFIN_OUT"].includes(cardColumn.name) ? (
+
+ ["NFIN_IN", "NFIN_OUT"].includes(cardColumn.name)
+ ? showPayNotes({ sender: row, direction: row[`NLNK_DOCUMENT_${cardColumn.name}`] })
+ : cardColumn.name == "NCOST_FACT"
+ ? showCostNotes({ sender: row })
+ : cardColumn.name == "NPAY_IN"
+ ? showPaymentAccountsIn({ sender: row })
+ : pOnlineShowDocument({
+ unitCode: row[`SLNK_UNIT_${cardColumn.name}`],
+ document: row[`NLNK_DOCUMENT_${cardColumn.name}`]
+ })
+ }
+ >
+
+ {formatColumnValue(cardColumn.name, row[cardColumn.name])}
+
+
+ ) : (
+
+ {["NDAYS_LEFT", "NINCOME_PRC"].includes(cardColumn.name)
+ ? row[cardColumn.name]
+ : formatColumnValue(cardColumn.name, row[cardColumn.name])}
+
+ )}
+
+
+ ))}
+
+
+
+
+
+
+ );
+};
diff --git a/app/panels/prj_fin/prj_fin.js b/app/panels/prj_fin/prj_fin.js
index f3f03da..d7c2e02 100644
--- a/app/panels/prj_fin/prj_fin.js
+++ b/app/panels/prj_fin/prj_fin.js
@@ -7,11 +7,8 @@
//Подключение библиотек
//---------------------
-import React, { useState } from "react"; //Классы React
-import { Box } from "@mui/material"; //Интерфейсные компоненты
-import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог
+import React from "react"; //Классы React
import { Projects } from "./projects"; //Список проектов
-import { Stages } from "./stages"; //Список этапов проекта
//-----------
//Тело модуля
@@ -19,37 +16,8 @@ import { Stages } from "./stages"; //Список этапов проекта
//Корневая панель экономики проекта
const PrjFin = () => {
- //Собственное состояние
- const [prjFinPanel, setPrjFinPanel] = useState({
- selectedProject: null,
- stagesFilters: []
- });
-
- //При открытии списка этапов проекта
- const handleStagesOpen = ({ project = {}, filters = [] } = {}) => {
- setPrjFinPanel(pv => ({ ...pv, selectedProject: { ...project }, stagesFilters: [...filters] }));
- };
-
- //При закрытии списка этапов проекта
- const handleStagesClose = () => {
- setPrjFinPanel(pv => ({ ...pv, selectedProject: null, stagesFilters: [] }));
- };
-
//Генерация содержимого
- return (
-
-
- {prjFinPanel.selectedProject ? (
-
-
-
- ) : null}
-
- );
+ return ;
};
//----------------
diff --git a/app/panels/prj_fin/projects.js b/app/panels/prj_fin/projects.js
index 05b103e..663517c 100644
--- a/app/panels/prj_fin/projects.js
+++ b/app/panels/prj_fin/projects.js
@@ -8,207 +8,24 @@
//---------------------
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
-import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Grid, Icon, Stack, Link, Button, Table, TableBody, TableRow, TableCell, Typography, Box, Paper, IconButton } from "@mui/material"; //Интерфейсные компоненты
-import { hasValue, formatDateRF, formatNumberRFCurrency, object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
+import { Box } 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 { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
-
-//-----------------------
-//Вспомогательные функции
-//-----------------------
-
-//Формирование значения для колонки "Состояние проекта"
-const formatPrjStateValue = (value, addText = false) => {
- const [text, icon] =
- value == 0
- ? ["Зарегистрирован", "app_registration"]
- : value == 1
- ? ["Открыт", "lock_open"]
- : value == 2
- ? ["Остановлен", "do_not_disturb_on"]
- : value == 3
- ? ["Закрыт", "lock_outline"]
- : value == 4
- ? ["Согласован", "thumb_up_alt"]
- : ["Исполнение прекращено", "block"];
- return (
-
- {icon}
- {addText == true ? text : null}
-
- );
-};
-
-//Формирование значения для контрольных колонок
-const formatCtrlValue = (value, addText = false) => {
- if (hasValue(value)) {
- const [text, icon, color] = value == 0 ? ["В норме", "done", "green"] : ["Требует внимания", "error", "red"];
- return (
-
-
- {icon}
-
- {addText == true ? text : null}
-
- );
- } else return value;
-};
-
-//Форматирование значений колонок
-const valueFormatter = ({ value, columnDef }) => {
- switch (columnDef.name) {
- case "NSTATE":
- return formatPrjStateValue(value, true);
- case "DBEGPLAN":
- case "DENDPLAN":
- return formatDateRF(value);
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COEXEC":
- case "NCTRL_PERIOD":
- case "NCTRL_COST":
- case "NCTRL_ACT":
- return formatCtrlValue(value, true);
- }
- return value;
-};
-
-//Генерация представления ячейки заголовка
-const headCellRender = ({ columnDef }) => {
- switch (columnDef.name) {
- case "NSTATE":
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COEXEC":
- case "NCTRL_PERIOD":
- case "NCTRL_COST":
- case "NCTRL_ACT":
- return {
- stackProps: { justifyContent: "center" },
- cellProps: { align: "center" }
- };
- }
-};
-
-//Генерация представления ячейки c данными
-const dataCellRender = ({ row, columnDef }, handleStagesOpen) => {
- switch (columnDef.name) {
- case "SCODE":
- case "SNAME_USL":
- return {
- data: (
- handleStagesOpen({ project: row })}>
- {row[columnDef.name]}
-
- )
- };
- case "NSTATE":
- return {
- cellProps: { align: "center" },
- data: formatPrjStateValue(row[columnDef.name], false)
- };
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COEXEC":
- case "NCTRL_PERIOD":
- case "NCTRL_COST":
- case "NCTRL_ACT":
- return {
- cellProps: { align: "center" },
- data: hasValue(row[columnDef.name]) ? (
- handleStagesOpen({ project: row, filters: [{ name: columnDef.name, from: row[columnDef.name] }] })}>
- {formatCtrlValue(row[columnDef.name], false)}
-
- ) : null
- };
- }
-};
-
-//Генерация представления расширения строки
-const rowExpandRender = ({ columnsDef, row }, pOnlineShowDocument, showProjectPayNotes, handleStagesOpen) => {
- const cardColumns = columnsDef.filter(
- columnDef =>
- columnDef.visible == false &&
- columnDef.name != "NRN" &&
- !columnDef.name.startsWith("SLNK_UNIT_") &&
- !columnDef.name.startsWith("NLNK_DOCUMENT_") &&
- hasValue(row[columnDef.name])
- );
- const formatColumnValue = (name, value) =>
- name.startsWith("N") ? formatNumberRFCurrency(value) : name.startsWith("D") ? formatDateRF(value) : value;
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- {cardColumns.map((cardColumn, i) => (
-
-
-
- {cardColumn.caption}:
-
-
-
- {hasValue(row[`SLNK_UNIT_${cardColumn.name}`]) && hasValue(row[`NLNK_DOCUMENT_${cardColumn.name}`]) ? (
- {
- if (["NFIN_IN", "NFIN_OUT"].includes(cardColumn.name))
- showProjectPayNotes(row.NRN, row[`NLNK_DOCUMENT_${cardColumn.name}`]);
- else
- pOnlineShowDocument({
- unitCode: row[`SLNK_UNIT_${cardColumn.name}`],
- document: row[`NLNK_DOCUMENT_${cardColumn.name}`]
- });
- }}
- >
-
- {formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
-
- ) : (
-
- {formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
- )}
-
-
- ))}
-
-
-
-
-
-
- );
-};
+import { PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
+import { Stages } from "./stages"; //Список этапов проекта
//-----------
//Тело модуля
//-----------
//Список проектов
-const Projects = ({ onStagesOpen }) => {
+const Projects = () => {
//Собственное состояние
const [projectsDataGrid, setProjectsDataGrid] = useState({
dataLoaded: false,
@@ -218,7 +35,9 @@ const Projects = ({ onStagesOpen }) => {
rows: [],
reload: true,
pageNumber: 1,
- morePages: true
+ morePages: true,
+ selectedProject: null,
+ stagesFilters: []
});
//Подключение к контексту взаимодействия с сервером
@@ -265,15 +84,19 @@ const Projects = ({ onStagesOpen }) => {
]);
//Отображение журнала платежей по этапу проекта
- const showProjectPayNotes = async (project, direction) => {
+ const showPayNotes = async ({ sender, direction }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.SELECT_FIN",
- args: { NRN: project, NDIRECTION: direction }
+ args: { NRN: sender.NRN, NDIRECTION: direction }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "PayNotes", 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] }));
+
//При изменении состояния фильтра
const handleFilterChanged = ({ filters }) => setProjectsDataGrid(pv => ({ ...pv, filters: [...filters], pageNumber: 1, reload: true }));
@@ -283,8 +106,8 @@ const Projects = ({ onStagesOpen }) => {
//При изменении количества отображаемых страниц
const handlePagesCountChanged = () => setProjectsDataGrid(pv => ({ ...pv, pageNumber: pv.pageNumber + 1, reload: true }));
- //При открытии списка этапов
- const handleStagesOpen = ({ project, filters }) => (onStagesOpen ? onStagesOpen({ project, filters }) : null);
+ //При закрытии списка этапов проекта
+ const handleStagesClose = () => setProjectsDataGrid(pv => ({ ...pv, selectedProject: null, stagesFilters: [] }));
//При необходимости обновить данные
useEffect(() => {
@@ -293,7 +116,7 @@ const Projects = ({ onStagesOpen }) => {
//Генерация содержимого
return (
- <>
+
{projectsDataGrid.dataLoaded ? (
{
reloading={projectsDataGrid.reload}
expandable={true}
headCellRender={headCellRender}
- dataCellRender={prms => dataCellRender(prms, handleStagesOpen)}
- rowExpandRender={prms => rowExpandRender(prms, pOnlineShowDocument, showProjectPayNotes, handleStagesOpen)}
- valueFormatter={valueFormatter}
+ 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 ? (
+
+
+
+ ) : null}
+
);
};
-//Контроль свойств - Список проектов
-Projects.propTypes = {
- onStagesOpen: PropTypes.func
-};
-
//----------------
//Интерфейс модуля
//----------------
diff --git a/app/panels/prj_fin/stage_arts.js b/app/panels/prj_fin/stage_arts.js
index e18e045..37103c3 100644
--- a/app/panels/prj_fin/stage_arts.js
+++ b/app/panels/prj_fin/stage_arts.js
@@ -9,80 +9,15 @@
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Box, Icon, Stack, Link } from "@mui/material"; //Интерфейсные компоненты
-import { hasValue, formatNumberRFCurrency, object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
+import { Box } from "@mui/material"; //Интерфейсные компоненты
+import { object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_FILTER_SHAPE } from "../../components/p8p_data_grid"; //Таблица данных
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
-
-//-----------------------
-//Вспомогательные функции
-//-----------------------
-
-//Формирование значения для контрольных колонок
-const formatCtrlValue = (value, addText = false) => {
- if (hasValue(value)) {
- const [text, icon, color] = value == 0 ? ["В норме", "done", "green"] : ["Требует внимания", "error", "red"];
- return (
-
-
- {icon}
-
- {addText == true ? text : null}
-
- );
- } else return value;
-};
-
-//Форматирование значений колонок
-const valueFormatter = ({ value, columnDef }) => {
- switch (columnDef.name) {
- case "NPLAN":
- case "NCOST_FACT":
- case "NCONTR":
- return formatNumberRFCurrency(value);
- case "NCTRL_COST":
- case "NCTRL_CONTR":
- return formatCtrlValue(value, true);
- }
- return value;
-};
-
-//Генерация представления ячейки c данными
-const dataCellRender = ({ row, columnDef }, showStageArtCostNotes, showStageArtContracts) => {
- switch (columnDef.name) {
- case "NCOST_FACT":
- case "NCONTR":
- return {
- data: row[columnDef.name] ? (
- (columnDef.name === "NCOST_FACT" ? showStageArtCostNotes(row.NRN) : showStageArtContracts(row.NRN))}
- >
- {formatNumberRFCurrency(row[columnDef.name])}
-
- ) : null
- };
- case "NCTRL_COST":
- case "NCTRL_CONTR":
- return {
- data: (
-
-
- {formatNumberRFCurrency(row[columnDef.name === "NCTRL_COST" ? "NCOST_DIFF" : "NCONTR_LEFT"])}
-
- {formatCtrlValue(row[columnDef.name], false)}
-
- )
- };
- }
-};
+import { PANEL_UNITS, dataCellRender, valueFormatter } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//-----------
//Тело модуля
@@ -131,20 +66,20 @@ const StageArts = ({ stage, filters }) => {
}, [stage, stageArtsDataGrid.reload, stageArtsDataGrid.filters, stageArtsDataGrid.dataLoaded, executeStored, SERV_DATA_TYPE_CLOB]);
//Отображение журнала затрат по статье калькуляции
- const showStageArtCostNotes = async article => {
+ const showCostNotes = async ({ sender }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGE_ARTS_SELECT_COST_FACT",
- args: { NSTAGE: stage, NFPDARTCL: article }
+ args: { NSTAGE: stage, NFPDARTCL: sender.NRN }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "CostNotes", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение договоров по статье калькуляции
- const showStageArtContracts = async article => {
+ const showContracts = async ({ sender }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGE_ARTS_SELECT_CONTR",
- args: { NSTAGE: stage, NFPDARTCL: article }
+ args: { NSTAGE: stage, NFPDARTCL: sender.NRN }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "Contracts", inputParameters: [{ name: "in_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
@@ -170,7 +105,7 @@ const StageArts = ({ stage, filters }) => {
size={P8P_DATA_GRID_SIZE.SMALL}
morePages={false}
reloading={stageArtsDataGrid.reload}
- dataCellRender={prms => dataCellRender(prms, showStageArtCostNotes, showStageArtContracts)}
+ dataCellRender={prms => dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECT_STAGE_ARTS, showCostNotes, showContracts })}
valueFormatter={valueFormatter}
onFilterChanged={handleFilterChanged}
/>
diff --git a/app/panels/prj_fin/stage_contracts.js b/app/panels/prj_fin/stage_contracts.js
index 0af5207..84ef9c3 100644
--- a/app/panels/prj_fin/stage_contracts.js
+++ b/app/panels/prj_fin/stage_contracts.js
@@ -9,162 +9,15 @@
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Box, Stack, Grid, Paper, Table, TableBody, TableRow, TableCell, Typography, Button, Link, Icon } from "@mui/material"; //Интерфейсные компоненты
-import { hasValue, formatDateRF, formatNumberRFCurrency, object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
+import { Box } from "@mui/material"; //Интерфейсные компоненты
+import { object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_FILTER_SHAPE } from "../../components/p8p_data_grid"; //Таблица данных
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
-
-//-----------------------
-//Вспомогательные функции
-//-----------------------
-
-//Формирование значения для контрольных колонок
-const formatCtrlValue = (value, addText = false) => {
- if (hasValue(value)) {
- const [text, icon, color] = value == 0 ? ["В норме", "done", "green"] : ["Требует внимания", "error", "red"];
- return (
-
-
- {icon}
-
- {addText == true ? text : null}
-
- );
- } else return value;
-};
-
-//Форматирование значений колонок
-const valueFormatter = ({ value, columnDef }) => {
- switch (columnDef.name) {
- case "DDOC_DATE":
- case "DCSTAGE_BEGIN_DATE":
- case "DCSTAGE_END_DATE":
- return formatDateRF(value);
- case "NCTRL_FIN":
- return formatCtrlValue(value, true);
- }
- return value;
-};
-
-//Генерация представления ячейки c данными
-const dataCellRender = ({ row, columnDef }, pOnlineShowDocument) => {
- switch (columnDef.name) {
- case "SDOC_PREF":
- case "SDOC_NUMB":
- return {
- data: (
-
- pOnlineShowDocument({
- unitCode: row[`SLNK_UNIT_${columnDef.name}`],
- document: row[`NLNK_DOCUMENT_${columnDef.name}`]
- })
- }
- >
- {row[columnDef.name]}
-
- )
- };
- case "NCTRL_FIN":
- return {
- data: (
-
- {row[columnDef.name] === 1 ? (
-
- {formatNumberRFCurrency(row["NPAY_IN_REST"])}
-
- ) : null}
- {formatCtrlValue(row[columnDef.name], false)}
-
- )
- };
- }
-};
-
-//Генерация представления расширения строки
-const rowExpandRender = ({ columnsDef, row }, pOnlineShowDocument, showStageContractPaymentAccountsIn, showStageContractPayNotes) => {
- const cardColumns = columnsDef.filter(
- columnDef =>
- columnDef.visible == false &&
- columnDef.name != "NRN" &&
- !columnDef.name.startsWith("SLNK_UNIT_") &&
- !columnDef.name.startsWith("NLNK_DOCUMENT_") &&
- hasValue(row[columnDef.name])
- );
- const formatColumnValue = (name, value) =>
- name.startsWith("N") ? formatNumberRFCurrency(value) : name.startsWith("D") ? formatDateRF(value) : value;
- return (
-
-
-
-
-
-
-
-
-
-
-
- {cardColumns.map((cardColumn, i) => (
-
-
-
- {cardColumn.caption}:
-
-
-
- {(hasValue(row[`SLNK_UNIT_${cardColumn.name}`]) && hasValue(row[`NLNK_DOCUMENT_${cardColumn.name}`])) ||
- ["NPAY_IN", "NFIN_OUT"].includes(cardColumn.name) ? (
-
- cardColumn.name === "NPAY_IN"
- ? showStageContractPaymentAccountsIn(row.NRN)
- : cardColumn.name === "NFIN_OUT"
- ? showStageContractPayNotes(row.NRN)
- : pOnlineShowDocument({
- unitCode: row[`SLNK_UNIT_${cardColumn.name}`],
- document: row[`NLNK_DOCUMENT_${cardColumn.name}`]
- })
- }
- >
-
- {formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
-
- ) : (
-
- {formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
- )}
-
-
- ))}
-
-
-
-
-
-
- );
-};
+import { PANEL_UNITS, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//-----------
//Тело модуля
@@ -233,20 +86,20 @@ const StageContracts = ({ stage, filters }) => {
]);
//Отображение выходящих счетов на оплату от соисполнителя этапа
- const showStageContractPaymentAccountsIn = async contract => {
+ const showPaymentAccountsIn = async ({ sender }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGE_CONTRACTS_SELECT_PAY_IN",
- args: { NPROJECTSTAGEPF: contract }
+ args: { NPROJECTSTAGEPF: sender.NRN }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "PaymentAccountsIn", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение фактических платежей соисполнителю этапа
- const showStageContractPayNotes = async contract => {
+ const showPayNotes = async ({ sender }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGE_CONTRACTS_SELECT_FIN_OUT",
- args: { NPROJECTSTAGEPF: contract }
+ args: { NPROJECTSTAGEPF: sender.NRN }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "PayNotes", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
@@ -279,9 +132,15 @@ const StageContracts = ({ stage, filters }) => {
morePages={stageContractsDataGrid.morePages}
reloading={stageContractsDataGrid.reload}
expandable={true}
- dataCellRender={prms => dataCellRender(prms, pOnlineShowDocument)}
+ dataCellRender={prms => dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECT_STAGE_CONTRACTS, pOnlineShowDocument })}
rowExpandRender={prms =>
- rowExpandRender(prms, pOnlineShowDocument, showStageContractPaymentAccountsIn, showStageContractPayNotes)
+ rowExpandRender({
+ ...prms,
+ panelUnit: PANEL_UNITS.PROJECT_STAGE_CONTRACTS,
+ pOnlineShowDocument,
+ showPaymentAccountsIn,
+ showPayNotes
+ })
}
valueFormatter={valueFormatter}
onOrderChanged={handleOrderChanged}
diff --git a/app/panels/prj_fin/stages.js b/app/panels/prj_fin/stages.js
index d295599..aef5dad 100644
--- a/app/panels/prj_fin/stages.js
+++ b/app/panels/prj_fin/stages.js
@@ -9,8 +9,8 @@
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Box, Icon, Stack, Grid, Paper, Table, TableBody, TableRow, TableCell, Typography, Button, IconButton, Link } from "@mui/material"; //Интерфейсные компоненты
-import { hasValue, formatDateRF, formatNumberRFCurrency, object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
+import { Box } from "@mui/material"; //Интерфейсные компоненты
+import { object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_FILTER_SHAPE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог
@@ -20,210 +20,7 @@ import { BackEndСtx } from "../../context/backend"; //Контекст взаи
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
-
-//-----------------------
-//Вспомогательные функции
-//-----------------------
-
-//Формирование значения для колонки "Состояние"
-const formatStageStatusValue = (value, addText = false) => {
- const [text, icon] =
- value == 0
- ? ["Зарегистрирован", "app_registration"]
- : value == 1
- ? ["Открыт", "lock_open"]
- : value == 2
- ? ["Закрыт", "lock_outline"]
- : value == 3
- ? ["Согласован", "thumb_up_alt"]
- : value == 4
- ? ["Исполнение прекращено", "block"]
- : ["Остановлен", "do_not_disturb_on"];
- return (
-
- {icon}
- {addText == true ? text : null}
-
- );
-};
-
-//Формирование значения для контрольных колонок
-const formatCtrlValue = (value, addText = false) => {
- if (hasValue(value)) {
- const [text, icon, color] = value == 0 ? ["В норме", "done", "green"] : ["Требует внимания", "error", "red"];
- return (
-
-
- {icon}
-
- {addText == true ? text : null}
-
- );
- } else return value;
-};
-
-//Форматирование значений колонок
-const valueFormatter = ({ value, columnDef }) => {
- switch (columnDef.name) {
- case "NSTATE":
- return formatStageStatusValue(value, true);
- case "DBEGPLAN":
- case "DENDPLAN":
- return formatDateRF(value);
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COEXEC":
- case "NCTRL_PERIOD":
- case "NCTRL_COST":
- case "NCTRL_ACT":
- return formatCtrlValue(value, true);
- }
- return value;
-};
-
-//Генерация представления ячейки заголовка
-const headCellRender = ({ columnDef }) => {
- switch (columnDef.name) {
- case "NSTATE":
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COEXEC":
- case "NCTRL_COST":
- case "NCTRL_ACT":
- return {
- stackProps: { justifyContent: "center" },
- cellProps: { align: "center" }
- };
- }
-};
-
-//Генерация представления ячейки c данными
-const dataCellRender = ({ row, columnDef }, showStageArts, showStageContracts) => {
- switch (columnDef.name) {
- case "NSTATE":
- return {
- cellProps: { align: "center" },
- data: formatStageStatusValue(row[columnDef.name], false)
- };
- case "NCTRL_COEXEC":
- case "NCTRL_ACT":
- return {
- cellProps: { align: "center" },
- data: formatCtrlValue(row[columnDef.name], false)
- };
- case "NCTRL_FIN":
- case "NCTRL_CONTR":
- case "NCTRL_COST":
- return {
- cellProps: { align: "center" },
- data: hasValue(row[columnDef.name]) ? (
-
- (columnDef.name === "NCTRL_FIN" ? showStageContracts : showStageArts)({
- stage: row.NRN,
- stageNumb: row.SNUMB,
- filters: [{ name: columnDef.name, from: row[columnDef.name] }]
- })
- }
- >
- {formatCtrlValue(row[columnDef.name], false)}
-
- ) : null
- };
- case "NCTRL_PERIOD":
- return {
- cellProps: { align: "right" },
- data: hasValue(row[columnDef.name]) ? (
-
-
- {row.NDAYS_LEFT} дн.
-
- {formatCtrlValue(row[columnDef.name], false)}
-
- ) : null
- };
- }
-};
-
-//Генерация представления расширения строки
-const rowExpandRender = ({ columnsDef, row }, pOnlineShowDocument, showStageArts, showStageContracts, showStagePayNotes, showStageCostNotes) => {
- const cardColumns = columnsDef.filter(
- columnDef =>
- columnDef.visible == false &&
- columnDef.name != "NRN" &&
- !columnDef.name.startsWith("SLNK_UNIT_") &&
- !columnDef.name.startsWith("NLNK_DOCUMENT_") &&
- hasValue(row[columnDef.name])
- );
- const formatColumnValue = (name, value) =>
- name.startsWith("N") ? formatNumberRFCurrency(value) : name.startsWith("D") ? formatDateRF(value) : value;
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {cardColumns.map((cardColumn, i) => (
-
-
-
- {cardColumn.caption}:
-
-
-
- {hasValue(row[`SLNK_UNIT_${cardColumn.name}`]) && hasValue(row[`NLNK_DOCUMENT_${cardColumn.name}`]) ? (
- {
- if (["NFIN_IN", "NFIN_OUT"].includes(cardColumn.name))
- showStagePayNotes(row.NRN, row[`NLNK_DOCUMENT_${cardColumn.name}`]);
- else if (cardColumn.name == "NCOST_FACT") showStageCostNotes(row.NRN);
- else
- pOnlineShowDocument({
- unitCode: row[`SLNK_UNIT_${cardColumn.name}`],
- document: row[`NLNK_DOCUMENT_${cardColumn.name}`]
- });
- }}
- >
-
- {formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
-
- ) : (
-
- {["NDAYS_LEFT", "NINCOME_PRC"].includes(cardColumn.name)
- ? row[cardColumn.name]
- : formatColumnValue(cardColumn.name, row[cardColumn.name])}
-
- )}
-
-
- ))}
-
-
-
-
-
-
- );
-};
+import { PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//-----------
//Тело модуля
@@ -294,34 +91,32 @@ const Stages = ({ project, projectName, filters }) => {
]);
//Отображение журнала платежей по этапу проекта
- const showStagePayNotes = async (stage, direction) => {
+ const showPayNotes = async ({ sender, direction }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGES_SELECT_FIN",
- args: { NRN: stage, NDIRECTION: direction }
+ args: { NRN: sender.NRN, NDIRECTION: direction }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "PayNotes", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение журнала затрат по этапу проекта
- const showStageCostNotes = async stage => {
+ const showCostNotes = async ({ sender }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.STAGES_SELECT_COST_FACT",
- args: { NRN: stage }
+ args: { NRN: sender.NRN }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "CostNotes", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение статей калькуляции по этапу проекта
- const showStageArts = ({ stage, stageNumb, filters = [] } = {}) => {
- setStagesDataGrid(pv => ({ ...pv, showStageArts: stage, selectedStageNumb: stageNumb, stageArtsFilters: [...filters] }));
- };
+ const showStageArts = ({ sender, filters = [] } = {}) =>
+ setStagesDataGrid(pv => ({ ...pv, showStageArts: sender.NRN, selectedStageNumb: sender.SNUMB, stageArtsFilters: [...filters] }));
//Отображение договоров с соисполнителями по этапу проекта
- const showStageContracts = ({ stage, stageNumb, filters = [] } = {}) => {
- setStagesDataGrid(pv => ({ ...pv, showStageContracts: stage, selectedStageNumb: stageNumb, stageContractsFilters: [...filters] }));
- };
+ const showContracts = ({ sender, filters = [] } = {}) =>
+ setStagesDataGrid(pv => ({ ...pv, showStageContracts: sender.NRN, selectedStageNumb: sender.SNUMB, stageContractsFilters: [...filters] }));
//При изменении состояния фильтра
const handleFilterChanged = ({ filters }) => setStagesDataGrid(pv => ({ ...pv, filters, pageNumber: 1, reload: true }));
@@ -357,11 +152,19 @@ const Stages = ({ project, projectName, filters }) => {
reloading={stagesDataGrid.reload}
expandable={true}
headCellRender={headCellRender}
- dataCellRender={prms => dataCellRender(prms, showStageArts, showStageContracts)}
+ dataCellRender={prms => dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECT_STAGES, showStageArts, showContracts })}
rowExpandRender={prms =>
- rowExpandRender(prms, pOnlineShowDocument, showStageArts, showStageContracts, showStagePayNotes, showStageCostNotes)
+ rowExpandRender({
+ ...prms,
+ panelUnit: PANEL_UNITS.PROJECT_STAGES,
+ pOnlineShowDocument,
+ showStageArts,
+ showContracts,
+ showPayNotes,
+ showCostNotes
+ })
}
- valueFormatter={valueFormatter}
+ valueFormatter={prms => valueFormatter({ ...prms, panelUnit: PANEL_UNITS.PROJECT_STAGES })}
onOrderChanged={handleOrderChanged}
onFilterChanged={handleFilterChanged}
onPagesCountChanged={handlePagesCountChanged}