import React from 'react'; import Invoice from '../../..'; import { Button, Drawer, Select, Modal, Input as InputAntd, Form, Tree, message } from 'kts-components-antd-x3'; import { chain, bignumber } from 'mathjs'; import { Input, NumberPicker } from '@formily/antd-components'; import { format15 } from '../GoodsList/hook/useColumns/autoFillFn'; import { LineAttributeType } from '../../../InvoiceController'; import IGood from '../../../InvoiceController/InvoiceControllerState/GoodsListState/IGood'; import { countTaxAmount, countAmountExcludeTax, countPrice } from '../../../tools/calculate'; import { bytesLnegth, cutStr } from '../../../tools/strringFn'; import { SchemaForm, FormButtonGroup, createAsyncFormActions, SchemaMarkupField as Field, FormEffectHooks, } from '@formily/antd'; import './index.less'; import { TaxClassificationModal } from "../../../.."; const { TreeNode } = Tree; const { confirm } = Modal; export default () => { const controller = Invoice.useInvoiceController(); const visible = controller.useMemo(s => s.goodsListState.endowCode.endowcodeGoodIndex.length > 0, []); const [defaultValue, setDefaultValue] = React.useState(); const onClose = React.useCallback(() => { controller.pipeline(async (s) => { s.goodsListState.endowCode.endowcodeGoodIndex = []; })(); }, [controller]); // 计算赋码默认值 React.useEffect(() => { if (visible) { controller.pipeline(async s => { const endowcodeGoodIndex = s.goodsListState.endowCode.endowcodeGoodIndex.filter(i => { const good = s.goodsListState.goodsMap.get(i); if (!good) return false; return good.lineAttribute !== LineAttributeType.折扣行; }) const good = s.goodsListState.goodsMap.get(s.goodsListState.endowCode.endowcodeGoodIndex[0]); if (!good) return; const getDefaultValue = s.goodsListState.endowCode.getDefaultValue; if (getDefaultValue) { setDefaultValue(await getDefaultValue({ ...good }, endowcodeGoodIndex.length)); } else { if (endowcodeGoodIndex.length === 1) { if (controller.state.goodsListState.isUpdateGoodsTaxRateList && controller.getGoodsTaxRateList && good.taxClassificationCode) { const goodsTaxRateList = await controller.getGoodsTaxRateList(good.taxClassificationCode); good.goodsTaxRateList = goodsTaxRateList; // if (good.taxRate !== undefined && good.taxRate !== null && !goodsTaxRateList.includes(good.taxRate)) { // good.taxRate = undefined; // } } setDefaultValue(good); } else { setDefaultValue({ taxRate: good.taxRate } as any); } } })() } else { setDefaultValue(undefined); } }, [visible]) return ( {defaultValue && } ); }; const DrawerBody = (props: { defaultValue: IGood }) => { const controller = Invoice.useInvoiceController(); const { defaultValue } = props; const actions = React.useMemo(() => createAsyncFormActions(), []); const taxClassificationProps = controller.useMemo(s => s.taxClassificationProps, []); /** 免税类型 是否需要 */ const isTaxFreeTypeNeeded = controller.useMemo(s => s.goodsListState.endowCode.isTaxFreeTypeNeeded, []); /** 税率 是否禁用 */ const readOnlyTaxRate = controller.useMemo(s => { if (s.goodsListState.endowCode.getReadOnlyTaxRate) { return s.goodsListState.endowCode.getReadOnlyTaxRate(s.goodsListState); } else { return false; } }, []) /** 优惠政策 是否禁用 */ const readOnlyFavouredPolicy = controller.useMemo(s => { if (s.goodsListState.endowCode.getReadOnlyFavouredPolicy) { return s.goodsListState.endowCode.getReadOnlyFavouredPolicy(s.goodsListState); } else { return false; } }, []) /** 税率列表 */ const taxRateList = controller.useMemo(s => s.goodsListState.taxRateList, []); /** 免税类型 列表 */ const taxFreeTypeList = controller.useMemo(s => s.goodsListState.endowCode.taxFreeTypeList, []); /** 优惠政策类型列表 */ const favouredPolicyNameList = controller.useMemo(s => s.goodsListState.endowCode.favouredPolicyNameList, []); /** 优惠政策类型列表 */ // const getTaxCategoryCodeTree = controller.useMemo(s => s.goodsListState.endowCode.getTaxCategoryCodeTree, []); /** 税率 */ const [taxRate, setTaxRate] = React.useState(0); /** 商品可用税率 */ const [goodsTaxRateList, setGoodsTaxRateList] = React.useState(defaultValue.goodsTaxRateList); const formattedTaxRateList = React.useMemo(() => { return (goodsTaxRateList || taxRateList).map((e) => ({ label: `${e}%`, value: e })) }, [goodsTaxRateList, taxRateList]) /** 税收分类编码 选择组件 */ const ShowSearch = React.useCallback(props => { const [dataSource, setDataSource] = React.useState([]); const onSearch = React.useCallback(async e => { const arr = await controller.state.goodsListState.endowCode.getTaxCategoryCodeList(e); setDataSource(arr); }, []) const onChange = React.useCallback((value: string) => { if (props.onChange) { props.onChange(value); } const info = dataSource.filter(i => i.value === value)[0]; if (!info) return; // !readOnlyTaxRate && actions.setFieldState('taxRate', async s => { // if (info.taxRate || info.taxRate === 0) { // s.value = info.taxRate // } // }); actions.setFieldState('shorthand', async (s) => { if (info.shorthand) { s.value = info.shorthand } }); }, [actions, dataSource, readOnlyTaxRate]) return ( ) }, [controller, actions]) /** 税收分类编码 选择组件2 */ const ShowSearch2 = React.useCallback(props => { // 是否显示 const [visible, setVisible] = React.useState(false); // 税收分类编码树 const [list, setList] = React.useState(); // 搜索条件 const [filter, setFilter] = React.useState<{ /** 税收分类编码 */ taxCategoryCode?: string, /** 货物和劳务名称/简称 */ val?: string }>(); /** 创建 树节点 */ const createTreeNode = React.useCallback(() => { if (!list) return <>; return ctn(list); function title(label: string) { if (!filter) return label; label = (filter.taxCategoryCode ? label.split(new RegExp(filter.taxCategoryCode, 'g')) : [label]).join(`${filter.taxCategoryCode}`); label = (filter.val ? label.split(new RegExp(filter.val, 'g')) : [label]).join(`${filter.val}`); return } function ctn(l: any[], p = '0') { if (!l || !l.length) return [<>]; return l.filter(e => e.pid === p).map(e => { return ( {ctn(l, e.id)} ) }) } }, [list, filter]) /** 点击了节点 */ const onSelect = React.useCallback((e: string[]) => { const id = e[0]; // 是否叶子节点 if (list?.filter(e => e.pid === id).length !== 0) { return; } const info = list?.filter(e => e.id === id)[0]; // !readOnlyTaxRate && actions.setFieldState('taxRate', async s => { // if (info.taxRate || info.taxRate === 0) { // s.value = info.taxRate // } // }); actions.setFieldState('taxClassificationCode', async s => { if (info.id) { s.value = info.id } }); actions.setFieldState('shorthand', async (s) => { if (info.shorthand) { s.value = info.shorthand } }); setVisible(false); }, [list, actions, readOnlyTaxRate]) React.useEffect(() => { (async () => { const fn = controller.state.goodsListState.endowCode.getTaxCategoryCodeTree || (async () => []); const list = await fn(filter?.taxCategoryCode, filter?.val); setList(list || []); })() }, [filter]) React.useEffect(() => { if (visible) { setList([]) } }, [visible]) return ( <> { setVisible(true) }} >点击选择} /> { setVisible(false) }} >
{ setFilter({ ...filter, val: e.target.value }) }} /> { setFilter({ ...filter, taxCategoryCode: e.target.value }) }} />
{ (list && list.length > 0) ? {createTreeNode()} : 请输入“产品或服务简称”或“税收分类编码”查找数据。 }
) }, [controller, actions]) /** 税收分类编码 选择组件3 */ const ShowSearch3 = React.useCallback(props => { const [open, setOpen] = React.useState(false); const [list, setList] = React.useState([]); const onSearch = React.useCallback(async (value: any = null) => { if(value?.target?.value){ const arr = await controller.state.goodsListState.endowCode.onSearchTaxClassificationCode(value?.target?.value); const list: any[] = arr.map((item: any)=> { return { ...item, title: `${item.productName} ${item.taxCategoryCode}`, key: item.taxCategoryCode, isLeaf: true } }); setList(list); } else { await onLoad(); } }, []); const onLoad = React.useCallback(async (value?: any) => { const arr = await controller.state.goodsListState.endowCode.onLoadTaxClassificationCode(value?.taxCategoryCode); const data: any[] = arr.map((item: any)=> { return { ...item, title: `${item.productName} ${item.taxCategoryCode}`, key: item.taxCategoryCode } }); const treeData = optimizeTreeData(data); if(value?.key) { setList((origin: any)=> { updateTreeData(origin, value.key, treeData) }); } else { setList(treeData); } return []; }, []); const onClick = React.useCallback(async () => { setOpen(true); await onLoad(); }, []); const onSelect = React.useCallback((key: any, info: any) => { // 根据税编改变税率列表 // 如果只有一个,默认选中,有多个时,置空,用户手选 if (controller.state.goodsListState.isUpdateGoodsTaxRateList) { if (info.node.taxRateList?.length) { setGoodsTaxRateList(info.node.taxRateList); } if (!readOnlyTaxRate) { actions.setFieldState('taxRate', async s => { if (info.node.taxRateList && info.node.taxRateList?.length === 1) { s.value = info.node.taxRateList[0] } else { s.value = undefined } }); } } // !readOnlyTaxRate && actions.setFieldState('taxRate', async s => { // if (info.node.taxRate || info.taxRate === 0) { // s.value = info.node.taxRate // } // }); actions.setFieldState('taxClassificationCode', async s => { if(info.node.taxCategoryCode) { s.value = info.node.taxCategoryCode } }); actions.setFieldState('shorthand', async (s) => { if (info.node.shorthand){ s.value = info.node.shorthand } }); setOpen(false); }, [controller, actions]); const optimizeTreeData = (data: any): any => { return data.map((item: any)=> { return { ...item, selectable: item?.hzx === 'N', isLeaf: item?.hzx === 'N' } }); } const updateTreeData = (list: any, key: React.Key, children: any): any => { const data = list.map((node: any) => { if (node.key === key) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, key, children) }; } return node; }); setList(data); return data; } return ( <> {setOpen(false)}} onSearch={onSearch} onLoad={onLoad} /> ) }, [controller, actions]) // 是否享受优惠政策 const [favouredPolicyMark, setFavouredPolicyMark] = React.useState(0); // 优惠政策类型名称 const [favouredPolicyName, setFavouredPolicyName] = React.useState(defaultValue?.favouredPolicyName); // 是否为免税或不征税(需要隐藏税率和免税类型) // const isZeroTaxRate = favouredPolicyMark === 1 && (favouredPolicyName === '免税' || favouredPolicyName === '不征税'); // 保存原始税率的 ref(用于从免税/不征税切换回其他类型时恢复) const originalTaxRateRef = React.useRef(defaultValue?.taxRate); // 确定 const onSubmit = React.useCallback(values => { controller.pipeline(async s => { const endowCodeGood = s.goodsListState.endowCode.endowcodeGoodIndex.map(e => s.goodsListState.goodsMap.get(e)); // 判断是否选择了免税或不征税 const isZeroTax = values.favouredPolicyMark === 1 && (values.favouredPolicyName === '免税' || values.favouredPolicyName === '不征税'); // 确定最终的税率值 const finalTaxRate = isZeroTax ? 0 : (values.taxRate ?? 0); // 赋码 endowCodeGood.forEach(good => { if (!good) return; good.shorthand = values.shorthand; good.taxClassificationCode = values.taxClassificationCode; good.taxRate = finalTaxRate; good.taxFreeType = values.taxFreeType; good.favouredPolicyMark = values.favouredPolicyMark; good.favouredPolicyName = values.favouredPolicyName; // 无论是否含税,都保持价税合计不变 good.taxAmount = countTaxAmount(good.lineAmountIncludeTax || 0, s.goodsListState.deduction, finalTaxRate); if (good.taxAmount || good.taxAmount === 0 ) { good.lineAmountExcludeTax = countAmountExcludeTax(good.lineAmountIncludeTax || 0, good.taxAmount); } if (good.lineAmountExcludeTax && good.quantity) { good.priceExcludeTax = countPrice(good.lineAmountExcludeTax, good.quantity, controller.state.calculatingDigits) as any; } //赋值商品的可用税率 good.goodsTaxRateList = goodsTaxRateList; }); s.goodsListState.goodsList = s.goodsListState.goodsList.slice(); s.goodsListState.endowCode.endowcodeGoodIndex = []; })(); }, [controller, goodsTaxRateList]); const effects = React.useCallback(() => { // 税率变化 FormEffectHooks.onFieldValueChange$('taxRate').subscribe((e) => { setTaxRate(e.value); actions.setFieldState('taxFreeType', async (s) => { if (e.value !== 0) s.value = undefined; }); }); // 是否享受优惠政策 FormEffectHooks.onFieldValueChange$('favouredPolicyMark').subscribe((e) => { setFavouredPolicyMark(e.value); actions.setFieldState('favouredPolicyName', async (s) => { if (e.value === 0) { s.value = undefined; // 当从"是"切换到"否"时,恢复原始税率 // 如果原始税率不在可用税率列表中,则使用列表中的第一个税率 const availableRates = goodsTaxRateList || taxRateList; const originalRate = originalTaxRateRef.current; const validRate = availableRates?.includes(originalRate as number) ? originalRate : (availableRates?.[0] ?? 0); actions.setFieldState('taxRate', async (s) => { s.value = validRate; }); } }); }); // 优惠政策类型 FormEffectHooks.onFieldValueChange$('favouredPolicyName').subscribe((e) => { const newValue = e.value; setFavouredPolicyName(newValue); // 当选择免税或不征税时,强制设置税率为0% if (newValue === '免税' || newValue === '不征税') { // 保存当前税率,以便切换回其他类型时恢复 actions.getFieldState('taxRate', (state) => { originalTaxRateRef.current = state.value; }); actions.setFieldState('taxRate', async (s) => { s.value = 0; }); } else if (newValue) { // 当从免税/不征税切换到其他类型时,恢复原始税率 actions.setFieldState('taxRate', async (s) => { s.value = originalTaxRateRef.current ?? 0; }); } }); }, [actions]); // 更新 税收分类编码列表 React.useEffect(() => { if (controller.getTaxCategoryCodeList) controller.getTaxCategoryCodeList(); }, [controller]); return ( {taxRate === 0 && isTaxFreeTypeNeeded && } {favouredPolicyMark === 1 && } ); }; const components = { string: Input, number: NumberPicker, };