Compare commits
2 Commits
6e2ba371fe
...
36a534f06f
| Author | SHA1 | Date | |
|---|---|---|---|
| 36a534f06f | |||
|
|
7ca972a96a |
@ -12,14 +12,14 @@ export const DEFAULT_PROJECT_CONFIG = {
|
||||
defaultValue: null,
|
||||
min: 0,
|
||||
step: 1,
|
||||
required_field: false,
|
||||
required_field: true,
|
||||
},
|
||||
'Тип проекта развития': {
|
||||
type: 'multiselect',
|
||||
options: ['Открытие ВСП', 'Закрытие ВСП', 'Переезд ВСП', 'Реновация РФ', 'Открытие УРМ'],
|
||||
placeholder: 'Выберите тип проекта',
|
||||
defaultValue: null,
|
||||
required_field: false,
|
||||
required_field: true,
|
||||
},
|
||||
'Название проекта': {
|
||||
type: 'text',
|
||||
@ -29,16 +29,17 @@ export const DEFAULT_PROJECT_CONFIG = {
|
||||
},
|
||||
'Формат ВСП': {
|
||||
type: 'multiselect',
|
||||
options: ['Фланговый', 'Типовой', 'Розничный', 'МСБ', 'Лёгкий', 'Мини', 'Розничный-киоск', 'МБО', 'Офис самообслуживания', 'Другое'],
|
||||
options: ['Флагманский', 'Типовой', 'Розничный', 'МСБ', 'Лёгкий', 'Мини', 'Розничный-киоск', 'МБО', 'Офис самообслуживания', 'Другое'],
|
||||
placeholder: 'Выберите формат ВСП',
|
||||
defaultValue: null,
|
||||
required_field: false,
|
||||
required_field: true,
|
||||
},
|
||||
'Адрес объекта': {
|
||||
type: 'text',
|
||||
placeholder: 'Введите адрес объекта',
|
||||
defaultValue: '',
|
||||
required_field: false,
|
||||
required_field: true,
|
||||
|
||||
},
|
||||
'Целевая численность, чел.': {
|
||||
type: 'number',
|
||||
@ -53,7 +54,8 @@ export const DEFAULT_PROJECT_CONFIG = {
|
||||
options: ['Собственность', 'Аренда', 'Субаренда'],
|
||||
placeholder: 'Выберите тип размещения',
|
||||
defaultValue: null,
|
||||
required_field: false,
|
||||
required_field: true,
|
||||
|
||||
},
|
||||
'Площадь размещения, м2': {
|
||||
type: 'number',
|
||||
|
||||
@ -135,7 +135,7 @@ export default function FormPage() {
|
||||
'Формат ВСП': {
|
||||
type: 'multiselect',
|
||||
options: [
|
||||
'Фланговый',
|
||||
'Флагманский',
|
||||
'Типовой',
|
||||
'Розничный',
|
||||
'МСБ',
|
||||
|
||||
@ -202,11 +202,13 @@ const SummaryPage = () => {
|
||||
|
||||
const onEdit = (row) => {
|
||||
const isSmeta = row.depth > 0;
|
||||
const projectId = isSmeta ? row.getParentRow()?.original?.id : row.original.id;
|
||||
const parentProject = isSmeta ? row.getParentRow()?.original : row.original;
|
||||
const projectId = parentProject?.id;
|
||||
setSelectedRowData({
|
||||
...row.original,
|
||||
_rowType: isSmeta ? 'smeta' : 'project',
|
||||
_projectId: projectId,
|
||||
_projectFundingByKoDecision: parentProject?.funding_by_ko_decision,
|
||||
});
|
||||
setEditModalOpen(true);
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Box, IconButton, Tooltip } from '@mui/material';
|
||||
import { differenceInMonths, isValid, parseISO } from 'date-fns';
|
||||
import { Back, EditPenSvg, TrashSvg } from '../../components/common/icons/icons';
|
||||
import StatusBadge from './components/StatusBadge/StatusBadge';
|
||||
import { DEVELOMENT_BLOCK, FUNDING_BY_DECISION } from './constants';
|
||||
@ -63,6 +64,19 @@ export const createFirstColumns = (handlers) => {
|
||||
header: 'Дата открытия / переезда / закрытия',
|
||||
size: 160,
|
||||
},
|
||||
{
|
||||
id: 'project_implementation_months',
|
||||
accessorFn: (row) => {
|
||||
if (!Array.isArray(row.sub_rows) || !row.board_decision_date) return null;
|
||||
|
||||
const boardDecisionDate = parseISO(row.board_decision_date);
|
||||
if (!isValid(boardDecisionDate)) return null;
|
||||
|
||||
return differenceInMonths(new Date(), boardDecisionDate);
|
||||
},
|
||||
header: 'Время реализации проекта в месяцах',
|
||||
size: 180,
|
||||
},
|
||||
{
|
||||
accessorKey: 'project_type',
|
||||
header: 'Тип проекта',
|
||||
|
||||
@ -4,7 +4,7 @@ import React from 'react';
|
||||
import { useAuth } from '../../../../app/context/AuthProvider';
|
||||
import { DangerOutlinedButton, PrimaryButton } from '../../../../components/common/Buttons/Buttons';
|
||||
import { DEVELOMENT_BLOCK, FUNDING_BY_DECISION } from '../../constants';
|
||||
import { canEditFirstTableField, isFirstTableFieldDependencySatisfied } from '../../constants/fieldAccess';
|
||||
import { canEditFirstTableField, hasReserveValuesInChildSmetas, isFirstTableFieldDependencySatisfied } from '../../constants/fieldAccess';
|
||||
|
||||
const EditModal = ({ open, onClose, rowData, onSave, isSaving = false, orgUnitNames = {} }) => {
|
||||
const { user } = useAuth();
|
||||
@ -80,8 +80,10 @@ const EditModal = ({ open, onClose, rowData, onSave, isSaving = false, orgUnitNa
|
||||
// Компонент для поля ввода
|
||||
const renderField = (field) => {
|
||||
const rawValue = formData[field.key];
|
||||
const isFundingByDecisionLocked = field.key === 'funding_by_ko_decision' && hasReserveValuesInChildSmetas(formData);
|
||||
const isFieldDisabled =
|
||||
field.disabled ||
|
||||
isFundingByDecisionLocked ||
|
||||
!canEditFirstTableField(field.key, user?.role_id) ||
|
||||
!isFirstTableFieldDependencySatisfied(field.key, formData);
|
||||
const fieldValue = field.valueType === 'boolean' && rawValue !== null && rawValue !== undefined
|
||||
@ -143,6 +145,11 @@ const EditModal = ({ open, onClose, rowData, onSave, isSaving = false, orgUnitNa
|
||||
return <MenuItem key={value} value={value}>{label}</MenuItem>;
|
||||
})]}
|
||||
</TextField>
|
||||
{isFundingByDecisionLocked && (
|
||||
<Typography sx={{ mt: 0.5, color: 'warning.main', fontSize: '0.75rem', lineHeight: 1.4 }}>
|
||||
Поле нельзя изменить: в одной из дочерних смет заполнено значение «Из резерва Банка в смету ПРРС АХР» или «Из резерва Банка в смету ПРРС КВ».
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,14 +11,14 @@ const ALL_ROLES = [
|
||||
// Матрица доступа к полям первой таблицы.
|
||||
export const FIRST_TABLE_FIELD_ACCESS = {
|
||||
name: ADMIN_ROLES,
|
||||
org_unit_id: ADMIN_ROLES,
|
||||
org_unit_id: ALL_ROLES,
|
||||
status: DFIP_ROLES,
|
||||
technical_number: [],
|
||||
object_address: ALL_ROLES,
|
||||
vsp_format: ALL_ROLES,
|
||||
placement_type: ADMIN_ROLES,
|
||||
staff_count: ADMIN_ROLES,
|
||||
total_area: ADMIN_ROLES,
|
||||
placement_type: ALL_ROLES,
|
||||
staff_count: ALL_ROLES,
|
||||
total_area: ALL_ROLES,
|
||||
project_type: ALL_ROLES,
|
||||
krf_decision_date: ALL_ROLES,
|
||||
fk_decision_date: ALL_ROLES,
|
||||
@ -41,10 +41,33 @@ export const FIRST_TABLE_FIELD_DEPENDENCIES = {
|
||||
board_decision_date: "fk_decision_date",
|
||||
};
|
||||
|
||||
export const FIRST_TABLE_FIELD_VALUE_REQUIREMENTS = {
|
||||
reserve_to_prrs_ahr: {
|
||||
fieldKey: "_projectFundingByKoDecision",
|
||||
value: "bank_reserve",
|
||||
},
|
||||
reserve_to_prrs_kv: {
|
||||
fieldKey: "_projectFundingByKoDecision",
|
||||
value: "bank_reserve",
|
||||
},
|
||||
};
|
||||
|
||||
export const canEditFirstTableField = (fieldKey, roleId) =>
|
||||
FIRST_TABLE_FIELD_ACCESS[fieldKey]?.includes(roleId) ?? false;
|
||||
|
||||
const isFilled = (value) => value !== null && value !== undefined && value !== "";
|
||||
|
||||
export const hasReserveValuesInChildSmetas = (project) =>
|
||||
(project?.sub_rows || []).some(
|
||||
(smeta) => isFilled(smeta.reserve_to_prrs_ahr) || isFilled(smeta.reserve_to_prrs_kv),
|
||||
);
|
||||
|
||||
export const isFirstTableFieldDependencySatisfied = (fieldKey, rowData) => {
|
||||
const dependencyKey = FIRST_TABLE_FIELD_DEPENDENCIES[fieldKey];
|
||||
return !dependencyKey || Boolean(rowData?.[dependencyKey]);
|
||||
if (dependencyKey && !rowData?.[dependencyKey]) return false;
|
||||
|
||||
const valueRequirement = FIRST_TABLE_FIELD_VALUE_REQUIREMENTS[fieldKey];
|
||||
if (valueRequirement && rowData?.[valueRequirement.fieldKey] !== valueRequirement.value) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -120,7 +120,7 @@ export const ModalCreateProject = ({
|
||||
switch (config.type) {
|
||||
case 'multiselect':
|
||||
return (
|
||||
<Box key={fieldName}>
|
||||
<Box key={fieldName} sx={{ mb: hasError ? '0.5rem' : 0 }}>
|
||||
<Typography
|
||||
className='gray-color'
|
||||
sx={{
|
||||
@ -159,7 +159,7 @@ export const ModalCreateProject = ({
|
||||
|
||||
case 'text':
|
||||
return (
|
||||
<Box key={fieldName}>
|
||||
<Box key={fieldName} sx={{ mb: hasError ? '0.5rem' : 0 }}>
|
||||
<Typography
|
||||
className='gray-color'
|
||||
sx={{
|
||||
@ -191,7 +191,7 @@ export const ModalCreateProject = ({
|
||||
|
||||
case 'number':
|
||||
return (
|
||||
<Box key={fieldName}>
|
||||
<Box key={fieldName} sx={{ mb: hasError ? '0.5rem' : 0 }}>
|
||||
<Typography
|
||||
className='gray-color'
|
||||
sx={{
|
||||
@ -264,9 +264,11 @@ export const ModalCreateProject = ({
|
||||
flexDirection: 'column',
|
||||
gap: '1.25rem',
|
||||
'& .sameSize': {
|
||||
height: '2.69rem',
|
||||
minWidth: '39.75rem',
|
||||
},
|
||||
'& .sameSize.MuiInputBase-root, & .sameSize .MuiInputBase-root': {
|
||||
height: '2.69rem',
|
||||
},
|
||||
'& .gray-color': { color: '#4A5565' },
|
||||
}}>
|
||||
{Object.entries(config).map(([fieldName, config]) => renderField(fieldName, config))}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user