hotfix/2.9.9.2312.02-个税

个税申报表添加新增编辑功能
This commit is contained in:
黎永顺 2023-12-28 09:46:25 +08:00
parent 707b27038c
commit 1be637e168
6 changed files with 373 additions and 30 deletions

View File

@ -213,8 +213,23 @@ export const taxPaymentVoucherPrintFeedback = (params) => {
export const taxdeclarationUpdateIcon = (params) => {
return postFetch("/api/bs/hrmsalary/taxdeclaration/updateIcon", params);
};
export const employeedeclareExport = params => {
return postExportFetch("/api/bs/hrmsalary/employeedeclare/export", params);
};
//个税申报表申报数据-获取表单
export const getTaxDecForm = (params) => {
return postFetch("/api/bs/hrmsalary/taxdeclaration/getAddForm", params);
};
//个税申报表申报数据-新增
export const taxdeclarationAdd = (params) => {
return postFetch("/api/bs/hrmsalary/taxdeclaration/add", params);
};
//个税申报表申报数据-编辑
export const taxdeclarationEdit = (params) => {
return postFetch("/api/bs/hrmsalary/taxdeclaration/edit", params);
};
//个税申报表申报数据-详情
export const getTaxdeclarationDetailInfo = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/taxdeclaration/detailInfo", "GET", params);
};

View File

@ -91,3 +91,48 @@ export const paymentBankConditions = [
defaultshow: true
}
];
export const incomeTaxDecConditions = [
{
items: [
{
conditionType: "SELECT",
domkey: ["employeeId"],
fieldcol: 16,
label: "姓名",
lanId: 25034,
labelcol: 8,
value: "",
rules: "required|string",
viewAttr: 3,
options: []
},
{
conditionType: "INPUT",
domkey: ["jobNum"],
fieldcol: 16,
label: "工号",
lanId: 1933,
labelcol: 8,
value: "",
viewAttr: 1
},
{
conditionType: "INPUT",
domkey: ["cardNum"],
fieldcol: 16,
label: "证件号码",
lanId: 1839,
labelcol: 8,
value: "",
viewAttr: 1
}
],
title: "baseInfo",
defaultshow: true
},
{
items: [],
title: "salaryItems",
defaultshow: true
}
];

View File

