From 633c4d3fedcbf4b8453c9261334c3fe7f37aeb00 Mon Sep 17 00:00:00 2001 From: Grog Date: Mon, 26 Oct 2026 13:35:05 +0300 Subject: [PATCH 1/4] =?UTF-8?q?AURORA-1671:=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB?= =?UTF-8?q?=D1=83=20=D0=93=D0=9A=20=D0=B8=20=D0=AE=D0=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.css | 6 +++ web/src/layouts/CatalogueGroups.tsx | 42 +++++----------- .../services/api/directories/catalogue_jur.ts | 3 +- .../catalogueJurSlice/catalogueJurSlice.ts | 9 +++- .../store/slices/catalogueJurSlice/types.ts | 2 + .../companyGroupsSlice/companyGroupsSlice.ts | 15 +----- .../store/slices/companyGroupsSlice/types.ts | 1 - web/src/types/api.ts | 1 + .../CataloguGroupTabs/CataloguGroupTabs.tsx | 2 +- .../CatalogueGroupHeader.tsx | 2 +- .../CatalogueJurForm/CatalogueJurForm.tsx | 50 ++++++++++++------- .../CatalogueJurTable/CatalogueJurTable.tsx | 6 +-- .../CompanyGroupForm/CompanyGroupForm.tsx | 4 +- .../CompanyGroupsList/CompanyGroupsList.tsx | 4 +- .../ConsolidationChessTableFilter.css | 7 --- .../ConsolidationChessTableFilter.tsx | 2 - .../RelatedGroupForm/RelatedGroupForm.tsx | 14 ++++-- web/src/widgets/RelatedGroupTable/config.tsx | 8 ++- 18 files changed, 87 insertions(+), 91 deletions(-) delete mode 100644 web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.css diff --git a/web/src/App.css b/web/src/App.css index e69de29..facf75a 100644 --- a/web/src/App.css +++ b/web/src/App.css @@ -0,0 +1,6 @@ +.custom-select-selection-item .ant-select-selection-item { + background-color: #ecfdf3 !important; + color: #1f5f35 !important; + box-shadow: inset 0 0 0 1px #2ea64b38 !important; + border-radius: 999px !important; +} \ No newline at end of file diff --git a/web/src/layouts/CatalogueGroups.tsx b/web/src/layouts/CatalogueGroups.tsx index 9509c4a..9028064 100644 --- a/web/src/layouts/CatalogueGroups.tsx +++ b/web/src/layouts/CatalogueGroups.tsx @@ -7,7 +7,6 @@ import { createCatalogueJur } from '../services/api/directories/catalogue_jur'; import { createCompanyGroup, fetchRelatedGroups } from '../services/api/directories/company_groups'; import { createRelatedGroup } from '../services/api/directories/related-groups'; import { getCatalogueJurThunk } from '../store/slices/catalogueJurSlice/thunks'; -import { setActiveCompanyGroup } from '../store/slices/companyGroupsSlice/companyGroupsSlice'; import { getCompanyGroupsThunk } from '../store/slices/companyGroupsSlice/thunks'; import { useAppDispatch, useAppSelector } from '../store/store'; import type { RelatedGroupOut } from '../types/api'; @@ -37,29 +36,20 @@ export function CatalogueGroup() { const [activeTab, setActiveTab] = useState('legal_entities'); const [gskData, setGskData] = useState([]); const [gszData, setGszData] = useState([]); - const activeCompanyGroup = useAppSelector((state) => state.company_groups.activeCompanyGroup); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); const relatedGroupFilter = useAppSelector((state) => state.catalogue_jur.relatedGroupFilter); - const rawRows = useAppSelector((state) => state.company_groups.raw_rows); async function createJurHandler(values: CatalogueJurFormProps) { - try { - await createCatalogueJur(values); - dispatch(getCompanyGroupsThunk()); - dispatch( - getCatalogueJurThunk({ - closed: isGettingArchive, - outside_group: false, - company_group_id: activeCompanyGroup?.id, - }), - ); - setKindForm(null); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await createCatalogueJur(values); + dispatch(getCompanyGroupsThunk()); + dispatch( + getCatalogueJurThunk({ + closed: isGettingArchive, + outside_group: false, + company_group_id: activeCompanyGroup?.id, + }), + ); + setKindForm(null); } async function createRelatedGroupHandler(values: RelatedGroupFormType) { if (values.company_group_id) { @@ -123,12 +113,6 @@ export function CatalogueGroup() { setActiveTab('legal_entities'); }, [relatedGroupFilter]); - useEffect(() => { - if (!activeCompanyGroup && rawRows?.length) { - dispatch(setActiveCompanyGroup(rawRows?.[0])); - } - }, [rawRows, activeCompanyGroup]); - return (
{ setKindForm(null); }} - onOk={async (values) => { - await createJurHandler(values); - }} + onOk={createJurHandler} /> )} {(kindForm === 'gsk' || kindForm === 'gsz') && ( diff --git a/web/src/services/api/directories/catalogue_jur.ts b/web/src/services/api/directories/catalogue_jur.ts index 9b1d30a..33d3d8f 100644 --- a/web/src/services/api/directories/catalogue_jur.ts +++ b/web/src/services/api/directories/catalogue_jur.ts @@ -7,10 +7,9 @@ import type { MoveCatalogueJurProps, WithdrawCatalogueJurProps, } from '../../../types/catalogueJur/catalogueJur'; -import { LE_PAGE } from './company_groups'; export async function fetchCatalogueJur(params: GetCatalogueJurPropsI) { - const res = await api.get>('/directories/legal-entities', { limit: LE_PAGE, offset: 0, ...params }); + const res = await api.get>('/directories/legal-entities', { limit: 200, offset: 0, ...params }); return res; } diff --git a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts index 7a14e25..d381927 100644 --- a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts +++ b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts @@ -2,6 +2,7 @@ import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; import type { RelatedGroupOut } from '../../../types/api'; import { getCatalogueJurThunk } from './thunks'; import type { CatalogueJurSliceType } from './types'; +import { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; const initialState: CatalogueJurSliceType = { raw_rows: [], @@ -10,6 +11,7 @@ const initialState: CatalogueJurSliceType = { error: null, isGettingArchive: false, relatedGroupFilter: null, + activeCompanyGroup: null, }; const catalogueJurSlice = createSlice({ @@ -22,6 +24,10 @@ const catalogueJurSlice = createSlice({ setRelatedGroupFilter(state, action: PayloadAction) { state.relatedGroupFilter = action.payload; }, + setActiveCompanyGroup(state, action: PayloadAction) { + state.activeCompanyGroup = action.payload; + state.relatedGroupFilter = null + }, }, extraReducers: (builder) => { builder @@ -40,5 +46,6 @@ const catalogueJurSlice = createSlice({ }); }, }); -export const { setIsGettingArchive, setRelatedGroupFilter } = catalogueJurSlice.actions; + +export const { setIsGettingArchive, setRelatedGroupFilter, setActiveCompanyGroup } = catalogueJurSlice.actions; export default catalogueJurSlice.reducer; diff --git a/web/src/store/slices/catalogueJurSlice/types.ts b/web/src/store/slices/catalogueJurSlice/types.ts index 0ed8c2b..53b8cac 100644 --- a/web/src/store/slices/catalogueJurSlice/types.ts +++ b/web/src/store/slices/catalogueJurSlice/types.ts @@ -1,5 +1,6 @@ import type { RelatedGroupOut } from '../../../types/api'; import type { ICatalogueJur } from '../../../types/catalogueJur/catalogueJur'; +import { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; export interface CatalogueJurSliceType { total_groups: number; @@ -8,6 +9,7 @@ export interface CatalogueJurSliceType { error: string | null; isGettingArchive: boolean; relatedGroupFilter?: RelatedGroupOut | null; + activeCompanyGroup?: ICompanyGroup | null; } export interface GetCatalogueJurPropsI { diff --git a/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts b/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts index c298b6a..ce86dad 100644 --- a/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts +++ b/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts @@ -1,5 +1,4 @@ -import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; -import type { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; +import { createSlice } from '@reduxjs/toolkit'; import { getCompanyGroupsThunk } from './thunks'; import type { CompanyGroupSliceType } from './types'; @@ -8,17 +7,12 @@ const initialState: CompanyGroupSliceType = { total_groups: 0, loading: false, error: null, - activeCompanyGroup: null, }; const comGroupsSlice = createSlice({ name: 'company_groups', initialState, - reducers: { - setActiveCompanyGroup(state, action: PayloadAction) { - state.activeCompanyGroup = action.payload; - }, - }, + reducers: {}, extraReducers: (builder) => { builder .addCase(getCompanyGroupsThunk.pending, (state) => { @@ -27,10 +21,6 @@ const comGroupsSlice = createSlice({ }) .addCase(getCompanyGroupsThunk.fulfilled, (state, action) => { state.raw_rows = action.payload; - if (state.activeCompanyGroup?.id) { - const newActiveCompanyGroup = action.payload.find((elem) => elem.id === state.activeCompanyGroup?.id); - state.activeCompanyGroup = newActiveCompanyGroup; - } state.total_groups = action.payload.length; state.loading = false; }) @@ -40,5 +30,4 @@ const comGroupsSlice = createSlice({ }); }, }); -export const { setActiveCompanyGroup } = comGroupsSlice.actions; export default comGroupsSlice.reducer; diff --git a/web/src/store/slices/companyGroupsSlice/types.ts b/web/src/store/slices/companyGroupsSlice/types.ts index 7a49aa3..5f35cfa 100644 --- a/web/src/store/slices/companyGroupsSlice/types.ts +++ b/web/src/store/slices/companyGroupsSlice/types.ts @@ -5,5 +5,4 @@ export interface CompanyGroupSliceType { raw_rows: ICompanyGroup[]; loading: boolean; error: string | null; - activeCompanyGroup?: ICompanyGroup | null; } diff --git a/web/src/types/api.ts b/web/src/types/api.ts index 0956c4f..410a74c 100644 --- a/web/src/types/api.ts +++ b/web/src/types/api.ts @@ -375,6 +375,7 @@ export interface ConsolidationCreate { export interface RelatedGroupOut { id: string; code: string; + crm_id:string, company_group_id: string; kind: 'gsk' | 'gsz'; name: string; diff --git a/web/src/widgets/CataloguGroupTabs/CataloguGroupTabs.tsx b/web/src/widgets/CataloguGroupTabs/CataloguGroupTabs.tsx index 636ea7d..679e474 100644 --- a/web/src/widgets/CataloguGroupTabs/CataloguGroupTabs.tsx +++ b/web/src/widgets/CataloguGroupTabs/CataloguGroupTabs.tsx @@ -12,7 +12,7 @@ interface CataloguGroupTabsI { export type CatalogueGroupTabKey = 'legal_entities' | 'gsk' | 'gsz'; export const CataloguGroupTabs = ({ activeTab, setActiveTab, gskData, gszData }: CataloguGroupTabsI) => { - const activeCompanyGroup = useAppSelector((state) => state.company_groups.activeCompanyGroup); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); return ( { - const activeCompanyGroup = useAppSelector((state) => state.company_groups.activeCompanyGroup); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); const count = activeCompanyGroup?.legal_entities_count ?? 0; const organizationWord = pluralRu(count, ['организация', 'организации', 'организаций']); diff --git a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx index bd865e0..e2193b8 100644 --- a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx +++ b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx @@ -27,12 +27,11 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId const [loadingOfficesOptions, setLoadingOfficesOptions] = useState(false); const [confirmLoading, setConfirmLoading] = useState(false); const [officesOptions, setOfficesOptions] = useState<{ value: string; label: string }[]>([]); - const companyGrops = useAppSelector((state) => state.company_groups.raw_rows); const companyGropsLoading = useAppSelector((state) => state.company_groups.loading); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); const type = Form.useWatch('entity_type', form); - const companyGroupId = Form.useWatch('company_group_id', form); async function getInitialData() { if (jurId) { @@ -51,6 +50,7 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId gsk_id: data.memberships?.find((elem) => elem.kind === 'gsk')?.related_group_id, gsz_id: data.memberships?.find((elem) => elem.kind === 'gsz')?.related_group_id, }); + getRelatedGroupsHandler(data.company_group_id as string); } catch (e) { if (e instanceof ApiError) { notification.error({ description: e.message }); @@ -58,6 +58,11 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId } finally { setInitialDataLoading(false); } + } else { + form.setFieldsValue({ + company_group_id: activeCompanyGroup?.id ?? undefined, + }); + getRelatedGroupsHandler(activeCompanyGroup?.id ?? ''); } } @@ -76,12 +81,12 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId } } - async function getRelatedGroupsHandler() { - if (!companyGroupId) return; + async function getRelatedGroupsHandler(companyId: string) { + if (!companyId) return; setLoadingRelatedGroupsOptions(true); try { - const res = await fetchRelatedGroups(companyGroupId); + const res = await fetchRelatedGroups(companyId); const gsks = res.filter((elem) => elem.kind === 'gsk'); const gszs = res.filter((elem) => elem.kind === 'gsz'); setGskData(gsks); @@ -101,18 +106,25 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId const values = await form.validateFields(); await onOk({ ...values, - kpp: type === 'ИП' ? null : values.kpp?.toString(), + kpp: type === 'ИП' ? null : (values.kpp?.toString() ?? null), inn: jurId ? undefined : values?.inn?.toString(), company_group_id: jurId ? undefined : values.company_group_id, gsz_id: values.gsz_id ? values?.gsz_id : null, gsk_id: values.gsk_id ? values?.gsk_id : null, regional_office_id: values.regional_office_id ? values?.regional_office_id : null, + crm_id: values.crm_id ?? null, }); } catch (e) { if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); + if (e.code === 'INN_EXISTS') { + form.setFields([ + { + name: 'inn', + errors: [e.message], + }, + ]); + } + notification.error({ description: e.message }); } } finally { setConfirmLoading(false); @@ -128,21 +140,13 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId return companyGrops?.map((company) => company && { value: company.id, label: company.name }); }, [companyGrops]); - useEffect(() => { - getInitialData(); - }, [jurId, open]); - useEffect(() => { getOfficesOptionsHandler(); }, []); useEffect(() => { - form.setFieldsValue({ - gsk_id: undefined, - gsz_id: undefined, - }); - getRelatedGroupsHandler(); - }, [companyGroupId]); + getInitialData(); + }, [jurId, open]); return ( = ({ open, onCancel, onOk, jurId label='Альтернативные наименования' extra='Введите синоним и нажмите Enter. Можно добавить несколько значений.'> + diff --git a/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx b/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx index 16efc82..8a86ddb 100644 --- a/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx +++ b/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx @@ -2,9 +2,9 @@ import { FolderOpenOutlined, SearchOutlined } from '@ant-design/icons'; import { Empty, Input, List, Spin, Tag, Typography } from 'antd'; import { useEffect, useMemo, useState } from 'react'; import { useVirtualList } from '../../hooks/useVirtualList'; -import { setActiveCompanyGroup } from '../../store/slices/companyGroupsSlice/companyGroupsSlice'; import { getCompanyGroupsThunk } from '../../store/slices/companyGroupsSlice/thunks'; import { useAppDispatch, useAppSelector } from '../../store/store'; +import { setActiveCompanyGroup } from '../../store/slices/catalogueJurSlice/catalogueJurSlice'; const { Text } = Typography; @@ -13,7 +13,7 @@ export const CompanyGroupsList = () => { const rawRows = useAppSelector((state) => state.company_groups.raw_rows); const loading = useAppSelector((state) => state.company_groups.loading); - const activeCompanyGroup = useAppSelector((state) => state.company_groups.activeCompanyGroup); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); const [query, setQuery] = useState(''); diff --git a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.css b/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.css deleted file mode 100644 index 8dacfcf..0000000 --- a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.css +++ /dev/null @@ -1,7 +0,0 @@ -/* Теги выбранных значений в селектах фильтра шахматки */ -.custom-select-selection-item .ant-select-selection-item { - background-color: #ecfdf3 !important; - color: #1f5f35 !important; - box-shadow: inset 0 0 0 1px #2ea64b38 !important; - border-radius: 999px !important; -} diff --git a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx b/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx index cf58c0c..d6eebba 100644 --- a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx +++ b/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx @@ -6,7 +6,6 @@ import { type OptionType, TreeFilterDropdown } from '../../components/TreeFilter import type { Account, MatrixCompany, Quarter } from '../../types/api'; import { quarterShortLabel } from '../../utils/labels'; import { useNotificationApi } from '../../utils/useNotification'; -import './ConsolidationChessTableFilter.css'; interface ConsolidationChessTableFilterI { companies: string[]; @@ -16,7 +15,6 @@ interface ConsolidationChessTableFilterI { credit: string[]; onCreditChange: (val: string[]) => void; allCompanies: MatrixCompany[]; - /** Год и квартал версии — только для показа: версия задаётся адресом. */ year?: number; quarter?: Quarter; } diff --git a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx index 60d0f58..5cae809 100644 --- a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx +++ b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx @@ -26,9 +26,15 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate const [confirmLoading, setConfirmLoading] = useState(false); const companyGrops = useAppSelector((state) => state.company_groups.raw_rows); const companyGropsLoading = useAppSelector((state) => state.company_groups.loading); + const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); async function getInitialData() { - if (!relatedGroupId) return; + if (!relatedGroupId) { + form.setFieldsValue({ + company_group_id: activeCompanyGroup?.id ?? undefined, + }); + return; + } setInitialDataLoading(true); try { const data = await fetchRelatedGroup(relatedGroupId); @@ -36,7 +42,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate form.setFieldsValue({ crm_id: data?.crm_id, name: data?.name, - created_date: data?.created_date ?? dayjs().format('YYYY-MM-DD'), + created_date: data?.created_date ?? (relatedGroupId ? null : dayjs().format('YYYY-MM-DD')), company_group_id: data?.company_group_id, }); } catch (e) { @@ -53,7 +59,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate try { const { created_date, name, crm_id, company_group_id } = await form.validateFields(); await onOk({ - created_date: created_date ?? dayjs().format('YYYY-MM-DD'), + created_date: created_date ?? (relatedGroupId ? null : dayjs().format('YYYY-MM-DD') ), name, crm_id, company_group_id: relatedGroupId ? undefined : company_group_id, @@ -96,7 +102,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate confirmLoading={confirmLoading}>
- + diff --git a/web/src/widgets/RelatedGroupTable/config.tsx b/web/src/widgets/RelatedGroupTable/config.tsx index 34ebe25..5fb57ee 100644 --- a/web/src/widgets/RelatedGroupTable/config.tsx +++ b/web/src/widgets/RelatedGroupTable/config.tsx @@ -6,13 +6,17 @@ import { store } from '../../store/store'; import type { RelatedGroupOut } from '../../types/api'; export const relateGroupConfig: TableConfig = { rowKey: 'id', - searchableKeys: ['code', 'name', 'members_count', 'created_date'], + searchableKeys: ['code', 'crm_id', 'name', 'members_count', 'created_date'], columns: [ { key: 'code', title: 'ID', features: { search: true, multiselect: true }, }, + { + key: 'crm_id', + title: 'CRM ID', + }, { key: 'name', title: 'Наименование', @@ -35,7 +39,7 @@ export const relateGroupConfig: TableConfig = { key: 'created_date', title: 'Дата создания', render: (val) => { - return new Date(val as string).toLocaleDateString('ru-RU'); + return val ? new Date(val as string).toLocaleDateString('ru-RU') : '—'; }, }, ], -- 2.47.2 From daec128fc37c159f3cd671c98714fa516147f727 Mon Sep 17 00:00:00 2001 From: Grog Date: Mon, 26 Oct 2026 14:11:48 +0300 Subject: [PATCH 2/4] =?UTF-8?q?AURORA-1671:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=88=D0=B8?= =?UTF-8?q?=D0=B1=D0=BA=D0=B8=20crm=5Fid=5Fexists=20=D0=BD=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D1=8F=D0=BC=D1=83=D1=8E=20=D0=B2=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/layouts/CatalogueGroups.tsx | 68 +++++-------------- web/src/layouts/CatalogueJur.tsx | 31 +++------ .../CatalogueJurForm/CatalogueJurForm.tsx | 8 +++ .../CatalogueJurTable/CatalogueJurTable.tsx | 20 ++---- .../CompanyGroupForm/CompanyGroupForm.tsx | 8 +++ .../RelatedGroupForm/RelatedGroupForm.tsx | 14 +++- .../RelatedGroupTable/RelatedGroupTable.tsx | 18 ++--- 7 files changed, 63 insertions(+), 104 deletions(-) diff --git a/web/src/layouts/CatalogueGroups.tsx b/web/src/layouts/CatalogueGroups.tsx index 9028064..897efd3 100644 --- a/web/src/layouts/CatalogueGroups.tsx +++ b/web/src/layouts/CatalogueGroups.tsx @@ -1,7 +1,6 @@ import { PlusOutlined } from '@ant-design/icons'; import { Button, Space } from 'antd'; import { useEffect, useState } from 'react'; -import { ApiError } from '../api/client'; import PageTitle from '../components/PageTitle'; import { createCatalogueJur } from '../services/api/directories/catalogue_jur'; import { createCompanyGroup, fetchRelatedGroups } from '../services/api/directories/company_groups'; @@ -13,7 +12,6 @@ import type { RelatedGroupOut } from '../types/api'; import type { CatalogueJurFormProps } from '../types/catalogueJur/catalogueJur'; import type { CreateCompanyGroupProps } from '../types/companyGroups/companyGroups'; import type { CreateEntityKind, RelatedGroupFormType } from '../types/relatedGroup/relatedGroup'; -import { useNotificationApi } from '../utils/useNotification'; import { CataloguGroupTabs, type CatalogueGroupTabKey } from '../widgets/CataloguGroupTabs/CataloguGroupTabs'; import { CompanyGroupHeader } from '../widgets/CatalogueGroupHeader/CatalogueGroupHeader'; import { CatalogueJurForm } from '../widgets/CatalogueJurForm/CatalogueJurForm'; @@ -26,7 +24,6 @@ import { RelatedGroupTable } from '../widgets/RelatedGroupTable/RelatedGroupTabl export function CatalogueGroup() { const dispatch = useAppDispatch(); - const notification = useNotificationApi(); const isGettingArchive = useAppSelector((state) => state.catalogue_jur.isGettingArchive); @@ -53,55 +50,30 @@ export function CatalogueGroup() { } async function createRelatedGroupHandler(values: RelatedGroupFormType) { if (values.company_group_id) { - try { - await createRelatedGroup(values.company_group_id, { - ...values, - company_group_id: undefined, - }); - getRelatedGroupsHandler(); - setKindForm(null); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await createRelatedGroup(values.company_group_id, { + ...values, + company_group_id: undefined, + }); + getRelatedGroupsHandler(); + setKindForm(null); } } async function createCompanyGroupHandler(values: CreateCompanyGroupProps) { - try { - await createCompanyGroup(values); - dispatch(getCompanyGroupsThunk()); - getRelatedGroupsHandler(); - setKindForm(null); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await createCompanyGroup(values); + dispatch(getCompanyGroupsThunk()); + getRelatedGroupsHandler(); + setKindForm(null); } async function getRelatedGroupsHandler() { if (activeCompanyGroup?.id) { setRelatedGroupLoading(true); - try { - const res = await fetchRelatedGroups(activeCompanyGroup?.id); - const gsks = res.filter((elem) => elem.kind === 'gsk'); - const gszs = res.filter((elem) => elem.kind === 'gsz'); - setGskData(gsks); - setGszData(gszs); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } finally { - setRelatedGroupLoading(false); - } + const res = await fetchRelatedGroups(activeCompanyGroup?.id); + const gsks = res.filter((elem) => elem.kind === 'gsk'); + const gszs = res.filter((elem) => elem.kind === 'gsz'); + setGskData(gsks); + setGszData(gszs); + setRelatedGroupLoading(false); } } @@ -197,9 +169,7 @@ export function CatalogueGroup() { onCancel={() => { setKindForm(null); }} - onOk={async (values) => { - await createRelatedGroupHandler(values); - }} + onOk={createRelatedGroupHandler} /> )} {kindForm === 'gk' && ( @@ -208,9 +178,7 @@ export function CatalogueGroup() { onCancel={() => { setKindForm(null); }} - onOk={async (values) => { - await createCompanyGroupHandler(values); - }} + onOk={createCompanyGroupHandler} /> )}
diff --git a/web/src/layouts/CatalogueJur.tsx b/web/src/layouts/CatalogueJur.tsx index 3b2ac3b..8919f11 100644 --- a/web/src/layouts/CatalogueJur.tsx +++ b/web/src/layouts/CatalogueJur.tsx @@ -1,41 +1,30 @@ import { PlusOutlined } from '@ant-design/icons'; import { Button, Space } from 'antd'; import { useState } from 'react'; -import { ApiError } from '../api/client'; import PageTitle from '../components/PageTitle'; import { createCatalogueJur } from '../services/api/directories/catalogue_jur'; import { getCatalogueJurThunk } from '../store/slices/catalogueJurSlice/thunks'; import { useAppDispatch, useAppSelector } from '../store/store'; import type { CatalogueJurFormProps } from '../types/catalogueJur/catalogueJur'; -import { useNotificationApi } from '../utils/useNotification'; import { CatalogueJurForm } from '../widgets/CatalogueJurForm/CatalogueJurForm'; import { CatalogueJurTable } from '../widgets/CatalogueJurTable/CatalogueJurTable'; export function CatalogueJur() { const dispatch = useAppDispatch(); - const notification = useNotificationApi(); const isGettingArchive = useAppSelector((state) => state.catalogue_jur.isGettingArchive); const [createFormOpen, setCreateFormOpen] = useState(false); const outside_group = true; async function createJurHandler(values: CatalogueJurFormProps) { - try { - await createCatalogueJur(values); - dispatch( - getCatalogueJurThunk({ - closed: isGettingArchive, - outside_group: outside_group, - }), - ); - setCreateFormOpen(false); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await createCatalogueJur(values); + dispatch( + getCatalogueJurThunk({ + closed: isGettingArchive, + outside_group: outside_group, + }), + ); + setCreateFormOpen(false); } return ( @@ -59,9 +48,7 @@ export function CatalogueJur() { onCancel={() => { setCreateFormOpen(false); }} - onOk={async (values) => { - await createJurHandler(values); - }} + onOk={createJurHandler} /> )} diff --git a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx index e2193b8..a54cad8 100644 --- a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx +++ b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx @@ -124,6 +124,14 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId }, ]); } + if (e.code === 'CRM_ID_EXISTS') { + form.setFields([ + { + name: 'crm_id', + errors: [e.message], + }, + ]); + } notification.error({ description: e.message }); } } finally { diff --git a/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx b/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx index 6149d2d..9dfe714 100644 --- a/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx +++ b/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx @@ -122,21 +122,13 @@ export function CatalogueJurTable({ outside_group, tabsComponent }: CatalogueJur } async function editJurHandler(values: CatalogueJurFormProps) { - try { - await editCatalogueJur(jurId, values); - getCatalogueJur(); - closeEditCatalogueJurHandler(); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await editCatalogueJur(jurId, values); + getCatalogueJur(); + closeEditCatalogueJurHandler(); } useEffect(() => { - getCatalogueJur(); + getCatalogueJur(); }, [isGettingArchive, activeCompanyGroup, outside_group]); const extraColumns: ColumnsType = useMemo( @@ -327,9 +319,7 @@ export function CatalogueJurTable({ outside_group, tabsComponent }: CatalogueJur onCancel={() => { closeEditCatalogueJurHandler(); }} - onOk={async (values) => { - await editJurHandler(values); - }} + onOk={editJurHandler} /> )} diff --git a/web/src/widgets/CompanyGroupForm/CompanyGroupForm.tsx b/web/src/widgets/CompanyGroupForm/CompanyGroupForm.tsx index c5274e3..76e31f6 100644 --- a/web/src/widgets/CompanyGroupForm/CompanyGroupForm.tsx +++ b/web/src/widgets/CompanyGroupForm/CompanyGroupForm.tsx @@ -49,6 +49,14 @@ export const CompanyGroupForm: React.FC = ({ open, onCancel, onOk }) => { }); } catch (e) { if (e instanceof ApiError) { + if (e.code === 'CRM_ID_EXISTS') { + form.setFields([ + { + name: 'crm_id', + errors: [e.message], + }, + ]); + } notification.error({ description: e.message, }); diff --git a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx index 5cae809..ec63a23 100644 --- a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx +++ b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx @@ -59,7 +59,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate try { const { created_date, name, crm_id, company_group_id } = await form.validateFields(); await onOk({ - created_date: created_date ?? (relatedGroupId ? null : dayjs().format('YYYY-MM-DD') ), + created_date: created_date ?? (relatedGroupId ? null : dayjs().format('YYYY-MM-DD')), name, crm_id, company_group_id: relatedGroupId ? undefined : company_group_id, @@ -67,6 +67,14 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate }); } catch (e) { if (e instanceof ApiError) { + if (e.code === 'CRM_ID_EXISTS') { + form.setFields([ + { + name: 'crm_id', + errors: [e.message], + }, + ]); + } notification.error({ description: e.message, }); @@ -101,8 +109,8 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate loading={initialDataLoading} confirmLoading={confirmLoading}> - - + + diff --git a/web/src/widgets/RelatedGroupTable/RelatedGroupTable.tsx b/web/src/widgets/RelatedGroupTable/RelatedGroupTable.tsx index e591330..f3a842a 100644 --- a/web/src/widgets/RelatedGroupTable/RelatedGroupTable.tsx +++ b/web/src/widgets/RelatedGroupTable/RelatedGroupTable.tsx @@ -62,17 +62,9 @@ export function RelatedGroupTable({ tabsComponent, data, loading, getData, activ } async function editRelatedGroupHandler(values: RelatedGroupFormType) { - try { - await editRelatedGroup(groupId, values); - getData(); - closeEditRelatedGroupHandler(); - } catch (e) { - if (e instanceof ApiError) { - notification.error({ - description: e.message, - }); - } - } + await editRelatedGroup(groupId, values); + getData(); + closeEditRelatedGroupHandler(); } const extraColumns: ColumnsType = useMemo( @@ -167,9 +159,7 @@ export function RelatedGroupTable({ tabsComponent, data, loading, getData, activ onCancel={() => { closeEditRelatedGroupHandler(); }} - onOk={async (values) => { - await editRelatedGroupHandler(values); - }} + onOk={editRelatedGroupHandler} /> )} {deleteModalOpen && ( -- 2.47.2 From 630a616bf17e3d31cd38757f184fb47cbed8fae4 Mon Sep 17 00:00:00 2001 From: Grog Date: Mon, 26 Oct 2026 14:14:50 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.css | 2 +- web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts | 4 ++-- web/src/store/slices/catalogueJurSlice/types.ts | 2 +- web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts | 2 +- web/src/types/api.ts | 2 +- web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx | 2 +- web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx | 2 +- web/src/widgets/RelatedGroupTable/config.tsx | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/web/src/App.css b/web/src/App.css index facf75a..4f7a3bb 100644 --- a/web/src/App.css +++ b/web/src/App.css @@ -3,4 +3,4 @@ color: #1f5f35 !important; box-shadow: inset 0 0 0 1px #2ea64b38 !important; border-radius: 999px !important; -} \ No newline at end of file +} diff --git a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts index d381927..8662ee1 100644 --- a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts +++ b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts @@ -1,8 +1,8 @@ import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; import type { RelatedGroupOut } from '../../../types/api'; +import type { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; import { getCatalogueJurThunk } from './thunks'; import type { CatalogueJurSliceType } from './types'; -import { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; const initialState: CatalogueJurSliceType = { raw_rows: [], @@ -26,7 +26,7 @@ const catalogueJurSlice = createSlice({ }, setActiveCompanyGroup(state, action: PayloadAction) { state.activeCompanyGroup = action.payload; - state.relatedGroupFilter = null + state.relatedGroupFilter = null; }, }, extraReducers: (builder) => { diff --git a/web/src/store/slices/catalogueJurSlice/types.ts b/web/src/store/slices/catalogueJurSlice/types.ts index 53b8cac..7227c33 100644 --- a/web/src/store/slices/catalogueJurSlice/types.ts +++ b/web/src/store/slices/catalogueJurSlice/types.ts @@ -1,6 +1,6 @@ import type { RelatedGroupOut } from '../../../types/api'; import type { ICatalogueJur } from '../../../types/catalogueJur/catalogueJur'; -import { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; +import type { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; export interface CatalogueJurSliceType { total_groups: number; diff --git a/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts b/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts index ce86dad..c56a483 100644 --- a/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts +++ b/web/src/store/slices/companyGroupsSlice/companyGroupsSlice.ts @@ -1,4 +1,4 @@ -import { createSlice } from '@reduxjs/toolkit'; +import { createSlice } from '@reduxjs/toolkit'; import { getCompanyGroupsThunk } from './thunks'; import type { CompanyGroupSliceType } from './types'; diff --git a/web/src/types/api.ts b/web/src/types/api.ts index 410a74c..d304177 100644 --- a/web/src/types/api.ts +++ b/web/src/types/api.ts @@ -375,7 +375,7 @@ export interface ConsolidationCreate { export interface RelatedGroupOut { id: string; code: string; - crm_id:string, + crm_id: string; company_group_id: string; kind: 'gsk' | 'gsz'; name: string; diff --git a/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx b/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx index 8a86ddb..47d0caf 100644 --- a/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx +++ b/web/src/widgets/CompanyGroupsList/CompanyGroupsList.tsx @@ -2,9 +2,9 @@ import { FolderOpenOutlined, SearchOutlined } from '@ant-design/icons'; import { Empty, Input, List, Spin, Tag, Typography } from 'antd'; import { useEffect, useMemo, useState } from 'react'; import { useVirtualList } from '../../hooks/useVirtualList'; +import { setActiveCompanyGroup } from '../../store/slices/catalogueJurSlice/catalogueJurSlice'; import { getCompanyGroupsThunk } from '../../store/slices/companyGroupsSlice/thunks'; import { useAppDispatch, useAppSelector } from '../../store/store'; -import { setActiveCompanyGroup } from '../../store/slices/catalogueJurSlice/catalogueJurSlice'; const { Text } = Typography; diff --git a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx index ec63a23..84deb75 100644 --- a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx +++ b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx @@ -109,7 +109,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate loading={initialDataLoading} confirmLoading={confirmLoading}> - + diff --git a/web/src/widgets/RelatedGroupTable/config.tsx b/web/src/widgets/RelatedGroupTable/config.tsx index 5fb57ee..c4b72af 100644 --- a/web/src/widgets/RelatedGroupTable/config.tsx +++ b/web/src/widgets/RelatedGroupTable/config.tsx @@ -39,7 +39,7 @@ export const relateGroupConfig: TableConfig = { key: 'created_date', title: 'Дата создания', render: (val) => { - return val ? new Date(val as string).toLocaleDateString('ru-RU') : '—'; + return val ? new Date(val as string).toLocaleDateString('ru-RU') : '—'; }, }, ], -- 2.47.2 From 3aad67051011991f80369370129e0acef3089e0d Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Tue, 27 Oct 2026 00:00:47 +0400 Subject: [PATCH 4/4] =?UTF-8?q?fix(web):=20=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B8=20=E2=80=94=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=BD=D0=BD=D0=B0=D1=8F=20=D0=93=D0=9A,=20?= =?UTF-8?q?=D1=81=D1=87=D1=91=D1=82=D1=87=D0=B8=D0=BA=20=D0=AE=D0=9B,=20?= =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D1=83=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=B5=D0=B9=20(=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20#179,=20?= =?UTF-8?q?AURORA-1671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Страница ГК: снова выбирается первая ГК списка; список ЮЛ без выбранной ГК не запрашивается (иначе уходил запрос по всем ГК), «ЮЛ вне ГК» грузится без ГК. - Выбранная ГК обновляется после перезагрузки списка ГК — счётчик ЮЛ в шапке и на вкладке после создания/переноса/вывода ЮЛ. - Загрузка ГСК/ГСЗ: try/finally — ошибка не оставляет вечный спиннер. - Форма ЮЛ: INVALID_INN/INVALID_KPP/INN_EXISTS/CRM_ID_EXISTS — у поля; КПП приводится к верхнему регистру при вводе. - crm_id ГСК/ГСЗ — string | null; колонка «ID в CRM»; LE_PAGE вместо литерала; возвращён комментарий в фильтре шахматки. Co-Authored-By: Claude Opus 5.5 --- web/src/App.css | 1 + web/src/layouts/CatalogueGroups.tsx | 31 ++++++++++++++---- .../services/api/directories/catalogue_jur.ts | 3 +- .../catalogueJurSlice/catalogueJurSlice.ts | 7 ++++ web/src/types/api.ts | 3 +- web/src/types/relatedGroup/relatedGroup.ts | 2 +- .../CatalogueJurForm/CatalogueJurForm.tsx | 32 +++++++++---------- .../CatalogueJurTable/CatalogueJurTable.tsx | 5 ++- .../ConsolidationChessTableFilter.tsx | 1 + .../RelatedGroupForm/RelatedGroupForm.tsx | 2 +- web/src/widgets/RelatedGroupTable/config.tsx | 2 +- 11 files changed, 60 insertions(+), 29 deletions(-) diff --git a/web/src/App.css b/web/src/App.css index 4f7a3bb..606dd57 100644 --- a/web/src/App.css +++ b/web/src/App.css @@ -1,3 +1,4 @@ +/* Теги выбранных значений в селектах: фильтр шахматки, синонимы ЮЛ */ .custom-select-selection-item .ant-select-selection-item { background-color: #ecfdf3 !important; color: #1f5f35 !important; diff --git a/web/src/layouts/CatalogueGroups.tsx b/web/src/layouts/CatalogueGroups.tsx index 897efd3..6d712ea 100644 --- a/web/src/layouts/CatalogueGroups.tsx +++ b/web/src/layouts/CatalogueGroups.tsx @@ -1,10 +1,12 @@ import { PlusOutlined } from '@ant-design/icons'; import { Button, Space } from 'antd'; import { useEffect, useState } from 'react'; +import { ApiError } from '../api/client'; import PageTitle from '../components/PageTitle'; import { createCatalogueJur } from '../services/api/directories/catalogue_jur'; import { createCompanyGroup, fetchRelatedGroups } from '../services/api/directories/company_groups'; import { createRelatedGroup } from '../services/api/directories/related-groups'; +import { setActiveCompanyGroup } from '../store/slices/catalogueJurSlice/catalogueJurSlice'; import { getCatalogueJurThunk } from '../store/slices/catalogueJurSlice/thunks'; import { getCompanyGroupsThunk } from '../store/slices/companyGroupsSlice/thunks'; import { useAppDispatch, useAppSelector } from '../store/store'; @@ -12,6 +14,7 @@ import type { RelatedGroupOut } from '../types/api'; import type { CatalogueJurFormProps } from '../types/catalogueJur/catalogueJur'; import type { CreateCompanyGroupProps } from '../types/companyGroups/companyGroups'; import type { CreateEntityKind, RelatedGroupFormType } from '../types/relatedGroup/relatedGroup'; +import { useNotificationApi } from '../utils/useNotification'; import { CataloguGroupTabs, type CatalogueGroupTabKey } from '../widgets/CataloguGroupTabs/CataloguGroupTabs'; import { CompanyGroupHeader } from '../widgets/CatalogueGroupHeader/CatalogueGroupHeader'; import { CatalogueJurForm } from '../widgets/CatalogueJurForm/CatalogueJurForm'; @@ -24,6 +27,7 @@ import { RelatedGroupTable } from '../widgets/RelatedGroupTable/RelatedGroupTabl export function CatalogueGroup() { const dispatch = useAppDispatch(); + const notification = useNotificationApi(); const isGettingArchive = useAppSelector((state) => state.catalogue_jur.isGettingArchive); @@ -35,6 +39,7 @@ export function CatalogueGroup() { const [gszData, setGszData] = useState([]); const activeCompanyGroup = useAppSelector((state) => state.catalogue_jur.activeCompanyGroup); const relatedGroupFilter = useAppSelector((state) => state.catalogue_jur.relatedGroupFilter); + const rawRows = useAppSelector((state) => state.company_groups.raw_rows); async function createJurHandler(values: CatalogueJurFormProps) { await createCatalogueJur(values); @@ -68,12 +73,19 @@ export function CatalogueGroup() { async function getRelatedGroupsHandler() { if (activeCompanyGroup?.id) { setRelatedGroupLoading(true); - const res = await fetchRelatedGroups(activeCompanyGroup?.id); - const gsks = res.filter((elem) => elem.kind === 'gsk'); - const gszs = res.filter((elem) => elem.kind === 'gsz'); - setGskData(gsks); - setGszData(gszs); - setRelatedGroupLoading(false); + try { + const res = await fetchRelatedGroups(activeCompanyGroup?.id); + const gsks = res.filter((elem) => elem.kind === 'gsk'); + const gszs = res.filter((elem) => elem.kind === 'gsz'); + setGskData(gsks); + setGszData(gszs); + } catch (e) { + if (e instanceof ApiError) { + notification.error({ description: e.message }); + } + } finally { + setRelatedGroupLoading(false); + } } } @@ -81,6 +93,13 @@ export function CatalogueGroup() { getRelatedGroupsHandler(); }, [activeCompanyGroup]); + // Без выбранной ГК таблица ЮЛ не грузится — выбираем первую ГК списка + useEffect(() => { + if (!activeCompanyGroup && rawRows?.length) { + dispatch(setActiveCompanyGroup(rawRows[0])); + } + }, [rawRows, activeCompanyGroup, dispatch]); + useEffect(() => { setActiveTab('legal_entities'); }, [relatedGroupFilter]); diff --git a/web/src/services/api/directories/catalogue_jur.ts b/web/src/services/api/directories/catalogue_jur.ts index 33d3d8f..9b1d30a 100644 --- a/web/src/services/api/directories/catalogue_jur.ts +++ b/web/src/services/api/directories/catalogue_jur.ts @@ -7,9 +7,10 @@ import type { MoveCatalogueJurProps, WithdrawCatalogueJurProps, } from '../../../types/catalogueJur/catalogueJur'; +import { LE_PAGE } from './company_groups'; export async function fetchCatalogueJur(params: GetCatalogueJurPropsI) { - const res = await api.get>('/directories/legal-entities', { limit: 200, offset: 0, ...params }); + const res = await api.get>('/directories/legal-entities', { limit: LE_PAGE, offset: 0, ...params }); return res; } diff --git a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts index 8662ee1..7abf90b 100644 --- a/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts +++ b/web/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts @@ -1,6 +1,7 @@ import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; import type { RelatedGroupOut } from '../../../types/api'; import type { ICompanyGroup } from '../../../types/companyGroups/companyGroups'; +import { getCompanyGroupsThunk } from '../companyGroupsSlice/thunks'; import { getCatalogueJurThunk } from './thunks'; import type { CatalogueJurSliceType } from './types'; @@ -43,6 +44,12 @@ const catalogueJurSlice = createSlice({ .addCase(getCatalogueJurThunk.rejected, (state, action) => { state.error = action.payload ?? 'Неизвестная ошибка'; state.loading = false; + }) + // Выбранная ГК — копия строки списка ГК: после перезагрузки списка берём свежую (счётчик ЮЛ в шапке и вкладке) + .addCase(getCompanyGroupsThunk.fulfilled, (state, action) => { + if (state.activeCompanyGroup?.id) { + state.activeCompanyGroup = action.payload.find((elem) => elem.id === state.activeCompanyGroup?.id) ?? null; + } }); }, }); diff --git a/web/src/types/api.ts b/web/src/types/api.ts index d304177..7e36dd4 100644 --- a/web/src/types/api.ts +++ b/web/src/types/api.ts @@ -375,7 +375,7 @@ export interface ConsolidationCreate { export interface RelatedGroupOut { id: string; code: string; - crm_id: string; + crm_id: string | null; company_group_id: string; kind: 'gsk' | 'gsz'; name: string; @@ -390,7 +390,6 @@ export interface RelatedGroupMemberOut { } export interface RelatedGroupDetail extends RelatedGroupOut { members: RelatedGroupMemberOut[]; - crm_id: string; } export interface LegalEntityBrief { id: string; diff --git a/web/src/types/relatedGroup/relatedGroup.ts b/web/src/types/relatedGroup/relatedGroup.ts index 7472809..82cfb1c 100644 --- a/web/src/types/relatedGroup/relatedGroup.ts +++ b/web/src/types/relatedGroup/relatedGroup.ts @@ -1,7 +1,7 @@ export type RelatedGroupFormType = { name: string; created_date: string | null; - crm_id: string; + crm_id: string | null; kind?: 'gsk' | 'gsz'; company_group_id?: string; }; diff --git a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx index a54cad8..2a78176 100644 --- a/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx +++ b/web/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx @@ -17,6 +17,14 @@ type Props = { jurId?: string; }; +// Ошибки сервера, относящиеся к одному полю, показываем у этого поля +const FIELD_BY_ERROR_CODE: Record = { + INN_EXISTS: 'inn', + INVALID_INN: 'inn', + INVALID_KPP: 'kpp', + CRM_ID_EXISTS: 'crm_id', +}; + export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId }) => { const [form] = Form.useForm(); const notification = useNotificationApi(); @@ -116,21 +124,9 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId }); } catch (e) { if (e instanceof ApiError) { - if (e.code === 'INN_EXISTS') { - form.setFields([ - { - name: 'inn', - errors: [e.message], - }, - ]); - } - if (e.code === 'CRM_ID_EXISTS') { - form.setFields([ - { - name: 'crm_id', - errors: [e.message], - }, - ]); + const field = e.code ? FIELD_BY_ERROR_CODE[e.code] : undefined; + if (field) { + form.setFields([{ name: field, errors: [e.message] }]); } notification.error({ description: e.message }); } @@ -194,7 +190,11 @@ export const CatalogueJurForm: React.FC = ({ open, onCancel, onOk, jurId - + value?.toUpperCase()} + rules={[{ pattern: /^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$/, message: 'Некорректный формат' }]}> diff --git a/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx b/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx index 9dfe714..94c3112 100644 --- a/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx +++ b/web/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx @@ -128,7 +128,10 @@ export function CatalogueJurTable({ outside_group, tabsComponent }: CatalogueJur } useEffect(() => { - getCatalogueJur(); + // «ЮЛ вне ГК» грузится без выбранной ГК; список ГК — только по выбранной (без неё запрос ушёл бы по всем ГК) + if (outside_group || activeCompanyGroup?.id) { + getCatalogueJur(); + } }, [isGettingArchive, activeCompanyGroup, outside_group]); const extraColumns: ColumnsType = useMemo( diff --git a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx b/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx index d6eebba..d9ab17b 100644 --- a/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx +++ b/web/src/widgets/ConsolidationChessTableFilter/ConsolidationChessTableFilter.tsx @@ -15,6 +15,7 @@ interface ConsolidationChessTableFilterI { credit: string[]; onCreditChange: (val: string[]) => void; allCompanies: MatrixCompany[]; + /** Год и квартал версии — только для показа: версия задаётся адресом. */ year?: number; quarter?: Quarter; } diff --git a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx index 84deb75..d4ed42e 100644 --- a/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx +++ b/web/src/widgets/RelatedGroupForm/RelatedGroupForm.tsx @@ -42,7 +42,7 @@ export const RelatedGroupForm: React.FC = ({ open, onCancel, onOk, relate form.setFieldsValue({ crm_id: data?.crm_id, name: data?.name, - created_date: data?.created_date ?? (relatedGroupId ? null : dayjs().format('YYYY-MM-DD')), + created_date: data?.created_date ?? null, company_group_id: data?.company_group_id, }); } catch (e) { diff --git a/web/src/widgets/RelatedGroupTable/config.tsx b/web/src/widgets/RelatedGroupTable/config.tsx index c4b72af..fe4f8cb 100644 --- a/web/src/widgets/RelatedGroupTable/config.tsx +++ b/web/src/widgets/RelatedGroupTable/config.tsx @@ -15,7 +15,7 @@ export const relateGroupConfig: TableConfig = { }, { key: 'crm_id', - title: 'CRM ID', + title: 'ID в CRM', }, { key: 'name', -- 2.47.2