kts-component-invoice-operate 3.2.23 → 3.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kts-component-invoice-operate",
3
- "version": "3.2.23",
3
+ "version": "3.2.25",
4
4
  "scripts": {
5
5
  "start": "dumi dev",
6
6
  "docs:build": "dumi build",
@@ -1,10 +1,15 @@
1
1
  import React from 'react';
2
2
  import Invoice from '../../..';
3
3
  import 'antd/dist/antd.css';
4
+ import InvoiceController from '../../../InvoiceController';
4
5
 
5
6
  export default () => {
7
+
8
+ const invoiceController = React.useMemo(() => new MyInvoiceController(), []);
9
+
6
10
  return (
7
11
  <Invoice
12
+ controller={invoiceController}
8
13
  invoiceType='digtal'
9
14
  invoiceHeader={
10
15
  <Invoice.InvoiceHeaderDigtal
@@ -15,3 +20,66 @@ export default () => {
15
20
  />
16
21
  )
17
22
  };
23
+
24
+ class MyInvoiceController extends InvoiceController {
25
+
26
+ constructor() {
27
+ super();
28
+ this.state.autoComplete.onItemNameSearch = async text => {
29
+ return [
30
+ {
31
+ "itemName": "呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵",
32
+ "taxClassificationCode": "1010112070000000000",
33
+ "itemModelName": null,
34
+ "shorthand": "蔬菜",
35
+ "taxRate": undefined
36
+ },
37
+ {
38
+ "itemName": "稻谷",
39
+ "taxClassificationCode": "1010101040000000000",
40
+ "itemModelName": null,
41
+ "shorthand": "谷物",
42
+ "taxRate": 3
43
+ },
44
+ {
45
+ "itemName": "苹果",
46
+ "taxClassificationCode": "1090111090000000000",
47
+ "itemModelName": null,
48
+ "shorthand": "小型起重设备",
49
+ "taxRate": null
50
+ },
51
+ {
52
+ "itemName": "银丝",
53
+ "taxClassificationCode": "1080411120000000000",
54
+ "itemModelName": null,
55
+ "shorthand": "金属制品",
56
+ "taxRate": 3
57
+ },
58
+ {
59
+ "itemName": "布料",
60
+ "taxClassificationCode": "1100101011100000000",
61
+ "itemModelName": null,
62
+ "shorthand": "发电",
63
+ "taxRate": 2
64
+ },
65
+ {
66
+ "itemName": "苹果",
67
+ "taxClassificationCode": "1010115010100000000",
68
+ "itemModelName": null,
69
+ "shorthand": "水果",
70
+ "taxRate": 3
71
+ }
72
+ ] as any
73
+ }
74
+
75
+ this.state.autoComplete.onBuyerTaxIdSearch = this.state.autoComplete.onBuyerNameSearch = async test => {
76
+ return [
77
+ { buyerName: '测试1', buyerTaxId: 'xxxxx1', buyerPhone:'xxxx1' },
78
+ { buyerName: '测试2', buyerTaxId: 'xxxxx2', buyerPhone:'xxxx2' },
79
+ { buyerName: '测试4', buyerTaxId: 'xxxxx4', buyerPhone:'xxxx4' },
80
+ { buyerName: '测试5', buyerTaxId: 'xxxxx5', buyerPhone:'xxxx5' },
81
+ { buyerName: '测试6', buyerTaxId: 'xxxxx6', buyerPhone:'xxxx6' },
82
+ ]
83
+ }
84
+ }
85
+ }
@@ -4,5 +4,11 @@ import IGood from "../GoodsListState/IGood";
4
4
  export default class AutoComplete {
5
5
 
6
6
  /** 商品名称自动补全 */
7
- onItemNameSearch?: (searchText: string) => Promise<IGood[]>
7
+ onItemNameSearch?: (searchText: string) => Promise<IGood[]>;
8
+
9
+ /** 购方名称自动补全 */
10
+ onBuyerNameSearch?: (searchText: string) => Promise<any[]>;
11
+
12
+ /** 统一社会信用代码/纳税人识别号 */
13
+ onBuyerTaxIdSearch?: (searchText: string) => Promise<any[]>;
8
14
  }
@@ -0,0 +1,68 @@
1
+ import { dutyFree, format15, updateUnitPriceExcludingTax, updateUnitPriceTax } from '../../ui/default/GoodsList/hook/useColumns/autoFillFn';
2
+ import { InvoiceControllerState, IGood } from '../';
3
+ import evaluate from '../../tools/evaluate';
4
+ import { countAmountIncludeTax } from '../../tools/calculate';
5
+
6
+ /**
7
+ * 删除一个货物
8
+ */
9
+ export default async (s: InvoiceControllerState, record: any, controller:any) => {
10
+ Object.keys(record).filter(e => !record[e] && record[e] !== 0).forEach(e => { delete record[e] });
11
+
12
+ // 没用 被编辑的货物 和 form 就退出
13
+ if (!s.goodsListState.editGood || !s.goodsListState.form) return;
14
+
15
+ // 导入时清空之前输入的值,使用导入的单价和税率(参考税局系统)
16
+ record.quantity = undefined;
17
+ record.lineAmountExcludeTax = undefined;
18
+ record.lineAmountIncludeTax = undefined;
19
+
20
+ // 中间数据
21
+ const between = { ...record };
22
+ between.itemName = record.itemName;
23
+ between.itemNameOther = record.itemName;
24
+
25
+ // 设置编辑货物
26
+ const editGood: IGood = s.goodsListState.editGood = { ...s.goodsListState.editGood, ...between };
27
+
28
+ if (editGood.taxRate) {
29
+ editGood.taxRate = dutyFree(controller, editGood.taxRate, s.goodsListState.form, editGood)
30
+ }
31
+
32
+ if (`${editGood.priceIncludeTax}` === '0') {
33
+ editGood.priceIncludeTax = undefined;
34
+ editGood.priceExcludeTax = undefined;
35
+ } else {
36
+ editGood.priceExcludeTax = getPriceExcludeTax(editGood, record, s.calculatingDigits) as number;
37
+ }
38
+
39
+ if (editGood.quantity && editGood.priceIncludeTax) {
40
+ editGood.lineAmountIncludeTax = countAmountIncludeTax(editGood.quantity, editGood.priceIncludeTax, s.calculatingDigits);
41
+ }
42
+
43
+ // 导入FORM里
44
+ if (s.goodsListState.isMyShow) {
45
+ s.goodsListState.form.setFieldsValue({
46
+ ...editGood,
47
+ itemName: editGood.itemNameSelf,
48
+ itemModelName: editGood.itemModelNameSelf,
49
+ });
50
+ } else {
51
+ s.goodsListState.form.setFieldsValue({
52
+ ...editGood,
53
+ });
54
+ }
55
+
56
+ s.goodsListState.importGoods.isVisibleDrawer = false;
57
+ s.goodsListState.isTaxIncluded
58
+ ? await updateUnitPriceExcludingTax(controller, s.goodsListState.form, record)
59
+ : await updateUnitPriceTax(controller, s.goodsListState.form, record)
60
+ }
61
+
62
+ /** 货物单价,不含税 */
63
+ const getPriceExcludeTax = (s: IGood, record: any, calculatingDigits?: number) => {
64
+ if ((!s.taxRate && s.taxRate !== 0) || (!record.priceIncludeTax && record.priceIncludeTax !== 0)) return;
65
+
66
+ // 单价(含税)/(1+税率) = 单价(不含税)
67
+ return format15(evaluate(`${record.priceIncludeTax} / (1+${s.taxRate}/100)`), calculatingDigits);
68
+ };
@@ -13,7 +13,8 @@ import saveEditGood from './fns/saveEditGood';
13
13
  import getGoodsSearch from './fns/getGoodsSearch';
14
14
  import mergeDetails from './fns/mergeDetails';
15
15
  import mergeDiscount from './fns/mergeDiscount';
16
-
16
+ import importGoodsDrawer from './fns/importGoodsDrawer';
17
+ 0
17
18
  export { default as InvoiceControllerState } from './InvoiceControllerState';
18
19
  export { default as IGood } from './InvoiceControllerState/GoodsListState/IGood';
19
20
  export { default as LineAttributeType } from './InvoiceControllerState/GoodsListState/LineAttributeType';
@@ -62,6 +63,9 @@ export default class InvoiceController extends InvoiceControllerForm {
62
63
  /** 给一组货物添加折扣行 */
63
64
  addGoodDiscountV2 = this.pipeline(addGoodDiscountV2);
64
65
 
66
+ /** 导入商品 */
67
+ importGoodsDrawer = this.pipeline(importGoodsDrawer);
68
+
65
69
  /** 获取 商品 列表 */
66
70
  getGoodsList?: (option?: IGetGoodsListOption | undefined) => Promise<any>;
67
71
 
@@ -2,11 +2,11 @@
2
2
  import { Input } from 'kts-components-antd-x3';
3
3
  import React, { ChangeEvent } from 'react';
4
4
  import { AutoComplete } from 'kts-xui';
5
- import { countAmountIncludeTax } from '../../../../../../../tools/calculate'
5
+ // import { countAmountIncludeTax } from '../../../../../../../tools/calculate'
6
6
  import { IGood, Invoice } from '../../../../../../../..';
7
7
  import './index.less';
8
- import { dutyFree, format15, updateUnitPriceExcludingTax, updateUnitPriceTax } from '../../autoFillFn';
9
- import evaluate from '../../../../../../../tools/evaluate';
8
+ // import { dutyFree, format15, updateUnitPriceExcludingTax, updateUnitPriceTax } from '../../autoFillFn';
9
+ // import evaluate from '../../../../../../../tools/evaluate';
10
10
 
11
11
  export default function ItemNameInput(props: { onChange?: (e: ChangeEvent<HTMLInputElement>) => void, value?: string, shorthand?: string }) {
12
12
 
@@ -37,60 +37,60 @@ export default function ItemNameInput(props: { onChange?: (e: ChangeEvent<HTMLIn
37
37
  // good && controller.state.goodsListState.form?.setFieldsValue(removeNullUndefined(good));
38
38
 
39
39
  const record = options.filter(e => e.itemName === itemName)[0] as any;
40
- debugger;
41
40
  if (!record) return;
42
- controller.run(async s => {
43
- Object.keys(record).filter(e => !record[e] && record[e] !== 0).forEach(e => { delete record[e] });
44
-
45
- // 没用 被编辑的货物 和 form 就退出
46
- if (!s.goodsListState.editGood || !s.goodsListState.form) return;
47
-
48
- // 导入时清空之前输入的值,使用导入的单价和税率(参考税局系统)
49
- record.quantity = undefined;
50
- record.lineAmountExcludeTax = undefined;
51
- record.lineAmountIncludeTax = undefined;
52
-
53
- // 中间数据
54
- const between = { ...record };
55
- between.itemName = record.itemName;
56
- between.itemNameOther = record.itemName;
57
-
58
- // 设置编辑货物
59
- const editGood: IGood = s.goodsListState.editGood = { ...s.goodsListState.editGood, ...between };
60
-
61
- if (editGood.taxRate) {
62
- editGood.taxRate = dutyFree(controller, editGood.taxRate, s.goodsListState.form, editGood)
63
- }
64
-
65
- if (`${editGood.priceIncludeTax}` === '0') {
66
- editGood.priceIncludeTax = undefined;
67
- editGood.priceExcludeTax = undefined;
68
- } else {
69
- editGood.priceExcludeTax = getPriceExcludeTax(editGood, record, s.calculatingDigits) as number;
70
- }
71
-
72
- if (editGood.quantity && editGood.priceIncludeTax) {
73
- editGood.lineAmountIncludeTax = countAmountIncludeTax(editGood.quantity, editGood.priceIncludeTax, s.calculatingDigits);
74
- }
75
-
76
- // 导入FORM里
77
- if (s.goodsListState.isMyShow) {
78
- s.goodsListState.form.setFieldsValue({
79
- ...editGood,
80
- itemName: editGood.itemNameSelf,
81
- itemModelName: editGood.itemModelNameSelf,
82
- });
83
- } else {
84
- s.goodsListState.form.setFieldsValue({
85
- ...editGood,
86
- });
87
- }
88
-
89
- s.goodsListState.importGoods.isVisibleDrawer = false;
90
- s.goodsListState.isTaxIncluded
91
- ? await updateUnitPriceExcludingTax(controller, s.goodsListState.form, record)
92
- : await updateUnitPriceTax(controller, s.goodsListState.form, record)
93
- })
41
+ controller.importGoodsDrawer(record);
42
+ // controller.run(async s => {
43
+ // Object.keys(record).filter(e => !record[e] && record[e] !== 0).forEach(e => { delete record[e] });
44
+
45
+ // // 没用 被编辑的货物 form 就退出
46
+ // if (!s.goodsListState.editGood || !s.goodsListState.form) return;
47
+
48
+ // // 导入时清空之前输入的值,使用导入的单价和税率(参考税局系统)
49
+ // record.quantity = undefined;
50
+ // record.lineAmountExcludeTax = undefined;
51
+ // record.lineAmountIncludeTax = undefined;
52
+
53
+ // // 中间数据
54
+ // const between = { ...record };
55
+ // between.itemName = record.itemName;
56
+ // between.itemNameOther = record.itemName;
57
+
58
+ // // 设置编辑货物
59
+ // const editGood: IGood = s.goodsListState.editGood = { ...s.goodsListState.editGood, ...between };
60
+
61
+ // if (editGood.taxRate) {
62
+ // editGood.taxRate = dutyFree(controller, editGood.taxRate, s.goodsListState.form, editGood)
63
+ // }
64
+
65
+ // if (`${editGood.priceIncludeTax}` === '0') {
66
+ // editGood.priceIncludeTax = undefined;
67
+ // editGood.priceExcludeTax = undefined;
68
+ // } else {
69
+ // editGood.priceExcludeTax = getPriceExcludeTax(editGood, record, s.calculatingDigits) as number;
70
+ // }
71
+
72
+ // if (editGood.quantity && editGood.priceIncludeTax) {
73
+ // editGood.lineAmountIncludeTax = countAmountIncludeTax(editGood.quantity, editGood.priceIncludeTax, s.calculatingDigits);
74
+ // }
75
+
76
+ // // 导入FORM里
77
+ // if (s.goodsListState.isMyShow) {
78
+ // s.goodsListState.form.setFieldsValue({
79
+ // ...editGood,
80
+ // itemName: editGood.itemNameSelf,
81
+ // itemModelName: editGood.itemModelNameSelf,
82
+ // });
83
+ // } else {
84
+ // s.goodsListState.form.setFieldsValue({
85
+ // ...editGood,
86
+ // });
87
+ // }
88
+
89
+ // s.goodsListState.importGoods.isVisibleDrawer = false;
90
+ // s.goodsListState.isTaxIncluded
91
+ // ? await updateUnitPriceExcludingTax(controller, s.goodsListState.form, record)
92
+ // : await updateUnitPriceTax(controller, s.goodsListState.form, record)
93
+ // })
94
94
  }, [options, controller])
95
95
 
96
96
  return (
@@ -117,9 +117,9 @@ export default function ItemNameInput(props: { onChange?: (e: ChangeEvent<HTMLIn
117
117
  // }
118
118
 
119
119
  /** 货物单价,不含税 */
120
- const getPriceExcludeTax = (s: IGood, record: any, calculatingDigits?: number) => {
121
- if ((!s.taxRate && s.taxRate !== 0) || (!record.priceIncludeTax && record.priceIncludeTax !== 0)) return;
120
+ // const getPriceExcludeTax = (s: IGood, record: any, calculatingDigits?: number) => {
121
+ // if ((!s.taxRate && s.taxRate !== 0) || (!record.priceIncludeTax && record.priceIncludeTax !== 0)) return;
122
122
 
123
- // 单价(含税)/(1+税率) = 单价(不含税)
124
- return format15(evaluate(`${record.priceIncludeTax} / (1+${s.taxRate}/100)`), calculatingDigits);
125
- };
123
+ // // 单价(含税)/(1+税率) = 单价(不含税)
124
+ // return format15(evaluate(`${record.priceIncludeTax} / (1+${s.taxRate}/100)`), calculatingDigits);
125
+ // };
@@ -1,24 +1,50 @@
1
1
 
2
- import { Input } from 'kts-xui';
2
+ import { AutoComplete, Input } from 'kts-xui';
3
3
  import React, { ChangeEvent } from 'react';
4
+ import { IGood, Invoice } from '../../../../../../../..';
4
5
  import './index.less';
5
6
 
6
- export default function ItemNameInput(props: {
7
- onChange?: (e: ChangeEvent<HTMLInputElement>) => void,
8
- suffix?: React.ReactNode,
9
- value?: string,
10
- shorthand?: string
7
+ export default function ItemNameInput(props: {
8
+ onChange?: (e: ChangeEvent<HTMLInputElement>) => void,
9
+ suffix?: React.ReactNode,
10
+ value?: string,
11
+ shorthand?: string
11
12
  }) {
12
13
 
14
+ const controller = Invoice.useInvoiceController();
15
+
16
+ const autoComplete = controller.useMemo(s => s.autoComplete, [])
17
+
18
+ const [options, setOptions] = React.useState<IGood[]>([])
19
+
13
20
  const onChange = React.useCallback((e: ChangeEvent<HTMLInputElement>) => {
14
21
  const event = { ...e };
15
22
  props.onChange && props.onChange(event);
16
23
  }, [])
17
24
 
25
+ const onChangeAutoComplete = React.useCallback(itemName => {
26
+ const record = options.filter(e => e.itemName === itemName)[0] as any;
27
+ if (!record) return;
28
+ controller.importGoodsDrawer(record);
29
+ }, [options, controller])
30
+
31
+ const onSearch = React.useCallback(async (searchText: string) => {
32
+ try {
33
+ if (autoComplete.onItemNameSearch) {
34
+ setOptions(await autoComplete.onItemNameSearch(searchText));
35
+ }
36
+ } catch (error) {
37
+ setOptions([]);
38
+ throw error;
39
+ }
40
+ }, [autoComplete.onItemNameSearch])
41
+
18
42
  return (
19
43
  <div className='kts-invoice-operate-goods-list-itemName-input'>
20
44
  {props.shorthand && <span style={{ alignSelf: 'center', fontSize: 12 }} >*{props.shorthand}*</span>}
21
- <Input style={{ height: '100%' }} value={props.value} onChange={onChange} suffix={props.suffix} />
45
+ <AutoComplete onSearch={onSearch} options={options.map(e => ({ value: e.itemName }))} onChange={onChangeAutoComplete} >
46
+ <Input style={{ height: '100%' }} value={props.value} onChange={onChange} suffix={props.suffix} />
47
+ </AutoComplete>
22
48
  </div>
23
49
  )
24
50
  }
@@ -1,10 +1,11 @@
1
1
 
2
- import React from "react";
2
+ import React, { ChangeEvent } from 'react';
3
3
  import Icon from '@ant-design/icons';
4
4
  import { decorator } from "grey-react-box";
5
5
  import { Form } from "kts-components-antd-x3";
6
- import { Button, Col, Input, InputProps, Row, Tooltip } from 'kts-xui'
6
+ import { AutoComplete, Button, Col, Input, InputProps, Row, Tooltip } from 'kts-xui'
7
7
  import { FormComponentProps } from "kts-components-antd-x3/lib/form";
8
+ import { WrappedFormUtils } from 'kts-components-antd-x3/lib/form/Form';
8
9
  import { ReactComponent as ArrowUpSvg } from './svg/arrowUp.svg';
9
10
  import { ReactComponent as ArrowDownSvg } from './svg/arrowDown.svg';
10
11
  import { ReactComponent as PlusSvg } from './svg/plus.svg'
@@ -19,21 +20,21 @@ const RULES = {
19
20
  { pattern: /^([A-Za-z()\u4e00-\u9fa5])*$/g, message: `${label}仅能中文、英文、括号` }
20
21
  ],
21
22
  companyNameByNormal: (label: string) => [
22
- { required: true, message: `${label}必填` },
23
- { max: 200, message: `${label}内容超长` }
23
+ { required: true, message: `${label}必填` },
24
+ { max: 200, message: `${label}内容超长` }
24
25
  ],
25
26
  taxId: (label: string) => [
26
27
  { max: 20, message: `${label}内容超长` },
27
28
  { pattern: /^([a-zA-Z0-9])*$/g, message: `${label}仅能数字、英文` }
28
29
  ],
29
30
  buyerTelPhone: (label: string) => [
30
- { max: 100, message: `${label}内容超长` },
31
- { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` }
31
+ { max: 100, message: `${label}内容超长` },
32
+ { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` }
32
33
  ],
33
34
  sellerTelPhone: (label: string) => [
34
- { required: true, message: `${label}必填` },
35
- { max: 100, message: `${label}内容超长` },
36
- { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` }
35
+ { required: true, message: `${label}必填` },
36
+ { max: 100, message: `${label}内容超长` },
37
+ { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` }
37
38
  ],
38
39
  bankName: (label: string) => [
39
40
  { max: 100, message: `${label}内容超长` }
@@ -69,7 +70,7 @@ export interface IStakeholder {
69
70
  /** 干系人 */
70
71
  export default decorator<IStakeholder, IStakeholder & FormComponentProps>(Form.create())(props => {
71
72
 
72
- const { form, isShowImportButton, onClickImportButton , isVatNormal = false} = props;
73
+ const { form, isShowImportButton, onClickImportButton, isVatNormal = false } = props;
73
74
 
74
75
  const [isExpand, setExpand] = React.useState(true);
75
76
 
@@ -120,10 +121,12 @@ export default decorator<IStakeholder, IStakeholder & FormComponentProps>(Form.c
120
121
  <Form.Item label='名称' colon={false}>
121
122
  {getFieldDecorator('buyerName', {
122
123
  rules: getRules('buyerName', isVatNormal ?
123
- RULES.companyNameByNormal('购买方名称') :
124
- RULES.companyNameBySpecial('购买方名称')),
124
+ RULES.companyNameByNormal('购买方名称') :
125
+ RULES.companyNameBySpecial('购买方名称')),
125
126
  })(
126
- <MyInput
127
+ <BuyerNameInput
128
+ myform={form}
129
+ fieldName='buyerName'
127
130
  readOnly={isReadOnly('buyerName')}
128
131
  placeholder="请输入"
129
132
  autoComplete="off"
@@ -145,11 +148,19 @@ export default decorator<IStakeholder, IStakeholder & FormComponentProps>(Form.c
145
148
  <Form.Item label='统一社会信用代码/纳税人识别号' colon={false}>
146
149
  {getFieldDecorator('buyerTaxId', {
147
150
  rules: getRules('buyerTaxId', [{ required: !isVatNormal, message: '购买方纳税人识别号必填' }, ...RULES.taxId('购买方纳税人识别号')])
148
- })(<MyInput readOnly={isReadOnly('buyerTaxId')} placeholder="请输入" autoComplete="off" />)}
151
+ })(
152
+ <BuyerNameInput
153
+ myform={form}
154
+ fieldName='buyerTaxId'
155
+ readOnly={isReadOnly('buyerTaxId')}
156
+ placeholder="请输入"
157
+ autoComplete="off"
158
+ />
159
+ )}
149
160
  </Form.Item>
150
161
  </Col>
151
162
  {
152
- !readOnly && isExpand && (
163
+ isExpand && (
153
164
  <>
154
165
  <Col span={15} >
155
166
  <Form.Item label='购买方地址' colon={false}>
@@ -227,7 +238,7 @@ export default decorator<IStakeholder, IStakeholder & FormComponentProps>(Form.c
227
238
  </Form.Item>
228
239
  </Col>
229
240
  {
230
- !readOnly && isExpand && (
241
+ isExpand && (
231
242
  <>
232
243
  <Col span={15} >
233
244
  <Form.Item label='销售方地址' colon={false}>
@@ -270,6 +281,58 @@ export default decorator<IStakeholder, IStakeholder & FormComponentProps>(Form.c
270
281
  )
271
282
  })
272
283
 
284
+
285
+ function BuyerNameInput(props: InputProps & { fieldName: string; myform: WrappedFormUtils<any> }) {
286
+
287
+ const { fieldName, myform: form } = props;
288
+
289
+ const controller = Invoice.useInvoiceController();
290
+
291
+ const autoComplete = controller.useMemo(s => s.autoComplete, [])
292
+
293
+ const [options, setOptions] = React.useState<any[]>([])
294
+
295
+ const onChangeAutoComplete = React.useCallback(value => {
296
+ const record = options.filter(e => e[fieldName] === value)[0] as any;
297
+ if (!record || !form) return;
298
+
299
+ form.setFieldsValue(record);
300
+ setOptions([])
301
+ }, [options, fieldName, form])
302
+
303
+ const onSearch = React.useCallback(async (searchText: string) => {
304
+ await Discontinue.start();
305
+ try {
306
+ if (fieldName === 'buyerName') {
307
+ if (autoComplete.onBuyerNameSearch) {
308
+ setOptions(await autoComplete.onBuyerNameSearch(searchText));
309
+ }
310
+ } else if (fieldName === 'buyerTaxId') {
311
+ if (autoComplete.onBuyerTaxIdSearch) {
312
+ setOptions(await autoComplete.onBuyerTaxIdSearch(searchText));
313
+ }
314
+ }
315
+
316
+ } catch (error) {
317
+ setOptions([]);
318
+ throw error;
319
+ }
320
+ }, [autoComplete.onBuyerNameSearch, fieldName])
321
+
322
+ if (props.readOnly) return <span>{props.value}</span>;
323
+
324
+ return (
325
+ <AutoComplete
326
+ onSearch={onSearch}
327
+ options={options.map(e => ({ value: e[fieldName] }))}
328
+ onChange={onChangeAutoComplete}
329
+ value={props.value}
330
+ >
331
+ <Input {...props} style={{ width: '100%', ...props.style }} />
332
+ </AutoComplete>
333
+ )
334
+ }
335
+
273
336
  class MyInput extends React.Component<InputProps>{
274
337
  render() {
275
338
  const props = this.props;
@@ -280,3 +343,14 @@ class MyInput extends React.Component<InputProps>{
280
343
  }
281
344
  }
282
345
  }
346
+
347
+
348
+ class Discontinue {
349
+
350
+ private static timer: any;
351
+
352
+ static start = (interval = 200) => new Promise<void>(resolve => {
353
+ clearTimeout(Discontinue.timer);
354
+ Discontinue.timer = setTimeout(resolve, interval);
355
+ })
356
+ }