@ -0,0 +1,193 @@
/*
* Author: 黎永顺
* name: 个税申报人员-新增与编辑
* Description:
* Date: 2023/12/27
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { incomeTaxDecConditions } from "./constants";
import { WeaLocaleProvider, WeaSlideModal, WeaTools } from "ecCom";
import { Button, Col, message, Row } from "antd";
import { getConditionDomkeys, getSearchs, toDecimal_n } from "../../../util";
import * as API from "../../../apis/declare";
const getLabel = WeaLocaleProvider.getLabel;
const getKey = WeaTools.getKey;
const APIFOX = {
add: API.taxdeclarationAdd,
edit: API.taxdeclarationEdit
};
@inject("declareStore")
@observer
class IncomeTaxDeclarationPersonnelSlide extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [], employeeDeclares: [], taxReportColumns: [],
loading: false, detailInfo: {}
};
}
componentWillReceiveProps(nextProps, nextContext) {
const { declareStore: { initTaxDecForm } } = nextProps;
if (nextProps.visible !== this.props.visible && nextProps.visible) this.getTaxDecForm(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
this.setState({
conditions: [], employeeDeclares: [], taxReportColumns: [],
loading: false, detailInfo: {}
}, () => initTaxDecForm());
}
}
getTaxDecForm = (props) => {
const { taxDeclarationId, id } = props;
API.getTaxDecForm({ taxDeclarationId }).then(({ status, data }) => {
if (status) {
const { employeeDeclares, taxReportColumns } = data;
this.setState({
employeeDeclares, taxReportColumns,
conditions: _.map(incomeTaxDecConditions, item => {
if (item.title === "baseInfo") {
return {
...item, title: getLabel(1361, "基本信息"),
items: _.map(item.items, o => {
if (getKey(o) === "employeeId") {
if (!id) {
return {
...o, otherParams: { showSearch: true, optionFilterProp: "children" },
label: getLabel(o.lanId, o.label),
options: _.map(employeeDeclares, g => ({
key: g.employeeId.toString(),
showname: g.employeeName
}))
};
} else {
return {
conditionType: "INPUT",
domkey: ["username"],
fieldcol: 16,
label: getLabel(25034, "姓名"),
labelcol: 8,
value: "",
viewAttr: 1
};
}
}
return { ...o, label: getLabel(o.lanId, o.label) };
})
};
} else if (item.title === "salaryItems") {
return {
...item, title: getLabel(111, "薪资项"),
items: _.map(taxReportColumns, o => ({
conditionType: o.dataType === "number" ? "INPUTNUMBER" : "INPUT",
domkey: [o.reportColumnDataIndex],
fieldcol: 16,
label: o.reportColumnName,
labelcol: 8,
value: o.dataType === "number" ? 0 : "",
rules: o.dataType === "number" ? "required" : "",
otherParams: { precision: 2 },
viewAttr: o.dataType === "number" ? 3 : 2
}))
};
}
})
}, () => {
const { declareStore: { taxDecForm } } = props;
taxDecForm.initFormFields(this.state.conditions);
id && this.getTaxdeclarationDetailInfo(id);
});
}
});
};
getTaxdeclarationDetailInfo = (id) => {
API.getTaxdeclarationDetailInfo({ id }).then(({ status, data }) => {
if (status) {
const { conditions } = this.state;
const { declareStore: { taxDecForm } } = this.props;
const detailInfo = { ...data, ...data["resultValue"] };
this.setState({
detailInfo: detailInfo
}, () => {
_.forEach(getConditionDomkeys(conditions), o => {
taxDecForm.updateFields({
[o]: this.state.detailInfo[o] || ""
});
});
});
}
});
};
handleFormChange = (params) => {
const { declareStore: { taxDecForm } } = this.props;
const { employeeDeclares } = this.state;
const key = Object.keys(params)[0];
const value = params[key].value;
if (key === "employeeId") {
taxDecForm.updateFields({
jobNum: _.find(employeeDeclares, o => o.employeeId == value).jobNum,
cardNum: _.find(employeeDeclares, o => o.employeeId == value).cardNum
});
}
};
save = () => {
const { declareStore: { taxDecForm }, taxDeclarationId, id } = this.props;
const { employeeDeclares, detailInfo } = this.state;
const type = id ? "edit" : "add";
taxDecForm.validateForm().then(f => {
if (f.isValid) {
const { cardNum, jobNum, employeeId, ...taxReportColumnValues } = taxDecForm.getFormParams();
const payload = {
taxDeclarationId, employeeId: employeeId || detailInfo.employeeId,
employeeType: employeeId ? _.find(employeeDeclares, o => o.employeeId == employeeId).employeeType : detailInfo.employeeType,
taxReportColumnValues: _.reduce(_.keys(taxReportColumnValues), (pre, cur) => {
if (Object.prototype.toString.call(taxReportColumnValues[cur]) === "[object Number]") {
return { ...pre, [cur]: toDecimal_n(taxReportColumnValues[cur], 2) };
} else {
return { ...pre, [cur]: taxReportColumnValues[cur] };
}
}, {})
};
this.setState({ loading: true });
APIFOX[type](type === "add" ? payload : { ...payload, id }).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(30700, "操作成功!"));
this.props.onClose(true);
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
renderTitle = () => {
return <Row className="declareSchemeDialogTitle" type="flex">
<Col span={12} className="declareSchemeDialogTitle-left">
<div className="icon-circle-base"><i className="icon-coms-fa"/></div>
<span className="title">{this.props.title}</span>
</Col>
<Col span={12} className="declareSchemeDialogTitle-right">
<Button type="primary" loading={this.state.loading} onClick={this.save}>{getLabel(537558, "保存")}</Button>
</Col>
</Row>;
};
render() {
const { declareStore: { taxDecForm } } = this.props;
const { conditions } = this.state;
return (
<WeaSlideModal {...this.props} className="incomeTaxDecPerSlideWrapper" onClose={() => this.props.onClose()}
top={0} width={60} height={100} measure="%" direction="right" title={this.renderTitle()}
content={getSearchs(taxDecForm, conditions, 2, false, this.handleFormChange)}
/>
);
}
}
export default IncomeTaxDeclarationPersonnelSlide;

View File

@ -5,8 +5,8 @@
* Date: 2023/8/18
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTab, WeaTable } from "ecCom";
import { Button, message } from "antd";
import { WeaLocaleProvider, WeaTab } from "ecCom";
import { Button, message, Spin } from "antd";
import TaxDeclarationInfo from "./components/taxDeclarationInfo";
import { apiflowBillingConfigStatus } from "../../apis/intelligentCalculateSalarySettings";
import PaymentBtn from "./components/paymentBtn";
@ -26,6 +26,7 @@ import {
taxPaymentWithheldVoucherGet
} from "../../apis/declare";
import { convertToUrlString, getQueryString } from "../../util/url";
import IncomeTaxDeclarationPersonnelSlide from "./components/incomeTaxDeclarationPersonnelSlide";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
@ -49,6 +50,9 @@ class Index extends Component {
correct: false, cancel: false, cancelFeedback: false, refreshingPay: false,
issuance: false
},
taxDecPersonSlide: {
visible: false, title: getLabel(1421, "新增"), taxDeclarationId: "", id: ""
},
intelCalcSalaryStatus: false, //智能算薪 总开关是否开启
declareInfo: {}, pageInfo: { current: 0, pageSize: 10, total: 0 }
};
@ -56,7 +60,11 @@ class Index extends Component {
}
componentDidMount() {
const promise = this.init();
window.addEventListener("message", this.handleReceive, false);
}
componentWillUnmount() {
window.removeEventListener("message", this.handleReceive, false);
}
init = async () => {
@ -95,6 +103,32 @@ class Index extends Component {
taxdeclarationGetRate = (index) => {
return taxdeclarationGetRate({ index });
};
handleReceive = ({ data }) => {
const { type, payload: { id, params } = {} } = data;
if (type === "init") {
const promise = this.init();
} else if (type === "turn") {
if (id === "PAGEINFO") {
this.setState({ pageInfo: { ...this.state.pageInfo, ...params } }, () => this.getDetailList());
} else if (id === "EDIT") {
this.handleTaxDescPerSlide({
visible: true, id: params.id,
title: getLabel(501169, "编辑")
});
}
}
};
postMessageToChild = (payload = {}) => {
const { declareInfo, intelCalcSalaryStatus } = this.state;
const i18n = {
"总计": getLabel(523, "总计"), "编辑": getLabel(501169, "编辑"),
"操作": getLabel(30585, "操作"), "共": getLabel(83698, "共"),
"条": getLabel(18256, "条")
};
const declareStatus = intelCalcSalaryStatus ? declareInfo.declareStatus : "";
const childFrameObj = document.getElementById("atdTable");
childFrameObj && childFrameObj.contentWindow.postMessage(JSON.stringify({ ...payload, i18n, declareStatus }), "*");
};
getDetailList = () => {
const { loading, pageInfo, selectedKey } = this.state;
const [incomeCategory, taxDeclarationId] = selectedKey.split("%%");
@ -111,10 +145,16 @@ class Index extends Component {
dataSource, pageInfo: { ...pageInfo, current, pageSize, total },
columns: _.map(columns, (it, idx) => {
if (idx <= 1) {
return { ...it, width: 150, fixed: "left" };
return { ...it, width: 150, fixed: "left", ellipsis: true };
}
return { ...it, width: 150 };
return { ...it, width: 150, ellipsis: true };
})
}, () => {
const payload = {
dataSource, pageInfo: this.state.pageInfo,
columns: this.state.columns
};
this.postMessageToChild(payload);
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
@ -221,11 +261,18 @@ class Index extends Component {
};
window.open(`${window.ecologyContentPath || ""}/api/bs/hrmsalary/taxdeclaration/detail/export?${convertToUrlString(payload)}`, "_blank");
};
handleTaxDescPerSlide = (params) => {
const { callback, ...module } = params;
const { taxDecPersonSlide, selectedKey } = this.state;
const [__, taxDeclarationId] = selectedKey.split("%%");
this.setState({
taxDecPersonSlide: { ...taxDecPersonSlide, ...module, taxDeclarationId }
}, () => callback && this.getDetailList());
};
render() {
const {
tabs, selectedKey, columns, pageInfo,
dataSource, loading, declareInfo, intelCalcSalaryStatus
tabs, selectedKey, loading, declareInfo, intelCalcSalaryStatus, taxDecPersonSlide
} = this.state;
let btns = [
<Button type="primary" onClick={this.export}>{getLabel(17416, "导出")}</Button>,
@ -234,23 +281,6 @@ class Index extends Component {
<Button type="ghost" onClick={() => this.handleOperateDeclare("refresh")}
loading={loading.refresh}>{getLabel(111, "刷新数据")}</Button>
];
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(18609, "共")} ${total} ${getLabel(18256, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.getDetailList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.getDetailList());
}
};
//申报状态:作废中
declareInfo.declareStatus === "DECLARE_CANCELLING" && (btns.splice(1, 2, <Button
type="ghost" loading={loading.cancelFeedback}
@ -291,6 +321,16 @@ class Index extends Component {
btns.splice(1, 1);
}
}
if (intelCalcSalaryStatus) {
if (["NOT_DECLARE", "DECLARE_FAIL"].includes(declareInfo.declareStatus)) {
btns.unshift(
<Button type="primary" onClick={() => this.handleTaxDescPerSlide({
visible: true,
title: getLabel(1421, "新增")
})}>{getLabel(1421, "新增")}</Button>
);
}
}
if (intelCalcSalaryStatus && (declareInfo.declareStatus === "DECLARE_SUCCESS_UNPAID")) {
btns.push(
<PaymentBtn declareInfo={declareInfo} updateDeclare={this.declare}/>,
@ -309,13 +349,21 @@ class Index extends Component {
datas={tabs} keyParam="viewcondition" selectedKey={selectedKey}
buttons={btns} onChange={(v) => this.setState({ selectedKey: v }, () => this.getDetailList())}
/>
<WeaTable
loading={loading.query} bordered
columns={columns} dataSource={dataSource}
pagination={pagination}
scroll={{ x: 1200, y: `calc(100vh - 190px)` }}
<IncomeTaxDeclarationPersonnelSlide
{...taxDecPersonSlide}
onClose={(callback) => this.handleTaxDescPerSlide({ visible: false, id: "", callback })}
/>
</div>
<div className="declareDetail-layout-table-content">
<Spin spinning={loading.query}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/taxDeclareTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/taxDeclareTable"
id="atdTable"
/>
</Spin>
</div>
</div>
);
}

View File

@ -1,4 +1,8 @@
.declareDetail-layout {
height: 100%;
display: flex;
flex-direction: column;
.declareDetail-layout-content {
padding: 0 16px;
@ -12,6 +16,15 @@
}
}
.declareDetail-layout-table-content {
flex: 1;
padding: 0 16px;
.ant-spin-nested-loading, .ant-spin-container {
height: 100% !important;
}
}
.icon-span {
cursor: pointer;
@ -218,3 +231,29 @@
}
}
}
.incomeTaxDecPerSlideWrapper {
.wea-slide-modal-content {
background: #f6f6f6;
padding: 16px;
overflow: auto;
height: 100%;
}
.wea-search-group {
padding: 0;
background: #fff;
border: 1px solid #e5e5e5;
border-bottom: none;
margin-bottom: 16px;
.wea-form-cell, .wea-content {
padding: 0;
}
.wea-form-item {
padding: 5px 16px;
border-bottom: 1px solid #e5e5e5;
}
}
}

View File

@ -9,9 +9,12 @@ const { TableStore } = WeaTableNew;
export class DeclareStore {
@observable paymentForm = new WeaForm(); // declareDetail----在线申报-缴款Form
@observable declareForm = new WeaForm(); //薪资核算重构-核算form
@observable taxDecForm = new WeaForm(); //个税申报人员-新增编辑form
// ** 薪资核算重构-初始化核算form **
@action
initDeclareForm = () => this.declareForm = new WeaForm();
@action
initTaxDecForm = () => this.taxDecForm = new WeaForm();
@observable tableStore = new TableStore(); // new table