Blame view

src/pages/Order/WarningWhitelist/components/InvoicingDrawerForm.tsx 18.6 KB
曾国涛 authored
1
// import { PlusOutlined } from '@ant-design/icons';
2
import InvoiceModal from '@/pages/Invoice/InvoiceVerification/components/InvoiceModal';
曾国涛 authored
3
import {
曾国涛 authored
4
  postServiceConstGetPayeeEnum,
5
  postServiceConstInitInvoiceDetailNames,
曾国涛 authored
6
7
  postServiceConstInvoiceType,
  postServiceConstInvoicingType,
曾国涛 authored
8
  postServiceConstListInvoiceDetailNames,
曾国涛 authored
9
  postServiceInvoiceApplyInvoice,
10
  postServiceInvoiceQueryCompanyInfo,
11
  postServiceInvoiceWaitReissueInvoices,
曾国涛 authored
12
} from '@/services';
13
import { FloatAdd, FloatSub, enum2ReverseSelect, enumToSelect } from '@/utils';
14
import { convertCurrency } from '@/utils/numberUtil';
曾国涛 authored
15
16
import {
  DrawerForm,
17
  FormListActionType,
曾国涛 authored
18
19
  ProCard,
  ProFormDigit,
曾国涛 authored
20
  ProFormGroup,
21
  ProFormInstance,
曾国涛 authored
22
23
  ProFormList,
  ProFormMoney,
曾国涛 authored
24
25
  ProFormSelect,
  ProFormText,
曾国涛 authored
26
  ProFormTextArea,
曾国涛 authored
27
} from '@ant-design/pro-components';
28
29
import { Button, Divider, Form, Space, Tooltip, message } from 'antd';
import { useEffect, useRef, useState } from 'react';
曾国涛 authored
30
31
export default ({ dataList, setVisible, mainOrder, onClose }) => {
曾国涛 authored
32
33
  // let subOrderIds = dataList?.map((item) => {
  //   return item.id;
34
  // })
曾国涛 authored
35
  const [form] = Form.useForm();
36
37
  const [projectOptions] = useState();
  const [dataListCopy] = useState(dataList);
38
  const listActionRef = useRef<FormListActionType>();
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  const formRef = useRef<ProFormInstance>();
  useEffect(() => {
    const initOptions = async () => {
      const res = await postServiceConstInitInvoiceDetailNames({
        data: dataListCopy.map((item) => {
          return item.productName;
        }),
      });
      const options = res.data;
      const datas = dataListCopy.map((item) => {
        return {
          ...item,
          projectName: options[item.productName],
        };
      });
      const initialValue = datas.map((item) => {
        return {
          productName: item.productName,
          projectName: item.projectName,
          subOrderId: item.id,
          specification: item.parameters,
          unit: item.unit,
          quantity: item.quantity,
          price: item.productPrice,
          totalPrice: item.subOrderPayment,
        };
      });
      form.setFieldValue('invoiceDetails', initialValue);
67
      form.setFieldValue('contacts', mainOrder.customerName);
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    };
    initOptions();
  }, []);

  useEffect(() => {}, [projectOptions]);

  function copyToClipboard(text: string) {
    // 创建一个临时的textarea元素
    const textarea = document.createElement('textarea');
    textarea.value = text;

    // 将textarea元素添加到DOM中
    document.body.appendChild(textarea);

    // 选中textarea中的文本
    textarea.select();

    try {
      // 尝试执行复制命令
      document.execCommand('copy');
      return true;
    } catch (err) {
      return false;
    } finally {
      // 移除临时的textarea元素
      document.body.removeChild(textarea);
    }
  }
曾国涛 authored
97
  useEffect(() => {}, []);
曾国涛 authored
98
  return (
曾国涛 authored
99
100
    <DrawerForm
      open
101
      title="申请开票"
曾国涛 authored
102
103
      resize={{
        maxWidth: window.innerWidth * 0.8,
104
        minWidth: 500,
曾国涛 authored
105
106
      }}
      form={form}
107
      formRef={formRef}
曾国涛 authored
108
109
110
111
      autoFocusFirstInput
      drawerProps={{
        destroyOnClose: true,
      }}
曾国涛 authored
112
113
114
115
116
117
      submitter={{
        render: (props, defaultDoms) => {
          return [
            <InvoiceModal
              key={'invoicePreview'}
              button={<Button type="primary"> 发票预览 </Button>}
118
              getRecord={() => {
119
120
121
                const totalPrice = form
                  .getFieldValue('invoiceDetails')
                  .reduce((accumulator, currentValue) => {
122
                    return FloatAdd(accumulator, currentValue.totalPrice);
123
                  }, 0);
124
125
126
127
                const partyBName = form.getFieldValue('partyBName');
                const openBank = form.getFieldValue('openBank');
                const bankAccount = form.getFieldValue('bankAccount');
                const bankCode = form.getFieldValue('bankCode');
128
129
130
131
                return {
                  ...form.getFieldsValue(),
                  totalPrice: totalPrice,
                  totalPriceText: convertCurrency(totalPrice),
132
133
134
135
136
137
138
139
140
141
142
143
                  comment:
                    '开户名称: ' +
                    partyBName +
                    '\n' +
                    '开户行: ' +
                    openBank +
                    '\n' +
                    '账号: ' +
                    bankAccount +
                    '\n' +
                    '银行联行号: ' +
                    bankCode,
144
145
                };
              }}
曾国涛 authored
146
147
148
149
150
            />,
            ...defaultDoms,
          ];
        },
      }}
曾国涛 authored
151
152
      submitTimeout={2000}
      onFinish={async (values) => {
曾国涛 authored
153
154
155
        postServiceInvoiceApplyInvoice({
          data: {
            ...values,
156
            subOrderIds: dataListCopy.map((item) => {
曾国涛 authored
157
158
159
160
              return item.id;
            }),
          },
        });
曾国涛 authored
161
        onClose();
曾国涛 authored
162
163
164
      }}
      onOpenChange={(val) => {
        return !val && setVisible();
曾国涛 authored
165
166
      }}
    >
曾国涛 authored
167
      <ProFormList
曾国涛 authored
168
        name="subOrderIdObjs"
曾国涛 authored
169
        readonly={true}
曾国涛 authored
170
        label="开票订单"
171
        initialValue={dataListCopy.map((item) => {
曾国涛 authored
172
173
174
175
          return {
            value: item.id,
          };
        })}
曾国涛 authored
176
        deleteIconProps={false}
177
        copyIconProps={false}
曾国涛 authored
178
      >
曾国涛 authored
179
        <ProFormGroup key="group">
曾国涛 authored
180
          <ProFormText readonly={true} name="value" label="" />
曾国涛 authored
181
        </ProFormGroup>
曾国涛 authored
182
      </ProFormList>
183
      <ProFormSelect
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
        name="ReissueInvoiceRecordIds"
        label="重开的发票"
        fieldProps={{
          mode: 'multiple',
        }}
        placeholder="请选择重开发票"
        request={async () => {
          let reissueIds = dataListCopy.map((item) => {
            return item.id;
          });
          let res = await postServiceInvoiceWaitReissueInvoices({
            data: reissueIds,
          });
          return enum2ReverseSelect(res.data);
        }}
      />
      <ProFormSelect
201
202
203
204
205
206
207
208
209
210
211
212
213
        key="key"
        label="购方名称"
        width="lg"
        showSearch
        name="partyAName"
        placeholder="请搜索购方"
        rules={[{ required: true, message: '购方名称必填' }]}
        onChange={(_, option) => {
          form.setFieldValue('partyATaxid', option.taxId);
        }}
        fieldProps={{
          optionItemRender(item) {
            if (item.type === 'add') {
214
              return <>{item.name}</>;
215
216
217
            }
            return (
              <>
218
                {item.name}
219
                <Divider type="vertical" />
220
                {item.taxId}
221
222
223
224
225
226
227
228
              </>
            );
          },
        }}
        debounceTime={1000}
        request={async (value) => {
          const keywords = value.keyWords;
          const res = await postServiceInvoiceQueryCompanyInfo({
229
230
231
232
            data: {
              nameLike: keywords,
              taxIdIsNotNull: true,
            },
233
234
235
236
237
          });
          let options = res?.data?.map((company) => {
            return {
              ...company,
              label: company.name,
238
              value: company.name,
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
              key: company.id,
            };
          });

          //第一个商品默认为要新增的商品
          if (keywords.trim() !== '') {
            options.unshift({
              name: keywords,
              type: 'add',
              label: keywords,
              value: keywords,
              key: keywords,
            });
          }
          return options;
        }}
      />
曾国涛 authored
256
257
      <ProFormText
        width="md"
曾国涛 authored
258
        name="partyATaxid"
曾国涛 authored
259
        label="购方税号"
260
        rules={[{ required: true, message: '购方税号必填' }]}
曾国涛 authored
261
262
263
264
        placeholder="请输入名称"
      />
      <ProFormText
        width="md"
曾国涛 authored
265
        name="partyAOpenBank"
曾国涛 authored
266
267
268
269
270
        label="开户银行"
        placeholder="请输入名称"
      />
      <ProFormText
        width="md"
曾国涛 authored
271
        name="partyABankAccount"
曾国涛 authored
272
273
274
        label="开户行账号"
        placeholder="请输入名称"
      />
275
276
277
278
279
      <ProFormText
        name="contacts"
        label="联系人"
        rules={[{ required: true, message: '请选择银行联行号!' }]}
      />
曾国涛 authored
280
      <ProFormSelect
曾国涛 authored
281
        name="invoicingType"
曾国涛 authored
282
        label="开具类型"
曾国涛 authored
283
284
285
286
287
        request={async () => {
          let invoicingTypeRet = await postServiceConstInvoicingType();
          let options = enumToSelect(invoicingTypeRet.data);
          return options;
        }}
曾国涛 authored
288
289
        placeholder="请选择开具类型"
        rules={[{ required: true, message: '请选择开具类型!' }]}
曾国涛 authored
290
291
      />
      <ProFormSelect
曾国涛 authored
292
        name="type"
曾国涛 authored
293
        label="开票类型"
曾国涛 authored
294
295
        placeholder="请选择开票类型"
        rules={[{ required: true, message: '请选择开票类型!' }]}
曾国涛 authored
296
297
298
299
300
        request={async () => {
          let invoiceTypeRet = await postServiceConstInvoiceType();
          let options = enumToSelect(invoiceTypeRet.data);
          return options;
        }}
曾国涛 authored
301
302
      />
      <ProFormSelect
曾国涛 authored
303
        name="partyB"
曾国涛 authored
304
        label="开票收款单位"
曾国涛 authored
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
        request={async () => {
          const res = await postServiceConstGetPayeeEnum();
          let options = res?.data?.map((payee: any) => {
            return {
              ...payee,
              label: payee.payeeName,
              value: payee.name,
            };
          });
          return options;
        }}
        onChange={(_, option) => {
          if (option) {
            form.setFieldsValue({
              partyBName: option.payeeName,
              partyBTaxid: option.taxId,
321
322
323
              bankAccount: option.bankAccount,
              openBank: option.openBank,
              bankCode: option.bankCode,
曾国涛 authored
324
325
326
            });
          }
        }}
曾国涛 authored
327
328
        placeholder="请选择收款单位"
        rules={[{ required: true, message: '请选择收款单位!' }]}
曾国涛 authored
329
      />
曾国涛 authored
330
331
332
333
334
335
336
337
338
339
340
341
      <ProFormText
        name="partyBName"
        label="开票收款单位名称"
        hidden
        rules={[{ required: true, message: '请选择收款单位!' }]}
      />
      <ProFormText
        name="partyBTaxid"
        label="开票收款单位税号"
        hidden
        rules={[{ required: true, message: '请选择收款单位!' }]}
      />
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
      <ProFormText
        name="bankAccount"
        label="账号"
        hidden
        rules={[{ required: true, message: '请选择账号!' }]}
      />
      <ProFormText
        name="openBank"
        label="开户行"
        hidden
        rules={[{ required: true, message: '请选择开户行!' }]}
      />
      <ProFormText
        name="bankCode"
        label="银行联行号"
        hidden
        rules={[{ required: true, message: '请选择银行联行号!' }]}
      />
曾国涛 authored
360
      <ProFormSelect
曾国涛 authored
361
        name="isUrgent"
曾国涛 authored
362
363
        label="是否加急"
        valueEnum={{
曾国涛 authored
364
365
          true: '是',
          false: '否',
曾国涛 authored
366
        }}
曾国涛 authored
367
368
        placeholder="请选择是否加急"
        rules={[{ required: true, message: '请选择是否加急!' }]}
曾国涛 authored
369
      />
370
371
372
373
374
375
376
377
378
379
      <ProFormMoney
        label="开票金额"
        name="price"
        locale="zh-CN"
        disabled={true}
        rules={[{ required: true, message: '请填写开票金额!' }]}
        initialValue={dataListCopy.reduce((accumulator, currentValue) => {
          return accumulator + currentValue.subOrderPayment;
        }, 0)}
      />
曾国涛 authored
380
381
382
      <ProFormList
        name="invoiceDetails"
        label="开票明细"
383
384
385
386
387
388
389
390
391
392
393
394
        actionRef={listActionRef}
        actionGuard={{
          beforeRemoveRow: async (index) => {
            const list = listActionRef.current?.getList();
            const totalPrice = list[index].totalPrice;
            form.setFieldValue(
              'price',
              FloatSub(form.getFieldValue('price'), totalPrice),
            );
            return true;
          },
        }}
曾国涛 authored
395
396
397
398
399
400
401
402
403
404
405
        rules={[
          {
            required: true,
            validator: async (_, value) => {
              if (value && value.length > 0) {
                return;
              }
              throw new Error('至少要有一项!');
            },
          },
        ]}
曾国涛 authored
406
407
408
409
410
411
412
413
414
415
        itemRender={(doms, listMeta) => {
          return (
            <ProCard
              bordered
              extra={doms.action}
              title={'明细' + (listMeta.index + 1)}
              style={{
                marginBlockEnd: 8,
              }}
            >
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
              <Tooltip title="点击复制商品名称">
                <Space
                  className="hover:cursor-pointer"
                  style={{
                    margin: 16,
                    marginTop: 4,
                    marginLeft: 0,
                    fontSize: 15,
                  }}
                  onClick={() => {
                    copyToClipboard(listMeta.record.productName);
                    message.info('商品名称复制成功!');
                  }}
                >
                  商品名称:{listMeta.record.productName}
                </Space>
              </Tooltip>
曾国涛 authored
433
434
435
              <ProFormSelect
                key={'projectName' + listMeta.index}
                width="md"
曾国涛 authored
436
                showSearch
曾国涛 authored
437
                name="projectName"
438
                rules={[{ required: true, message: '请输入开票项目名称!' }]}
曾国涛 authored
439
440
441
442
443
444
445
446
447
448
                request={async (value) => {
                  const keywords = value.keyWords;
                  const res = await postServiceConstListInvoiceDetailNames({
                    data: {
                      nameLike: keywords,
                    },
                  });
                  let options = res?.data?.map((c: any) => {
                    return {
                      ...c,
449
450
451
452
453
                      label:
                        '*' +
                        c.productAndServiceCatagoryAbbreviation +
                        '*' +
                        c.name,
曾国涛 authored
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
                      value:
                        '*' +
                        c.productAndServiceCatagoryAbbreviation +
                        '*' +
                        c?.name,
                      key: c.id,
                    };
                  });
                  return options;
                }}
                fieldProps={{
                  filterOption() {
                    return true;
                  },
                }}
                onChange={(_, option) => {
                  let index = listMeta.index;
                  let copyList = form.getFieldValue('invoiceDetails');
                  let currentData = copyList[index];
                  currentData.projectName =
                    '*' +
                    option.productAndServiceCatagoryAbbreviation +
                    '*' +
                    option.name;
                  form.setFieldValue('invoiceDetails', copyList);
                }}
                debounceTime={1000}
                label="项目名称"
482
                initialValue={listMeta.record.projectName}
曾国涛 authored
483
484
485
486
487
488
                placeholder="请输入名称"
              />
              <ProFormText
                key={'specification' + listMeta.index}
                name="specification"
                label="规格型号"
489
490
491
492
493
                rules={[
                  {
                    message: '规格型号不能为空!',
                    required: true,
                  },
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
                  {
                    validator: (_, value) => {
                      let len = 0;
                      // 判断是否为全角字符
                      for (let i = 0; i < value.length; i++) {
                        // 获取字符的Unicode值
                        const code = value.charCodeAt(i);
                        // 判断是否为全角字符
                        if (
                          (code >= 0xff01 && code <= 0xff5e) ||
                          (code >= 0x4e00 && code <= 0x9fff)
                        ) {
                          len += 2; // 全角字符
                        } else {
                          len += 1; // 半角字符
                        }
                      }
                      if (len <= 40) {
                        return Promise.resolve();
                      }
                      return Promise.reject(
                        new Error('规格型号不能超过40个字符!'),
                      );
                    },
                  },
519
                ]}
曾国涛 authored
520
521
522
523
524
525
526
527
528
529
530
531
                placeholder="请输入名称"
              />
              <ProFormText
                key={'unit' + listMeta.index}
                name="unit"
                label="单位"
                placeholder="请输入名称"
              />
              <ProFormDigit
                key={'quantity' + listMeta.index}
                label="数量"
                name="quantity"
532
533
534
535
536
537
538
539
540
541
                rules={[
                  {
                    validator: (_, value) => {
                      if (value === undefined || value > 0) {
                        return Promise.resolve();
                      }
                      return Promise.reject(new Error('数量必须大于0'));
                    },
                  },
                ]}
曾国涛 authored
542
543
544
545
546
              />
              <ProFormDigit
                key={'price' + listMeta.index}
                label="单价"
                name="price"
547
548
549
550
551
552
553
554
555
556
                rules={[
                  {
                    validator: (_, value) => {
                      if (value === undefined || value > 0) {
                        return Promise.resolve();
                      }
                      return Promise.reject(new Error('单价必须大于0'));
                    },
                  },
                ]}
曾国涛 authored
557
558
559
560
561
              />
              <ProFormMoney
                key={'totalPrice' + listMeta.index}
                label="金额"
                name="totalPrice"
562
563
564
565
566
567
568
569
570
571
572
573
                onChange={() => {
                  const invoiceDetails = form.getFieldValue('invoiceDetails');
                  console.log('invoiceDetails', invoiceDetails);
                  const totalPrice = invoiceDetails.reduce(
                    (accumulator, currentValue) => {
                      return FloatAdd(accumulator, currentValue.totalPrice);
                    },
                    0,
                  );
                  console.log('totalPrice', totalPrice);
                  form.setFieldValue('price', totalPrice);
                }}
574
575
576
577
578
579
580
581
582
583
                rules={[
                  {
                    validator: (_, value) => {
                      if (value === undefined || value > 0) {
                        return Promise.resolve();
                      }
                      return Promise.reject(new Error('金额必须大于0'));
                    },
                  },
                ]}
曾国涛 authored
584
585
586
587
588
589
                locale="zh-CN"
              />
            </ProCard>
          );
        }}
      ></ProFormList>
曾国涛 authored
590
591
592
593
594
      <ProFormTextArea
        name="applyInvoicingNotes"
        label="备注"
        placeholder="请输入名称"
      />
曾国涛 authored
595
596
597
    </DrawerForm>
  );
};