From 633c4d3fedcbf4b8453c9261334c3fe7f37aeb00 Mon Sep 17 00:00:00 2001 From: Grog Date: Mon, 26 Oct 2026 13:35:05 +0300 Subject: [PATCH] =?UTF-8?q?AURORA-1671:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=D1=83=20?= =?UTF-8?q?=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') : '—'; }, }, ],