added forms for catalogue jur
This commit is contained in:
parent
8e8e46ecbc
commit
3977daebe5
@ -1,7 +1,32 @@
|
|||||||
|
import { Button, Space } from "antd";
|
||||||
import PageTitle from "../components/PageTitle";
|
import PageTitle from "../components/PageTitle";
|
||||||
import { CatalogueJurTable } from "../widgets/CatalogueJurTable/CatalogueJurTable";
|
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() {
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -11,10 +36,16 @@ export function CatalogueJur() {
|
|||||||
height: "100vh",
|
height: "100vh",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PageTitle
|
<Space style={{ justifyContent: "space-between" }}>
|
||||||
header="Юридические лица"
|
<PageTitle header="Юридические лица" location="Справочники" />
|
||||||
location="Справочники"
|
<Button
|
||||||
/>
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => setCreateFormOpen(true)}
|
||||||
|
>
|
||||||
|
Создать ЮЛ
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
<main
|
<main
|
||||||
style={{
|
style={{
|
||||||
flex: "1 1 auto",
|
flex: "1 1 auto",
|
||||||
@ -26,6 +57,17 @@ export function CatalogueJur() {
|
|||||||
>
|
>
|
||||||
<CatalogueJurTable />
|
<CatalogueJurTable />
|
||||||
</main>
|
</main>
|
||||||
|
{createFormOpen && (
|
||||||
|
<CatalogueJurForm
|
||||||
|
open={createFormOpen}
|
||||||
|
onCancel={() => {
|
||||||
|
setCreateFormOpen(false);
|
||||||
|
}}
|
||||||
|
onOk={(values) => {
|
||||||
|
createJurHandler(values);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,9 @@ import { api } from "../../../api/client";
|
|||||||
import {
|
import {
|
||||||
GetCatalogueJurPropsI,
|
GetCatalogueJurPropsI,
|
||||||
} from "../../../store/slices/catalogueJurSlice/types";
|
} 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) {
|
export async function fetchCatalogueJur(params: GetCatalogueJurPropsI) {
|
||||||
// #TODO поменять на outside_group=true
|
|
||||||
const res = await api.get<ICatalogueJur[]>(
|
const res = await api.get<ICatalogueJur[]>(
|
||||||
"/directories/legal-entities",
|
"/directories/legal-entities",
|
||||||
params,
|
params,
|
||||||
@ -22,3 +21,40 @@ export async function fetchOneCatalogueJur(
|
|||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function moveCatalogueJur(
|
||||||
|
entityId: string,
|
||||||
|
body: MoveCatalogueJurProps,
|
||||||
|
): Promise<void> {
|
||||||
|
return api.post<void>(
|
||||||
|
`/directories/legal-entities/${entityId}/move`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export async function withdrawCatalogueJur(
|
||||||
|
entityId: string,
|
||||||
|
body: WithdrawCatalogueJurProps,
|
||||||
|
): Promise<void> {
|
||||||
|
return api.post<void>(
|
||||||
|
`/directories/legal-entities/${entityId}/withdraw`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export async function createCatalogueJur(
|
||||||
|
body: CatalogueJurFormProps,
|
||||||
|
): Promise<void> {
|
||||||
|
return api.post<void>(
|
||||||
|
`/directories/legal-entities`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export async function editCatalogueJur(
|
||||||
|
entityId: string,
|
||||||
|
body: CatalogueJurFormProps,
|
||||||
|
): Promise<void> {
|
||||||
|
return api.patch<void>(
|
||||||
|
`/directories/legal-entities/${entityId}`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,20 +1,23 @@
|
|||||||
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
import { useSelector } from "react-redux";
|
import { CatalogueJurSliceType } from "./types";
|
||||||
import { Config } from "../../../conf/config";
|
|
||||||
import {CatalogueJurSliceType } from "./types";
|
|
||||||
import { getCatalogueJurThunk } from "./thunks";
|
import { getCatalogueJurThunk } from "./thunks";
|
||||||
|
|
||||||
const initialState:CatalogueJurSliceType = {
|
const initialState: CatalogueJurSliceType = {
|
||||||
raw_rows: [],
|
raw_rows: [],
|
||||||
total_groups: 0,
|
total_groups: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
isGettingArchive: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const catalogueJurSlice = createSlice({
|
const catalogueJurSlice = createSlice({
|
||||||
name: "catalogue_jur",
|
name: "catalogue_jur",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {},
|
reducers: {
|
||||||
|
setIsGettingArchive(state, action: PayloadAction<boolean>) {
|
||||||
|
state.isGettingArchive = action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder
|
builder
|
||||||
.addCase(getCatalogueJurThunk.pending, (state, _) => {
|
.addCase(getCatalogueJurThunk.pending, (state, _) => {
|
||||||
@ -32,5 +35,5 @@ const catalogueJurSlice = createSlice({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
export const { setIsGettingArchive } = catalogueJurSlice.actions;
|
||||||
export default catalogueJurSlice.reducer;
|
export default catalogueJurSlice.reducer;
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export interface CatalogueJurSliceType{
|
|||||||
raw_rows: ICatalogueJur[];
|
raw_rows: ICatalogueJur[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
|
isGettingArchive:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
export interface ICatalogueJur {
|
export interface ICatalogueJur {
|
||||||
id: string;
|
id: string;
|
||||||
inn: string;
|
inn: string;
|
||||||
kpp: string | null;
|
kpp?: string;
|
||||||
crm_id: string | null;
|
crm_id?: string;
|
||||||
entity_type: string;
|
entity_type: "ЮЛ" | "ИП";
|
||||||
name: string;
|
name: string;
|
||||||
company_group_id: string | null;
|
company_group_id?: string;
|
||||||
company_group_name: string | null;
|
company_group_name: string | null;
|
||||||
regional_office_id: string | null;
|
regional_office_id?: string;
|
||||||
close_date: Date;
|
close_date: Date;
|
||||||
valid_from: Date;
|
valid_from: Date;
|
||||||
created_at: Date;
|
created_at: Date;
|
||||||
@ -15,10 +15,38 @@ export interface ICatalogueJur {
|
|||||||
outside_group: boolean;
|
outside_group: boolean;
|
||||||
closed: boolean | string;
|
closed: boolean | string;
|
||||||
memberships?: unknown[];
|
memberships?: unknown[];
|
||||||
aliases?: unknown[];
|
aliases?: JurAlliase[];
|
||||||
regional_office: {
|
regional_office: {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
is_head_office: boolean;
|
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;
|
||||||
|
};
|
||||||
|
|||||||
217
src/widgets/CatalogueJurForm/CatalogueJurForm.tsx
Normal file
217
src/widgets/CatalogueJurForm/CatalogueJurForm.tsx
Normal file
@ -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<void>;
|
||||||
|
jurId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CatalogueJurForm: React.FC<Props> = ({
|
||||||
|
open,
|
||||||
|
onCancel,
|
||||||
|
onOk,
|
||||||
|
jurId,
|
||||||
|
}) => {
|
||||||
|
const [form] = Form.useForm<CatalogueJurFormProps>();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const loadOffices = useCallback(
|
||||||
|
() => api.get<RegionalOffice[]>("/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 (
|
||||||
|
<Modal
|
||||||
|
title={
|
||||||
|
!!jurId ? "Изменить юридическое лицо" : "Добавить юридическое лицо"
|
||||||
|
}
|
||||||
|
open={open}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onOk={handleOk}
|
||||||
|
okText={!!jurId ? "Сохраить" : "Добавить"}
|
||||||
|
cancelText="Отмена"
|
||||||
|
destroyOnHidden
|
||||||
|
width={720}
|
||||||
|
loading={initialDataLoading}
|
||||||
|
>
|
||||||
|
<Form form={form} layout="vertical">
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={6}>
|
||||||
|
<Form.Item
|
||||||
|
name="inn"
|
||||||
|
label="ИНН"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "Укажите ИНН" },
|
||||||
|
{ pattern: /^\d{10}$/, message: "10 цифр" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
disabled={!!jurId}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
placeholder="0000000000"
|
||||||
|
maxLength={10}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Form.Item
|
||||||
|
name="kpp"
|
||||||
|
label="КПП"
|
||||||
|
rules={[{ pattern: /^\d{9}$/, message: "9 цифр" }]}
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
placeholder="000000000"
|
||||||
|
maxLength={9}
|
||||||
|
disabled={type === "ИП"}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Form.Item
|
||||||
|
name="crm_id"
|
||||||
|
label="ID ЮЛ в CRM"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "Укажите CRM ID" },
|
||||||
|
{ pattern: /^\d{11}$/, message: "11 цифр" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input maxLength={11} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Form.Item
|
||||||
|
name="entity_type"
|
||||||
|
label="Тип"
|
||||||
|
initialValue="ЮЛ"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: "ЮЛ", label: "ЮЛ" },
|
||||||
|
{ value: "ИП", label: "ИП" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label="Наименование организации"
|
||||||
|
rules={[{ required: true, message: "Укажите наименование" }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="ООО «Название»" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="aliases"
|
||||||
|
label="Альтернативные наименования"
|
||||||
|
extra="Введите синоним и нажмите Enter. Можно добавить несколько значений."
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
mode="tags"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
placeholder="Добавить синоним"
|
||||||
|
tokenSeparators={[","]}
|
||||||
|
open={false}
|
||||||
|
suffixIcon={null}
|
||||||
|
notFoundContent={null}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item name="company_group_id" label="Входит в ГСК">
|
||||||
|
<Select
|
||||||
|
disabled={!!jurId}
|
||||||
|
allowClear
|
||||||
|
placeholder="— не указан —"
|
||||||
|
options={raw_rows?.map((g) => ({ value: g.id, label: g.name }))}
|
||||||
|
showSearch
|
||||||
|
optionFilterProp="label"
|
||||||
|
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item name="regional_office_id" label="Входит в ГСЗ">
|
||||||
|
<Select
|
||||||
|
allowClear
|
||||||
|
placeholder="— не указан —"
|
||||||
|
options={offices?.data?.map((g) => ({
|
||||||
|
value: g.id,
|
||||||
|
label: g.name,
|
||||||
|
}))}
|
||||||
|
showSearch
|
||||||
|
optionFilterProp="label"
|
||||||
|
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -18,18 +18,37 @@ import {
|
|||||||
SwapOutlined,
|
SwapOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useAppDispatch, useAppSelector } from "../../store/store";
|
import { useAppDispatch, useAppSelector } from "../../store/store";
|
||||||
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
|
||||||
import { useTableFilters } from "../../components/GenericTable/useTableFilters";
|
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 { getCatalogueJurThunk } from "../../store/slices/catalogueJurSlice/thunks";
|
||||||
import { MoveCatalogueJurForm } from "../MoveCatalogueJurForm/MoveCatalogueJurForm";
|
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() {
|
export function CatalogueJurTable() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const rawRows = useAppSelector((state) => state.catalogue_jur.raw_rows);
|
const rawRows = useAppSelector((state) => state.catalogue_jur.raw_rows);
|
||||||
const loading = useAppSelector((state) => state.catalogue_jur.loading);
|
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 [jurId, setJurId] = useState("");
|
||||||
const { visibleKeys, setVisibleKeys } = useVisibleColumns(catalogueJurConfig);
|
const { visibleKeys, setVisibleKeys } = useVisibleColumns(catalogueJurConfig);
|
||||||
const {
|
const {
|
||||||
@ -43,7 +62,7 @@ export function CatalogueJurTable() {
|
|||||||
hasActiveFilters,
|
hasActiveFilters,
|
||||||
} = useTableFilters<ICatalogueJur>();
|
} = useTableFilters<ICatalogueJur>();
|
||||||
// single filtered array — title count and table share it
|
// single filtered array — title count and table share it
|
||||||
const { rows, totalCount, displayedCount } = useFilteredRows(
|
const { rows } = useFilteredRows(
|
||||||
rawRows,
|
rawRows,
|
||||||
catalogueJurConfig,
|
catalogueJurConfig,
|
||||||
rawQuery,
|
rawQuery,
|
||||||
@ -51,10 +70,59 @@ export function CatalogueJurTable() {
|
|||||||
sort,
|
sort,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
function getCatalogueJur() {
|
||||||
|
// #TODO поменять на outside_group=true
|
||||||
dispatch(
|
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]);
|
}, [isGettingArchive]);
|
||||||
|
|
||||||
const extraColumns: ColumnsType<ICatalogueJur> = useMemo(
|
const extraColumns: ColumnsType<ICatalogueJur> = useMemo(
|
||||||
@ -69,6 +137,10 @@ export function CatalogueJurTable() {
|
|||||||
key: "edit",
|
key: "edit",
|
||||||
icon: <EditOutlined />,
|
icon: <EditOutlined />,
|
||||||
label: "Изменить ЮЛ",
|
label: "Изменить ЮЛ",
|
||||||
|
onClick: () => {
|
||||||
|
setJurId(row.id);
|
||||||
|
setEditCatalogueFormOpen(true);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "history",
|
key: "history",
|
||||||
@ -80,18 +152,25 @@ export function CatalogueJurTable() {
|
|||||||
key: "move",
|
key: "move",
|
||||||
icon: <SwapOutlined />,
|
icon: <SwapOutlined />,
|
||||||
label: "Перевести в другую ГК",
|
label: "Перевести в другую ГК",
|
||||||
onClick: () => setJurId(row.id),
|
onClick: () => {
|
||||||
|
setJurId(row.id);
|
||||||
|
setMoveCatalogueFormOpen(true);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "withdraw",
|
key: "withdraw",
|
||||||
icon: <LogoutOutlined />,
|
icon: <LogoutOutlined />,
|
||||||
label: "Вывести из состава ГК",
|
label: "Вывести из состава ГК",
|
||||||
danger: true,
|
danger: true,
|
||||||
|
onClick: () => {
|
||||||
|
setJurId(row.id);
|
||||||
|
setWithdrawCatalogueFormOpen(true);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Dropdown menu={{ items }} trigger={["click"]}>
|
<Dropdown menu={{ items }} trigger={["click"]}>
|
||||||
<Button type="default">
|
<Button type="default" style={{ width: "32px" }}>
|
||||||
<EllipsisOutlined />
|
<EllipsisOutlined />
|
||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@ -101,7 +180,7 @@ export function CatalogueJurTable() {
|
|||||||
],
|
],
|
||||||
[navigate],
|
[navigate],
|
||||||
);
|
);
|
||||||
console.log(jurId, "test");
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
||||||
<Space
|
<Space
|
||||||
@ -131,17 +210,18 @@ export function CatalogueJurTable() {
|
|||||||
Сбросить фильтры
|
Сбросить фильтры
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Checkbox
|
||||||
|
checked={isGettingArchive}
|
||||||
|
onChange={(e) => dispatch(setIsGettingArchive(e.target.checked))}
|
||||||
|
>
|
||||||
|
Архив
|
||||||
|
</Checkbox>
|
||||||
<ColumnSettings
|
<ColumnSettings
|
||||||
defs={catalogueJurConfig.columns}
|
defs={catalogueJurConfig.columns}
|
||||||
visibleKeys={visibleKeys}
|
visibleKeys={visibleKeys}
|
||||||
onChange={setVisibleKeys}
|
onChange={setVisibleKeys}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
|
||||||
checked={isGettingArchive}
|
|
||||||
onChange={(e) => setIsGettingArchive(e.target.checked)}
|
|
||||||
>
|
|
||||||
Архив
|
|
||||||
</Checkbox>
|
|
||||||
</Space>
|
</Space>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
||||||
@ -156,19 +236,41 @@ export function CatalogueJurTable() {
|
|||||||
globalQuery={rawQuery}
|
globalQuery={rawQuery}
|
||||||
columnFilters={columnFilters}
|
columnFilters={columnFilters}
|
||||||
onColumnFiltersChange={setColumnFilters}
|
onColumnFiltersChange={setColumnFilters}
|
||||||
extraColumns={extraColumns}
|
extraColumns={isGettingArchive ? undefined : extraColumns}
|
||||||
/>
|
/>
|
||||||
{!!jurId && (
|
{moveCatalogueFormOpen && (
|
||||||
<MoveCatalogueJurForm
|
<MoveCatalogueJurForm
|
||||||
jurId={jurId}
|
jurId={jurId}
|
||||||
open={!!jurId}
|
open={moveCatalogueFormOpen}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setJurId("");
|
closeMoveCatalogueJurHandler();
|
||||||
}}
|
}}
|
||||||
onOk={async (values) => {
|
onOk={(values) => {
|
||||||
// await api.create(values)
|
moveCatalogueJurHandler(values);
|
||||||
console.log(values, 'test2')
|
}}
|
||||||
setJurId("");
|
/>
|
||||||
|
)}
|
||||||
|
{withdrawCatalogueFormOpen && (
|
||||||
|
<WithdrawCatalogueJurForm
|
||||||
|
jurId={jurId}
|
||||||
|
open={withdrawCatalogueFormOpen}
|
||||||
|
onCancel={() => {
|
||||||
|
closeWithdrawCatalogueJurHandler();
|
||||||
|
}}
|
||||||
|
onOk={(values) => {
|
||||||
|
withdrawCatalogueJurHandler(values);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{editCatalogueFormOpen && (
|
||||||
|
<CatalogueJurForm
|
||||||
|
jurId={jurId}
|
||||||
|
open={editCatalogueFormOpen}
|
||||||
|
onCancel={() => {
|
||||||
|
closeEditCatalogueJurHandler()
|
||||||
|
}}
|
||||||
|
onOk={(values) => {
|
||||||
|
editJurHandler(values);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { ICatalogueJur } from "../../types/catalogueJur/catalogueJur";
|
|||||||
|
|
||||||
export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
||||||
rowKey: "id",
|
rowKey: "id",
|
||||||
searchableKeys: ["closed", "inn", "kpp", "name", "entity_type"],
|
searchableKeys: ["closed", "inn", "kpp", "name", "company_group_name", "entity_type"],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
key: "closed",
|
key: "closed",
|
||||||
@ -30,6 +30,11 @@ export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
|||||||
title: "Организация",
|
title: "Организация",
|
||||||
features: { search: true, multiselect: true, sort: true },
|
features: { search: true, multiselect: true, sort: true },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "company_group_name",
|
||||||
|
title: "ГК",
|
||||||
|
features: { search: true, multiselect: true, sort: true },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "entity_type",
|
key: "entity_type",
|
||||||
title: "Тип",
|
title: "Тип",
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Modal, Form, Select, Row, Col, Input, DatePicker } from "antd";
|
import { Modal, Form, Select, Input, DatePicker } from "antd";
|
||||||
import { fetchGSKByComGroup } from "../../services/api/directories/company_groups";
|
|
||||||
import { useAppDispatch, useAppSelector } from "../../store/store";
|
import { useAppDispatch, useAppSelector } from "../../store/store";
|
||||||
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
||||||
import FormItem from "antd/es/form/FormItem";
|
import FormItem from "antd/es/form/FormItem";
|
||||||
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
|
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
|
||||||
import type { Dayjs } from "dayjs";
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { MoveCatalogueJurProps } from "../../types/catalogueJur/catalogueJur";
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -19,7 +18,7 @@ type FormValues = {
|
|||||||
type Props = {
|
type Props = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onOk: (values: FormValues) => void | Promise<void>;
|
onOk: (values: MoveCatalogueJurProps) => void | Promise<void>;
|
||||||
jurId: string;
|
jurId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,6 +33,7 @@ export const MoveCatalogueJurForm: React.FC<Props> = ({
|
|||||||
|
|
||||||
const { raw_rows, loading } = useAppSelector((state) => state.company_groups);
|
const { raw_rows, loading } = useAppSelector((state) => state.company_groups);
|
||||||
const [initialDataLoading, setInitialDataLoading] = useState(false);
|
const [initialDataLoading, setInitialDataLoading] = useState(false);
|
||||||
|
|
||||||
async function getInitialData() {
|
async function getInitialData() {
|
||||||
setInitialDataLoading(true);
|
setInitialDataLoading(true);
|
||||||
const data = await fetchOneCatalogueJur(jurId);
|
const data = await fetchOneCatalogueJur(jurId);
|
||||||
@ -41,7 +41,7 @@ export const MoveCatalogueJurForm: React.FC<Props> = ({
|
|||||||
name: data?.name,
|
name: data?.name,
|
||||||
company_group_name: data?.company_group_name ?? "",
|
company_group_name: data?.company_group_name ?? "",
|
||||||
old_company_group_id: data?.company_group_id ?? "",
|
old_company_group_id: data?.company_group_id ?? "",
|
||||||
company_group_id: "",
|
company_group_id: undefined,
|
||||||
effective_date: "",
|
effective_date: "",
|
||||||
});
|
});
|
||||||
setInitialDataLoading(false);
|
setInitialDataLoading(false);
|
||||||
@ -49,9 +49,8 @@ export const MoveCatalogueJurForm: React.FC<Props> = ({
|
|||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const { effective_date, company_group_id } = await form.validateFields();
|
||||||
await onOk(values);
|
await onOk({ effective_date, company_group_id });
|
||||||
form.resetFields();
|
|
||||||
} catch {
|
} catch {
|
||||||
// validation error - keep modal open
|
// validation error - keep modal open
|
||||||
}
|
}
|
||||||
@ -105,6 +104,7 @@ export const MoveCatalogueJurForm: React.FC<Props> = ({
|
|||||||
)
|
)
|
||||||
.map((g) => ({ value: g.id, label: g.name }))}
|
.map((g) => ({ value: g.id, label: g.name }))}
|
||||||
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
||||||
|
optionFilterProp="label"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
@ -120,6 +120,7 @@ export const MoveCatalogueJurForm: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
minDate={dayjs()}
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
format="DD.MM.YYYY"
|
format="DD.MM.YYYY"
|
||||||
placeholder="ДД.ММ.ГГГГ"
|
placeholder="ДД.ММ.ГГГГ"
|
||||||
|
|||||||
@ -0,0 +1,120 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Modal, Form, Select, Input, DatePicker } from "antd";
|
||||||
|
import FormItem from "antd/es/form/FormItem";
|
||||||
|
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { WithdrawCatalogueJurProps } from "../../types/catalogueJur/catalogueJur";
|
||||||
|
import TextArea from "antd/es/input/TextArea";
|
||||||
|
|
||||||
|
interface FormValues extends WithdrawCatalogueJurProps {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
onOk: (values: WithdrawCatalogueJurProps) => void | Promise<void>;
|
||||||
|
jurId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithdrawCatalogueJurForm: React.FC<Props> = ({
|
||||||
|
open,
|
||||||
|
onCancel,
|
||||||
|
onOk,
|
||||||
|
jurId,
|
||||||
|
}) => {
|
||||||
|
const [form] = Form.useForm<FormValues>();
|
||||||
|
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 (
|
||||||
|
<Modal
|
||||||
|
title="Вывести ЮЛ из состава ГК"
|
||||||
|
open={open}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onOk={handleOk}
|
||||||
|
okText="Вывести"
|
||||||
|
cancelText="Отмена"
|
||||||
|
destroyOnHidden
|
||||||
|
loading={initialDataLoading}
|
||||||
|
okButtonProps={{ danger: true }}
|
||||||
|
>
|
||||||
|
<Form form={form} layout="vertical">
|
||||||
|
<FormItem name="name" label="ЮЛ">
|
||||||
|
<Input disabled />
|
||||||
|
</FormItem>
|
||||||
|
<Form.Item
|
||||||
|
name="event"
|
||||||
|
label="Событие"
|
||||||
|
rules={[{ required: true, message: "Укажите событие" }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder="Выбрать"
|
||||||
|
showSearch
|
||||||
|
allowClear
|
||||||
|
options={eventOptions}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="effective_date"
|
||||||
|
label="Дата закрытия"
|
||||||
|
rules={[{ required: true, message: "Укажите дату" }]}
|
||||||
|
getValueProps={(value: string | undefined) => ({
|
||||||
|
value: value ? dayjs(value) : undefined,
|
||||||
|
})}
|
||||||
|
normalize={(value) =>
|
||||||
|
value ? value.format("YYYY-MM-DD") : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
format="DD.MM.YYYY"
|
||||||
|
placeholder="ДД.ММ.ГГГГ"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<FormItem name={"comment"} label="Комментарий">
|
||||||
|
<TextArea maxLength={6} rows={4} placeholder="Необязательно"/>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user