Commit 2d895a5d958f2370fc127c171df8bc449fd41924

Authored by 曾国涛
1 parent 7e09e9e9

feat: 开票功能开发

src/pages/Invoice/components/InvoiceDetailTable.tsx
1 1 import InvoiceDetailImportModal from '@/pages/Invoice/components/InvoiceDetailImportModal';
2 2 import type { ProColumns } from '@ant-design/pro-components';
3   -import {
4   - EditableProTable,
5   - ProCard,
6   - ProFormField,
7   -} from '@ant-design/pro-components';
  3 +import { EditableProTable } from '@ant-design/pro-components';
8 4 import { useEffect, useState } from 'react';
9 5  
10 6 export default ({ recordId, details, updateDetails, readOnly }) => {
... ... @@ -62,7 +58,7 @@ export default ({ recordId, details, updateDetails, readOnly }) => {
62 58 },
63 59 {
64 60 title: '税率/征收率',
65   - readonly: readOnly,
  61 + readonly: true,
66 62 dataIndex: 'taxRate',
67 63 valueType: () => ({
68 64 type: 'percent',
... ... @@ -71,7 +67,7 @@ export default ({ recordId, details, updateDetails, readOnly }) => {
71 67 },
72 68 {
73 69 title: '税额',
74   - readonly: readOnly,
  70 + readonly: true,
75 71 dataIndex: 'taxPrice',
76 72 valueType: 'digit',
77 73 ellipsis: true,
... ... @@ -125,19 +121,6 @@ export default ({ recordId, details, updateDetails, readOnly }) => {
125 121 onChange: setEditableRowKeys,
126 122 }}
127 123 />
128   - <ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
129   - <ProFormField
130   - ignoreFormItem
131   - fieldProps={{
132   - style: {
133   - width: '100%',
134   - },
135   - }}
136   - mode="read"
137   - valueType="jsonCode"
138   - text={JSON.stringify(details)}
139   - />
140   - </ProCard>
141 124 </>
142 125 );
143 126 };
... ...
src/pages/Invoice/components/InvoiceRecordDetailModal.tsx
... ... @@ -11,12 +11,13 @@ import { enumToSelect } from &#39;@/utils&#39;;
11 11 import {
12 12 ModalForm,
13 13 ProForm,
  14 + ProFormFieldSet,
14 15 ProFormInstance,
15 16 ProFormSelect,
16 17 ProFormText,
17 18 ProFormTextArea,
18 19 } from '@ant-design/pro-components';
19   -import { Button, Form, Space, message } from 'antd';
  20 +import { Button, Divider, Form, Space, message } from 'antd';
20 21 import { useEffect, useRef, useState } from 'react';
21 22  
22 23 export default ({ id }) => {
... ... @@ -121,14 +122,14 @@ export default ({ id }) =&gt; {
121 122 )}
122 123 </>,
123 124 /*<Button
124   - type={'default'}
125   - key="ok"
126   - onClick={() => {
127   - setVisible(false)
128   - }}
129   - >
130   - 取消
131   - </Button>,*/
  125 + type={'default'}
  126 + key="ok"
  127 + onClick={() => {
  128 + setVisible(false)
  129 + }}
  130 + >
  131 + 取消
  132 + </Button>,*/
132 133 ];
133 134 },
134 135 }}
... ... @@ -207,18 +208,31 @@ export default ({ id }) =&gt; {
207 208 { required: true, message: 'Please select your country!' },
208 209 ]}
209 210 />
210   - <ProFormText
211   - readonly
212   - width="md"
213   - name="subOrderIdsText"
  211 + <ProFormFieldSet
  212 + name="list"
