diff --git a/src/layouts/CatalogueJur.tsx b/src/layouts/CatalogueJur.tsx
index b3e9986..018ebed 100644
--- a/src/layouts/CatalogueJur.tsx
+++ b/src/layouts/CatalogueJur.tsx
@@ -1,7 +1,32 @@
+import { Button, Space } from "antd";
import PageTitle from "../components/PageTitle";
import { CatalogueJurTable } from "../widgets/CatalogueJurTable/CatalogueJurTable";
+import { PlusOutlined } from "@ant-design/icons";
+import { useState } from "react";
+import { useAppDispatch, useAppSelector } from "../store/store";
+import { CatalogueJurForm } from "../widgets/CatalogueJurForm/CatalogueJurForm";
+import { getCatalogueJurThunk } from "../store/slices/catalogueJurSlice/thunks";
+import { CatalogueJurFormProps } from "../types/catalogueJur/catalogueJur";
+import { createCatalogueJur } from "../services/api/directories/catalogue_jur";
export function CatalogueJur() {
+ const dispatch = useAppDispatch();
+ const isGettingArchive = useAppSelector(
+ (state) => state.catalogue_jur.isGettingArchive,
+ );
+
+ const [createFormOpen, setCreateFormOpen] = useState(false);
+
+ async function createJurHandler(values: CatalogueJurFormProps) {
+ try {
+ await createCatalogueJur(values);
+ dispatch(
+ getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
+ );
+ setCreateFormOpen(false);
+ } catch {}
+ }
+
return (
-
+
+
+ }
+ onClick={() => setCreateFormOpen(true)}
+ >
+ Создать ЮЛ
+
+
+ {createFormOpen && (
+
{
+ setCreateFormOpen(false);
+ }}
+ onOk={(values) => {
+ createJurHandler(values);
+ }}
+ />
+ )}
);
}
diff --git a/src/services/api/directories/catalogue_jur.ts b/src/services/api/directories/catalogue_jur.ts
index 57b23e6..ab72517 100644
--- a/src/services/api/directories/catalogue_jur.ts
+++ b/src/services/api/directories/catalogue_jur.ts
@@ -2,10 +2,9 @@ import { api } from "../../../api/client";
import {
GetCatalogueJurPropsI,
} from "../../../store/slices/catalogueJurSlice/types";
-import { ICatalogueJur } from "../../../types/catalogueJur/catalogueJur";
+import { CatalogueJurFormProps, ICatalogueJur, MoveCatalogueJurProps, WithdrawCatalogueJurProps } from "../../../types/catalogueJur/catalogueJur";
export async function fetchCatalogueJur(params: GetCatalogueJurPropsI) {
- // #TODO поменять на outside_group=true
const res = await api.get(
"/directories/legal-entities",
params,
@@ -22,3 +21,40 @@ export async function fetchOneCatalogueJur(
);
return res;
}
+
+
+export async function moveCatalogueJur(
+ entityId: string,
+ body: MoveCatalogueJurProps,
+): Promise {
+ return api.post(
+ `/directories/legal-entities/${entityId}/move`,
+ body,
+ );
+}
+export async function withdrawCatalogueJur(
+ entityId: string,
+ body: WithdrawCatalogueJurProps,
+): Promise {
+ return api.post(
+ `/directories/legal-entities/${entityId}/withdraw`,
+ body,
+ );
+}
+export async function createCatalogueJur(
+ body: CatalogueJurFormProps,
+): Promise {
+ return api.post(
+ `/directories/legal-entities`,
+ body,
+ );
+}
+export async function editCatalogueJur(
+ entityId: string,
+ body: CatalogueJurFormProps,
+): Promise {
+ return api.patch(
+ `/directories/legal-entities/${entityId}`,
+ body,
+ );
+}
\ No newline at end of file
diff --git a/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts b/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts
index 262ccb4..24bce55 100644
--- a/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts
+++ b/src/store/slices/catalogueJurSlice/catalogueJurSlice.ts
@@ -1,20 +1,23 @@
-import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
-import { useSelector } from "react-redux";
-import { Config } from "../../../conf/config";
-import {CatalogueJurSliceType } from "./types";
+import { createSlice, PayloadAction } from "@reduxjs/toolkit";
+import { CatalogueJurSliceType } from "./types";
import { getCatalogueJurThunk } from "./thunks";
-const initialState:CatalogueJurSliceType = {
+const initialState: CatalogueJurSliceType = {
raw_rows: [],
total_groups: 0,
loading: false,
error: null,
+ isGettingArchive: false,
};
const catalogueJurSlice = createSlice({
name: "catalogue_jur",
initialState,
- reducers: {},
+ reducers: {
+ setIsGettingArchive(state, action: PayloadAction) {
+ state.isGettingArchive = action.payload;
+ },
+ },
extraReducers: (builder) => {
builder
.addCase(getCatalogueJurThunk.pending, (state, _) => {
@@ -32,5 +35,5 @@ const catalogueJurSlice = createSlice({
});
},
});
-
+export const { setIsGettingArchive } = catalogueJurSlice.actions;
export default catalogueJurSlice.reducer;
diff --git a/src/store/slices/catalogueJurSlice/types.ts b/src/store/slices/catalogueJurSlice/types.ts
index b19fb4c..2010c66 100644
--- a/src/store/slices/catalogueJurSlice/types.ts
+++ b/src/store/slices/catalogueJurSlice/types.ts
@@ -5,6 +5,7 @@ export interface CatalogueJurSliceType{
raw_rows: ICatalogueJur[];
loading: boolean;
error: string | null;
+ isGettingArchive:boolean
}
diff --git a/src/types/catalogueJur/catalogueJur.ts b/src/types/catalogueJur/catalogueJur.ts
index ae39d83..bbd6840 100644
--- a/src/types/catalogueJur/catalogueJur.ts
+++ b/src/types/catalogueJur/catalogueJur.ts
@@ -1,13 +1,13 @@
export interface ICatalogueJur {
id: string;
inn: string;
- kpp: string | null;
- crm_id: string | null;
- entity_type: string;
+ kpp?: string;
+ crm_id?: string;
+ entity_type: "ЮЛ" | "ИП";
name: string;
- company_group_id: string | null;
+ company_group_id?: string;
company_group_name: string | null;
- regional_office_id: string | null;
+ regional_office_id?: string;
close_date: Date;
valid_from: Date;
created_at: Date;
@@ -15,10 +15,38 @@ export interface ICatalogueJur {
outside_group: boolean;
closed: boolean | string;
memberships?: unknown[];
- aliases?: unknown[];
+ aliases?: JurAlliase[];
regional_office: {
id: string;
name: string;
is_head_office: boolean;
};
}
+
+export type JurAlliase = {
+ alias: string;
+ created_at: Date;
+ id: string;
+ normalized_alias: string;
+};
+
+export type MoveCatalogueJurProps = {
+ company_group_id: string;
+ effective_date: string;
+};
+export type WithdrawCatalogueJurProps = {
+ event: "CLOSE" | "REMOVE_FROM_GROUP";
+ effective_date: string;
+ comment: string;
+};
+
+export type CatalogueJurFormProps = {
+ inn?: string;
+ kpp?: string;
+ crm_id: string;
+ entity_type: "ЮЛ" | "ИП";
+ name: string;
+ aliases?: string[] | {value:string, label:string}[];
+ company_group_id?: string;
+ regional_office_id?: string;
+};
diff --git a/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx b/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx
new file mode 100644
index 0000000..41ff66a
--- /dev/null
+++ b/src/widgets/CatalogueJurForm/CatalogueJurForm.tsx
@@ -0,0 +1,217 @@
+import React, { useCallback, useEffect, useState } from "react";
+import { Modal, Form, Input, Select, Row, Col, InputNumber } from "antd";
+import { CatalogueJurFormProps } from "../../types/catalogueJur/catalogueJur";
+import { useAppDispatch, useAppSelector } from "../../store/store";
+import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
+import { api } from "../../api/client";
+import { RegionalOffice } from "../../api/types";
+import { useAsyncData } from "../Admin/hooks";
+import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
+
+type Props = {
+ open: boolean;
+ onCancel: () => void;
+ onOk: (values: CatalogueJurFormProps) => void | Promise;
+ jurId?: string;
+};
+
+export const CatalogueJurForm: React.FC = ({
+ open,
+ onCancel,
+ onOk,
+ jurId,
+}) => {
+ const [form] = Form.useForm();
+ const dispatch = useAppDispatch();
+ const loadOffices = useCallback(
+ () => api.get("/directories/regional-offices"),
+ [],
+ );
+ const offices = useAsyncData(loadOffices);
+ const type = Form.useWatch("entity_type", form);
+
+ const { raw_rows, loading } = useAppSelector((state) => state.company_groups);
+ const [initialDataLoading, setInitialDataLoading] = useState(false);
+
+ async function getInitialData() {
+ setInitialDataLoading(true);
+ if (jurId) {
+ const data = await fetchOneCatalogueJur(jurId);
+ form.setFieldsValue({
+ name: data?.name,
+ company_group_id: data?.company_group_id,
+ aliases: data?.aliases?.map((aliase) => aliase.alias),
+ crm_id: data?.crm_id,
+ entity_type: data?.entity_type,
+ inn: data.inn,
+ kpp: data?.kpp,
+ regional_office_id: data?.regional_office_id,
+ });
+ }
+ setInitialDataLoading(false);
+ }
+
+ const handleOk = async () => {
+ try {
+ const values = await form.validateFields();
+ await onOk({
+ ...values,
+ kpp: type === "ИП" ? undefined : values.kpp?.toString(),
+ inn: jurId ? undefined : values?.inn?.toString(),
+ company_group_id: jurId ? undefined : values.company_group_id,
+ });
+ } catch {
+ return;
+ }
+ };
+
+ const handleCancel = () => {
+ form.resetFields();
+ onCancel();
+ };
+
+ useEffect(() => {
+ if (open && raw_rows.length === 0 && !loading) {
+ dispatch(getCompanyGroupsThunk());
+ }
+ }, [open, raw_rows.length, loading, dispatch]);
+
+ useEffect(() => {
+ if (!!jurId) {
+ getInitialData();
+ }
+ }, [open]);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx b/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx
index ee2fe59..9df753c 100644
--- a/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx
+++ b/src/widgets/CatalogueJurTable/CatalogueJurTable.tsx
@@ -18,18 +18,37 @@ import {
SwapOutlined,
} from "@ant-design/icons";
import { useAppDispatch, useAppSelector } from "../../store/store";
-import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
import { useTableFilters } from "../../components/GenericTable/useTableFilters";
-import { ICatalogueJur } from "../../types/catalogueJur/catalogueJur";
+import {
+ CatalogueJurFormProps,
+ ICatalogueJur,
+ MoveCatalogueJurProps,
+ WithdrawCatalogueJurProps,
+} from "../../types/catalogueJur/catalogueJur";
import { getCatalogueJurThunk } from "../../store/slices/catalogueJurSlice/thunks";
import { MoveCatalogueJurForm } from "../MoveCatalogueJurForm/MoveCatalogueJurForm";
+import {
+ editCatalogueJur,
+ moveCatalogueJur,
+ withdrawCatalogueJur,
+} from "../../services/api/directories/catalogue_jur";
+import { WithdrawCatalogueJurForm } from "../WithdrawCatalogueJurForm/WithdrawCatalogueJurForm";
+import { setIsGettingArchive } from "../../store/slices/catalogueJurSlice/catalogueJurSlice";
+import { CatalogueJurForm } from "../CatalogueJurForm/CatalogueJurForm";
export function CatalogueJurTable() {
const navigate = useNavigate();
const dispatch = useAppDispatch();
const rawRows = useAppSelector((state) => state.catalogue_jur.raw_rows);
const loading = useAppSelector((state) => state.catalogue_jur.loading);
- const [isGettingArchive, setIsGettingArchive] = useState(false);
+ const isGettingArchive = useAppSelector(
+ (state) => state.catalogue_jur.isGettingArchive,
+ );
+
+ const [moveCatalogueFormOpen, setMoveCatalogueFormOpen] = useState(false);
+ const [editCatalogueFormOpen, setEditCatalogueFormOpen] = useState(false);
+ const [withdrawCatalogueFormOpen, setWithdrawCatalogueFormOpen] =
+ useState(false);
const [jurId, setJurId] = useState("");
const { visibleKeys, setVisibleKeys } = useVisibleColumns(catalogueJurConfig);
const {
@@ -43,7 +62,7 @@ export function CatalogueJurTable() {
hasActiveFilters,
} = useTableFilters();
// single filtered array — title count and table share it
- const { rows, totalCount, displayedCount } = useFilteredRows(
+ const { rows } = useFilteredRows(
rawRows,
catalogueJurConfig,
rawQuery,
@@ -51,10 +70,59 @@ export function CatalogueJurTable() {
sort,
);
- useEffect(() => {
+ function getCatalogueJur() {
+ // #TODO поменять на outside_group=true
dispatch(
- getCatalogueJurThunk({ closed: isGettingArchive, outside_group: false }),
+ getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
);
+ }
+
+ function closeMoveCatalogueJurHandler() {
+ setJurId("");
+ setMoveCatalogueFormOpen(false);
+ }
+ function closeWithdrawCatalogueJurHandler() {
+ setJurId("");
+ setWithdrawCatalogueFormOpen(false);
+ }
+ function closeEditCatalogueJurHandler() {
+ setJurId("");
+ setEditCatalogueFormOpen(false);
+ }
+
+ async function moveCatalogueJurHandler(values: MoveCatalogueJurProps) {
+ try {
+ await moveCatalogueJur(jurId, values);
+ getCatalogueJur();
+ closeMoveCatalogueJurHandler();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ async function withdrawCatalogueJurHandler(
+ values: WithdrawCatalogueJurProps,
+ ) {
+ try {
+ await withdrawCatalogueJur(jurId, values);
+ getCatalogueJur();
+ closeWithdrawCatalogueJurHandler();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ async function editJurHandler(values: CatalogueJurFormProps) {
+ try {
+ await editCatalogueJur(jurId, values);
+ dispatch(
+ getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
+ );
+ closeEditCatalogueJurHandler()
+ } catch {}
+ }
+
+ useEffect(() => {
+ getCatalogueJur();
}, [isGettingArchive]);
const extraColumns: ColumnsType = useMemo(
@@ -69,6 +137,10 @@ export function CatalogueJurTable() {
key: "edit",
icon: ,
label: "Изменить ЮЛ",
+ onClick: () => {
+ setJurId(row.id);
+ setEditCatalogueFormOpen(true);
+ },
},
{
key: "history",
@@ -80,18 +152,25 @@ export function CatalogueJurTable() {
key: "move",
icon: ,
label: "Перевести в другую ГК",
- onClick: () => setJurId(row.id),
+ onClick: () => {
+ setJurId(row.id);
+ setMoveCatalogueFormOpen(true);
+ },
},
{
key: "withdraw",
icon: ,
label: "Вывести из состава ГК",
danger: true,
+ onClick: () => {
+ setJurId(row.id);
+ setWithdrawCatalogueFormOpen(true);
+ },
},
];
return (
-
@@ -101,7 +180,7 @@ export function CatalogueJurTable() {
],
[navigate],
);
- console.log(jurId, "test");
+
return (
)}
+
+ dispatch(setIsGettingArchive(e.target.checked))}
+ >
+ Архив
+
- setIsGettingArchive(e.target.checked)}
- >
- Архив
-
@@ -156,19 +236,41 @@ export function CatalogueJurTable() {
globalQuery={rawQuery}
columnFilters={columnFilters}
onColumnFiltersChange={setColumnFilters}
- extraColumns={extraColumns}
+ extraColumns={isGettingArchive ? undefined : extraColumns}
/>
- {!!jurId && (
+ {moveCatalogueFormOpen && (
{
- setJurId("");
+ closeMoveCatalogueJurHandler();
}}
- onOk={async (values) => {
- // await api.create(values)
- console.log(values, 'test2')
- setJurId("");
+ onOk={(values) => {
+ moveCatalogueJurHandler(values);
+ }}
+ />
+ )}
+ {withdrawCatalogueFormOpen && (
+ {
+ closeWithdrawCatalogueJurHandler();
+ }}
+ onOk={(values) => {
+ withdrawCatalogueJurHandler(values);
+ }}
+ />
+ )}
+ {editCatalogueFormOpen && (
+ {
+ closeEditCatalogueJurHandler()
+ }}
+ onOk={(values) => {
+ editJurHandler(values);
}}
/>
)}
diff --git a/src/widgets/CatalogueJurTable/config.tsx b/src/widgets/CatalogueJurTable/config.tsx
index 9aca89d..2920bc1 100644
--- a/src/widgets/CatalogueJurTable/config.tsx
+++ b/src/widgets/CatalogueJurTable/config.tsx
@@ -4,7 +4,7 @@ import { ICatalogueJur } from "../../types/catalogueJur/catalogueJur";
export const catalogueJurConfig: TableConfig = {
rowKey: "id",
- searchableKeys: ["closed", "inn", "kpp", "name", "entity_type"],
+ searchableKeys: ["closed", "inn", "kpp", "name", "company_group_name", "entity_type"],
columns: [
{
key: "closed",
@@ -30,6 +30,11 @@ export const catalogueJurConfig: TableConfig = {
title: "Организация",
features: { search: true, multiselect: true, sort: true },
},
+ {
+ key: "company_group_name",
+ title: "ГК",
+ features: { search: true, multiselect: true, sort: true },
+ },
{
key: "entity_type",
title: "Тип",
diff --git a/src/widgets/MoveCatalogueJurForm/MoveCatalogueJurForm.tsx b/src/widgets/MoveCatalogueJurForm/MoveCatalogueJurForm.tsx
index 75b6680..861fc10 100644
--- a/src/widgets/MoveCatalogueJurForm/MoveCatalogueJurForm.tsx
+++ b/src/widgets/MoveCatalogueJurForm/MoveCatalogueJurForm.tsx
@@ -1,12 +1,11 @@
-import React, { useEffect, useMemo, useRef, useState } from "react";
-import { Modal, Form, Select, Row, Col, Input, DatePicker } from "antd";
-import { fetchGSKByComGroup } from "../../services/api/directories/company_groups";
+import React, { useEffect, useState } from "react";
+import { Modal, Form, Select, Input, DatePicker } from "antd";
import { useAppDispatch, useAppSelector } from "../../store/store";
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
import FormItem from "antd/es/form/FormItem";
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
-import type { Dayjs } from "dayjs";
import dayjs from "dayjs";
+import { MoveCatalogueJurProps } from "../../types/catalogueJur/catalogueJur";
type FormValues = {
name: string;
@@ -19,7 +18,7 @@ type FormValues = {
type Props = {
open: boolean;
onCancel: () => void;
- onOk: (values: FormValues) => void | Promise;
+ onOk: (values: MoveCatalogueJurProps) => void | Promise;
jurId: string;
};
@@ -34,6 +33,7 @@ export const MoveCatalogueJurForm: React.FC = ({
const { raw_rows, loading } = useAppSelector((state) => state.company_groups);
const [initialDataLoading, setInitialDataLoading] = useState(false);
+
async function getInitialData() {
setInitialDataLoading(true);
const data = await fetchOneCatalogueJur(jurId);
@@ -41,7 +41,7 @@ export const MoveCatalogueJurForm: React.FC = ({
name: data?.name,
company_group_name: data?.company_group_name ?? "",
old_company_group_id: data?.company_group_id ?? "",
- company_group_id: "",
+ company_group_id: undefined,
effective_date: "",
});
setInitialDataLoading(false);
@@ -49,9 +49,8 @@ export const MoveCatalogueJurForm: React.FC = ({
const handleOk = async () => {
try {
- const values = await form.validateFields();
- await onOk(values);
- form.resetFields();
+ const { effective_date, company_group_id } = await form.validateFields();
+ await onOk({ effective_date, company_group_id });
} catch {
// validation error - keep modal open
}
@@ -105,6 +104,7 @@ export const MoveCatalogueJurForm: React.FC = ({
)
.map((g) => ({ value: g.id, label: g.name }))}
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
+ optionFilterProp="label"
/>
@@ -120,6 +120,7 @@ export const MoveCatalogueJurForm: React.FC = ({
}
>
void;
+ onOk: (values: WithdrawCatalogueJurProps) => void | Promise;
+ jurId: string;
+};
+
+export const WithdrawCatalogueJurForm: React.FC = ({
+ open,
+ onCancel,
+ onOk,
+ jurId,
+}) => {
+ const [form] = Form.useForm();
+ const [initialDataLoading, setInitialDataLoading] = useState(false);
+
+ const eventOptions = [
+ { value: "CLOSE", label: "Закрытие" },
+ { value: "REMOVE_FROM_GROUP", label: "Переход в другую ГК" },
+ ];
+
+ async function getInitialData() {
+ setInitialDataLoading(true);
+ const data = await fetchOneCatalogueJur(jurId);
+ form.setFieldsValue({
+ name: data?.name,
+ event: undefined,
+ effective_date: "",
+ comment: "",
+ });
+ setInitialDataLoading(false);
+ }
+
+ const handleOk = async () => {
+ try {
+ const {
+ effective_date,
+ event,
+ comment = "",
+ } = await form.validateFields();
+ await onOk({ effective_date, event, comment });
+ } catch {
+ // validation error - keep modal open
+ }
+ };
+
+ const handleCancel = () => {
+ form.resetFields();
+ onCancel();
+ };
+
+ useEffect(() => {
+ getInitialData();
+ }, [open]);
+
+ return (
+
+
+
+
+
+ ({
+ value: value ? dayjs(value) : undefined,
+ })}
+ normalize={(value) =>
+ value ? value.format("YYYY-MM-DD") : undefined
+ }
+ >
+
+
+
+
+
+
+
+ );
+};