214 213 label="订单号"
215   - initialValue={initialValues?.subOrderIds
216   - ?.map((item: any) => {
217   - return item;
218   - })
219   - .join(',')}
220   - placeholder="请输入名称"
221   - />
  214 + transform={(value: any) => ({
  215 + list: value,
  216 + startTime: value[0],
  217 + endTime: value[1],
  218 + })}
  219 + >
  220 + {initialValues?.subOrderIds?.map((item) => {
  221 + return (
  222 + <>
  223 + <Button
  224 + className="pl-1 pr-0"
  225 + type="link"
  226 + target="_blank"
  227 + href={'/order?subOrderId=' + item}
  228 + >
  229 + {item}
  230 + </Button>
  231 + <Divider type="vertical" />
  232 + </>
  233 + );
  234 + })}
  235 + </ProFormFieldSet>
222 236 </ProForm.Group>
223 237 购方信息
224 238 <hr />
... ...
src/pages/Invoice/index.tsx
... ... @@ -14,6 +14,7 @@ import {
14 14 postServiceBankStatementDeleteBankStatement,
15 15 postServiceBankStatementEditBankStatement,
16 16 postServiceBankStatementQueryBankStatement,
  17 + postServiceConstBeforeInvoicingInvoiceRecordStatus,
17 18 postServiceConstInvoiceType,
18 19 postServiceConstInvoicingType,
19 20 postServiceInvoiceDeleteInvoice,
... ... @@ -24,6 +25,7 @@ import {
24 25 } from '@/services';
25 26 import {
26 27 enumToProTableEnumValue,
  28 + enumToSelect,
27 29 enumValueToLabel,
28 30 formatDateTime,
29 31 } from '@/utils';
... ... @@ -115,7 +117,7 @@ const InvoicePage = () =&gt; {
115 117 width: 48,
116 118 },
117 119 {
118   - title: '记录编号',
  120 + title: '开票编号',
119 121 valueType: 'text',
120 122 dataIndex: 'id',
121 123 copyable: true,
... ... @@ -249,6 +251,18 @@ const InvoicePage = () =&gt; {
249 251 valueEnum: enumToProTableEnumValue(invoicingTypeValueEnum),
250 252 },
251 253 {
  254 + title: '开票状态',
  255 + valueType: 'select',
  256 + dataIndex: 'status',
  257 + filters: true,
  258 + onFilter: true,
  259 + hideInTable: true,
  260 + request: async () => {
  261 + const res = await postServiceConstBeforeInvoicingInvoiceRecordStatus();
  262 + return enumToSelect(res.data);
  263 + },
  264 + },
  265 + {
252 266 title: '是否加急',
253 267 valueType: 'select',
254 268 dataIndex: 'isUrgent',
... ... @@ -306,7 +320,7 @@ const InvoicePage = () =&gt; {
306 320 valueType: 'indexBorder',
307 321 },
308 322 {
309   - title: '记录编号',
  323 + title: '开票编号',
310 324 valueType: 'text',
311 325 dataIndex: 'id',
312 326 copyable: true,
... ...
src/pages/Order/components/InvoicingDrawerForm.tsx
... ... @@ -19,7 +19,7 @@ import { Form } from &#39;antd&#39;;
19 19 import { useEffect } from 'react';
20 20 import { PAYEE_OPTIONS } from '../constant';
21 21  
22   -export default ({ dataList, mainOrderList, setVisible, onClose }) => {
  22 +export default ({ dataList, mainOrder, setVisible, onClose }) => {
23 23 // let subOrderIds = dataList?.map((item) => {
24 24 // return item.id;
25 25 // });
... ... @@ -81,9 +81,7 @@ export default ({ dataList, mainOrderList, setVisible, onClose }) =&gt; {
81 81 width="md"
82 82 name="partyAName"
83 83 label="购方名称"
84   - initialValue={
85   - mainOrderList?.length === 1 ? mainOrderList[0].institution : ''
86   - }
  84 + initialValue={mainOrder.institution}
87 85 placeholder="请输入名称"
88 86 />
89 87 <ProFormText
... ... @@ -112,7 +110,8 @@ export default ({ dataList, mainOrderList, setVisible, onClose }) =&gt; {
112 110 <ProFormMoney
113 111 label="开票金额"
114 112 name="price"
115   - locale="en-GB"
  113 + locale="zh-CN"
  114 + rules={[{ required: true, message: '请填写开票金额!' }]}
116 115 initialValue={dataList.reduce((accumulator, currentValue) => {
117 116 return accumulator + currentValue.subOrderPayment;
118 117 }, 0)}
... ...
src/pages/Order/constant.ts
1   -import { RESPONSE_CODE } from '@/constants/enum';
2   -import {
3   - postServiceConstAfterInvoicingStatus,
4   - postServiceOrderQueryCustomerInformation,
5   -} from '@/services';
6   -import { enumToProTableEnumValue, enumToSelect } from '@/utils';
  1 +import { postServiceOrderQueryCustomerInformation } from '@/services';
  2 +import { enumToProTableEnumValue } from '@/utils';
7 3 import { getReceivingCompanyOptions, isSupplier } from '@/utils/order';
8 4  
9 5 export const COMFIR_RECEIPT_IMAGES_NUMBER = 3;
... ... @@ -225,13 +221,13 @@ export const FINANCIAL_STATUS_OPTIONS = {
225 221 UN_INVOICING: '取消开票',
226 222 };
227 223  
228   -export const getAfterInvoicingStatus = async () => {
  224 +/*export const getAfterInvoicingStatus = async () => {
229 225 let res = await postServiceConstAfterInvoicingStatus();
230 226 if (res.result === RESPONSE_CODE.SUCCESS) {
231 227 return res.data;
232 228 }
233 229 return {};
234   -};
  230 +};*/
235 231 export let AFTER_INVOICING_STATUS = {
236 232 NOT_YET_INVOICED: '尚未开票',
237 233 APPLY_FOR_INVOICING: '申请开票',
... ... @@ -428,6 +424,12 @@ export const MAIN_ORDER_COLUMNS = [
428 424 hideInTable: true,
429 425 },
430 426 {
  427 + title: '子订单编号',
  428 + dataIndex: 'subOrderId',
  429 + valueType: 'text',
  430 + hideInTable: true,
  431 + },
  432 + {
431 433 title: '销售代表',
432 434 dataIndex: 'salesCode',
433 435 valueType: 'text',
... ... @@ -619,10 +621,11 @@ export const MAIN_ORDER_COLUMNS = [
619 621 dataIndex: 'afterInvoicingStatus',
620 622 valueType: 'select',
621 623 hideInTable: true,
622   - request: async () => {
  624 + /*request: async () => {
623 625 let status = await getAfterInvoicingStatus();
624 626 return enumToSelect(status);
625   - },
  627 + },*/
  628 + valueEnum: enumToProTableEnumValue(AFTER_INVOICING_STATUS),
626 629 },
627 630 {
628 631 title: '发票号码',
... ...
src/pages/Order/index.tsx
... ... @@ -97,6 +97,7 @@ import ProductionTimeModal from &#39;./components/ProductionTimeModal&#39;;
97 97 import ShippingWarehouseChangeModal from './components/ShippingWarehouseChangeModal';
98 98 import UploadPayBillModal from './components/UploadPayBillModal';
99 99 import {
  100 + AFTER_INVOICING_STATUS,
100 101 CHECK_TYPE,
101 102 LOGISTICS_STATUS_OPTIONS,
102 103 MAIN_ORDER_COLUMNS,
... ... @@ -111,7 +112,6 @@ import {
111 112 PRODUCT_BELONG_DEPARTMENT_OPTIONS,
112 113 SHIPPING_WAREHOUSE_OPTIONS,
113 114 TAGS_COLOR,
114   - getAfterInvoicingStatus,
115 115 getInvoicingType,
116 116 getNeedInvoicing,
117 117 } from './constant';
... ... @@ -191,7 +191,6 @@ const OrderPage = () =&gt; {
191 191 const mainTableFormRef = useRef<ProFormInstance>();
192 192 let [searchParams, setSearchParam] = useState(Object); //表格的查询条件存储
193 193 const [messageApi, contextHolder] = message.useMessage();
194   - const [afterInvoicingStatus, setAfterInvoicingStatus] = useState({});
195 194 const [
196 195 shippingWarehouseChangeModalVisible,
197 196 setShippingWarehouseChangeModalVisible,
... ... @@ -221,21 +220,25 @@ const OrderPage = () =&gt; {
221 220 setSelectedSubOrderKeys([]);
222 221 };
223 222  
224   - useEffect(() => {
  223 + /*useEffect(() => {
225 224 let initAfterInvoicingStatus = async () => {
226 225 const afteInvoicingStatus = await getAfterInvoicingStatus();
227 226 setAfterInvoicingStatus(afteInvoicingStatus);
228 227 };
229 228 initAfterInvoicingStatus();
230   - }, []);
  229 + }, []);*/
231 230  
232 231 useEffect(() => {
233 232 // 使用URLSearchParams来解析查询参数
234 233 const params = new URLSearchParams(location.search);
235 234 const id = params.get('id');
  235 + const subOrderId = params.get('subOrderId');
236 236 if (id) {
237 237 mainTableFormRef.current?.setFieldValue('id', id);
238 238 }
  239 + if (subOrderId) {
  240 + mainTableFormRef.current?.setFieldValue('subOrderId', subOrderId);
  241 + }
239 242 }, []);
240 243  
241 244 useEffect(() => {
... ... @@ -1061,7 +1064,7 @@ const OrderPage = () =&gt; {
1061 1064 ? optRecord.invoicingUrgentCause
1062 1065 : enumValueToLabel(
1063 1066 optRecord.afterInvoicingStatus,
1064   - afterInvoicingStatus,
  1067 + AFTER_INVOICING_STATUS,
1065 1068 )
1066 1069 }
1067 1070 >
... ... @@ -1070,7 +1073,7 @@ const OrderPage = () =&gt; {
1070 1073 >
1071 1074 {enumValueToLabel(
1072 1075 optRecord.afterInvoicingStatus,
1073   - afterInvoicingStatus,
  1076 + AFTER_INVOICING_STATUS,
1074 1077 )}
1075 1078 </Tag>
1076 1079 </Tooltip>
... ... @@ -1445,7 +1448,7 @@ const OrderPage = () =&gt; {
1445 1448 ''
1446 1449 )}
1447 1450  
1448   - {optRecord.subPath?.includes('saleCancelInvoicing') ? (
  1451 + {/*{optRecord.subPath?.includes('saleCancelInvoicing') ? (
1449 1452 <ButtonConfirm
1450 1453 className="p-0"
1451 1454 title="确认取消申请开票?"
... ... @@ -1465,12 +1468,12 @@ const OrderPage = () =&gt; {
1465 1468 />
1466 1469 ) : (
1467 1470 ''
1468   - )}
  1471 + )}*/}
1469 1472 {optRecord.subPath?.includes('saleCancelInvoicing') ? (
1470 1473 <ButtonConfirm
1471 1474 className="p-0"
1472 1475 title="确认取消申请开票?"
1473   - text="取消申请(新)"
  1476 + text="取消申请"
1474 1477 onConfirm={async () => {
1475 1478 let res = await postServiceInvoiceCancelApply({
1476 1479 data: {
... ... @@ -1701,7 +1704,7 @@ const OrderPage = () =&gt; {
1701 1704 ''
1702 1705 )}
1703 1706  
1704   - {optRecord.subPath?.includes('applyInvoicing') ? (
  1707 + {/*{optRecord.subPath?.includes('applyInvoicing') ? (
1705 1708 <Button
1706 1709 className="p-0"
1707 1710 type="link"
... ... @@ -1716,6 +1719,23 @@ const OrderPage = () =&gt; {
1716 1719 </Button>
1717 1720 ) : (
1718 1721 ''
  1722 + )}*/}
  1723 +
  1724 + {optRecord.subPath?.includes('applyInvoicing') ? (
  1725 + <Button
  1726 + className="p-0"
  1727 + type="link"
  1728 + onClick={() => {
  1729 + setInvoicingDrawerFormVisible(true);
  1730 + createOptObject(optRecord.id, record.id);
  1731 + setIsEdit(false);
  1732 + setIsMainOrder(false);
  1733 + }}
  1734 + >
  1735 + 申请开票
  1736 + </Button>
  1737 + ) : (
  1738 + ''
1719 1739 )}
1720 1740  
1721 1741 {optRecord.subPath?.includes('checkOrder') ? (
... ... @@ -3088,7 +3108,7 @@ const OrderPage = () =&gt; {
3088 3108 ''
3089 3109 )}
3090 3110  
3091   - {record.mainPath?.includes('applyInvoicing') ? (
  3111 + {/*{record.mainPath?.includes('applyInvoicing') ? (
3092 3112 <Button
3093 3113 type="link"
3094 3114 className="p-0"
... ... @@ -3123,44 +3143,44 @@ const OrderPage = () =&gt; {
3123 3143 </Button>
3124 3144 ) : (
3125 3145 ''
3126   - )}
  3146 + )}*/}
3127 3147  
3128   - {/*{record.mainPath?.includes('applyInvoicing') ? (
3129   - <Button
3130   - type="link"
3131   - className="p-0"
3132   - onClick={() => {
3133   - let selectedSubOrders = subOrderSelectedMap.get(
3134   - record.id,
  3148 + {record.mainPath?.includes('applyInvoicing') ? (
  3149 + <Button
  3150 + type="link"
  3151 + className="p-0"
  3152 + onClick={() => {
  3153 + let selectedSubOrders = subOrderSelectedMap.get(
  3154 + record.id,
  3155 + );
  3156 + if (selectedSubOrders === undefined) {
  3157 + selectedSubOrders = record.subOrderInformationLists;
  3158 + }
  3159 + for (let i = 0; i < selectedSubOrders.length; i++) {
  3160 + if (
  3161 + selectedSubOrders[i].invoicingStatus ===
  3162 + 'UN_INVOICE' ||
  3163 + selectedSubOrders[i].afterInvoicingStatus ===
  3164 + 'APPLY_FOR_INVOICING'
  3165 + ) {
  3166 + message.error(
  3167 + '请选择需要开票且未申请开票的子订单进行申请',
3135 3168 );
3136   - if (selectedSubOrders === undefined) {
3137   - selectedSubOrders = record.subOrderInformationLists;
3138   - }
3139   - for (let i = 0; i < selectedSubOrders.length; i++) {
3140   - if (
3141   - selectedSubOrders[i].invoicingStatus ===
3142   - 'UN_INVOICE' ||
3143   - selectedSubOrders[i].afterInvoicingStatus ===
3144   - 'APPLY_FOR_INVOICING'
3145   - ) {
3146   - message.error(
3147   - '请选择需要开票且未申请开票的子订单进行申请',
3148   - );
3149   - return;
3150   - }
3151   - }
  3169 + return;
  3170 + }
  3171 + }
3152 3172  
3153   - createOptObject(null, record.id);
3154   - setApplyForInvoicingVisible(true);
3155   - setIsEdit(false);
3156   - setIsMainOrder(false);
3157   - }}
3158   - >
3159   - 申请开票
3160   - </Button>
  3173 + createOptObject(null, record.id);
  3174 + setInvoicingDrawerFormVisible(true);
  3175 + setIsEdit(false);
  3176 + setIsMainOrder(false);
  3177 + }}
  3178 + >
  3179 + 申请开票
  3180 + </Button>
3161 3181 ) : (
3162   - ''
3163   - )}*/}
  3182 + ''
  3183 + )}
3164 3184  
3165 3185 {record.mainPath?.includes('updateOrder') ? (
3166 3186 <Button
... ... @@ -4239,7 +4259,10 @@ const OrderPage = () =&gt; {
4239 4259 * 第一次进来这个页面,url带有id的话,会自动填充到查询表单中,但是第一次查询params不会带这个id进来
4240 4260 */
4241 4261 let orderIds = mainTableFormRef.current?.getFieldValue('id');
  4262 + let subOrderId =
  4263 + mainTableFormRef.current?.getFieldValue('subOrderId');
4242 4264 params.id = params.id || orderIds;
  4265 + params.subOrderId = params.subOrderId || subOrderId;
4243 4266 if (params.id !== '') {
4244 4267 params.id = params.id?.replace(/ /g, '');
4245 4268 if (params.id?.indexOf(',')) {
... ... @@ -4754,7 +4777,7 @@ const OrderPage = () =&gt; {
4754 4777 clearOptObject();
4755 4778 }
4756 4779 }}
4757   - mainOrderList={[...mainOrderSelectedMap.values()].flat()}
  4780 + mainOrder={isMainOrder ? getFirstMainOrder() : buildMainOrder()}
4758 4781 onClose={() => {
4759 4782 setInvoicingDrawerFormVisible(false);
4760 4783 setIsMainOrder(true);
... ...
src/services/request.ts
... ... @@ -8454,6 +8454,61 @@ export const postServiceConstAfterInvoicingStatus = /* #__PURE__ */ (() =&gt; {
8454 8454 return request;
8455 8455 })();
8456 8456  
  8457 +/** @description response type for postServiceConstBeforeInvoicingInvoiceRecordStatus */
  8458 +export interface PostServiceConstBeforeInvoicingInvoiceRecordStatusResponse {
  8459 + /**
  8460 + * @description
  8461 + * OK
  8462 + */
  8463 + 200: ServerResult;
  8464 + /**
  8465 + * @description
  8466 + * Created
  8467 + */
  8468 + 201: any;
  8469 + /**
  8470 + * @description
  8471 + * Unauthorized
  8472 + */
  8473 + 401: any;
  8474 + /**
  8475 + * @description
  8476 + * Forbidden
  8477 + */
  8478 + 403: any;
  8479 + /**
  8480 + * @description
  8481 + * Not Found
  8482 + */
  8483 + 404: any;
  8484 +}
  8485 +
  8486 +export type PostServiceConstBeforeInvoicingInvoiceRecordStatusResponseSuccess =
  8487 + PostServiceConstBeforeInvoicingInvoiceRecordStatusResponse[200];
  8488 +/**
  8489 + * @description
  8490 + * 开具类型
  8491 + * @tags front-const-controller
  8492 + * @produces *
  8493 + * @consumes application/json
  8494 + */
  8495 +export const postServiceConstBeforeInvoicingInvoiceRecordStatus =
  8496 + /* #__PURE__ */ (() => {
  8497 + const method = 'post';
  8498 + const url = '/service/const/beforeInvoicingInvoiceRecordStatus';
  8499 + function request(): Promise<PostServiceConstBeforeInvoicingInvoiceRecordStatusResponseSuccess> {
  8500 + return requester(request.url, {
  8501 + method: request.method,
  8502 + }) as unknown as Promise<PostServiceConstBeforeInvoicingInvoiceRecordStatusResponseSuccess>;
  8503 + }
  8504 +
  8505 + /** http method */
  8506 + request.method = method;
  8507 + /** request url */
  8508 + request.url = url;
  8509 + return request;
  8510 + })();
  8511 +
8457 8512 /** @description response type for postServiceConstCanApplyAfterInvoicingStatus */
8458 8513 export interface PostServiceConstCanApplyAfterInvoicingStatusResponse {
8459 8514 /**
... ...