package com.yifu.cloud.plus.v1.yifu.salary.util;

import com.alibaba.fastjson.JSONObject;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ValidityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.ExcelException;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.insurances.util.ValidityUtil;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TConfigSalary;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TSalaryConfigStandard;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TSalaryEmployee;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryAccountService;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryEmployeeService;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryAccountItemVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryAccountVo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static com.yifu.cloud.plus.v1.yifu.salary.util.SalaryCommonUtil.setFields;

/**
 * @author hgw
 * @Description: EXCEL内容转化为TSalaryAccount
 */
@Data
@Slf4j
public class SalaryAccountUtil implements Serializable {

	/**
	 * 用于返回实体
	 */
	private List<TSalaryAccountVo> entityList;
	/**
	 * 用于返回错误信息
	 */
	private List<ErrorMessage> errorInfo;

	// 重复数据
	private List<ErrorMessage> repeatInfo;

	/**
	 * @param jsonStr         客户原表json内容
	 * @param dicMap          字典Map
	 * @param dept            项目
	 * @param configSalary    当前项目下的配置（结算月等
	 * @param salaryConfigMap 客户原表-工资模板配置Map
	 * @param empIdCardMap    当前项目下的员工Map
	 * @param empNameMap      当前项目下的员工Map
	 * @param isDuplicateName false：有重名（当前项目下的员工），则不可用姓名查找，必须含有身份证号列
	 * @param repeatFlag      默认 0：不允许重复导入已存在系统内的数据；1：允许重复导入
	 * @param ownEmployeeMap  自有员工所在项目Map
	 * @Description: 将jsonStr数据源的数据导入到 List<TSalaryAccount>
	 * @Author: hgw
	 * @Date: 2019/9/16 17:26
	 * @return: void
	 **/
	public void getJsonStringToList(YifuUser user, String jsonStr, TSettleDomainSelectVo dept
			, TConfigSalary configSalary, Map<String, TSalaryConfigStandard> salaryConfigMap, Map<String, Boolean> isMustMap
			, Map<String, TSalaryEmployee> empIdCardMap, Map<String, TSalaryEmployee> empNameMap, boolean isDuplicateName
			, String salaryType, String invoiceTitle, TSalaryEmployeeService tSalaryEmployeeService
			, Map<String, Integer> checkMap, int repeatFlag, Map<String, Integer> ownEmployeeMap
			, Map<String, Integer> ownDeptMap, TSalaryAccountService tSalaryAccountService) {
		List<TSalaryAccountVo> tList = new ArrayList<>();
		List<HashMap> list = JSONObject.parseArray(jsonStr, HashMap.class);
		List<ErrorMessage> errorList = new ArrayList<>();
		List<ErrorMessage> repeatList = new ArrayList<>();
		try {
			// 得到数据的条数
			int rows = list.size();
			// 有数据时才处理
			if (rows > 0) {
				// 得到类的所有field
				Field[] allFields = TSalaryAccountVo.class.getDeclaredFields();
				// 从map中得到对应列的field
				Field field;
				// 将有注解的field存放到fieldsMap中
				Map<String, Field> fieldsMap = new HashMap<>();
				for (int i = 0; i < allFields.length; i++) {
					field = allFields[i];
					if (field.isAnnotationPresent(ExcelAttribute.class)) {
						// 设置类的私有字段属性可访问
						field.setAccessible(true);
						fieldsMap.put(field.getName(), field);
					}
				}
				String error;  //校验字段是否符合要求 返回错误信息
				String tempStr;  //临时存储单元格数据
				TSalaryAccountVo entity;  // 从第1行开始取数据
				HashMap temp;  // 得到一行中的所有单元格对象.
				ExcelAttribute attr;  //获取属性对应的注解属性
				Object cellValueObj;  //单元格值
				String cellValueStr;  //单元格字符串值
				String dbFiedName;  //单元格值，对应的数据库中文名
				Class<?> fieldType;  // 取得类型,并根据对象类型设置值.
				TSalaryConfigStandard scs;
				TSalaryEmployee emp;
				TSalaryEmployee newEmp;  //新员工
				List<TSalaryAccountItemVo> saiList;
				TSalaryAccountItemVo sai;
				BigDecimal cellValueBig;
				Map<String, Integer> checkIdNumberMap = new HashMap<>();  //验证身份证重复性的Map
				boolean salaryGiveTimeFlag;  //salaryGiveTime == true :立即发；false：暂停发：则不考虑开户行等
				boolean isNewEmployee;  //是否新员工：是：true；否：false;
				R<TSalaryEmployee> empR;
				String empName;
				String salaryStyle;//工资发放方式（0现金/1银行）/2线下
				BigDecimal relaySalary;  //应发工资
				BigDecimal actualSalarySum;  //实发工资
				// 当前年月
				String nowMonth = DateUtil.addMonth(CommonConstants.ZERO_INT);
				String must;
				// 当前年（用来获取已有薪资的计税月份，覆盖填写的计税月份2022-1-19 17:11:24hgw根据郭华照等人提出的需求
				int nowYear = Integer.parseInt(nowMonth.substring(0, 4));
				// 当前结算年，已有工资的最小计税月
				String minTaxMonth;
				for (int i = 0; i < rows; i++) {
					error = "";
					temp = list.get(i);
					entity = new TSalaryAccountVo();
					emp = null;
					newEmp = new TSalaryEmployee();
					salaryGiveTimeFlag = true;
					empName = null;
					isNewEmployee = false;
					saiList = new ArrayList<>();
					salaryStyle = SalaryConstants.SALARY_STYLE_BANK;
					relaySalary = null;
					actualSalarySum = null;
					for (Map.Entry<String, TSalaryConfigStandard> entry : salaryConfigMap.entrySet()) {
						cellValueObj = getFieldValueByName(entry.getKey(), temp);
						scs = entry.getValue();
						if (cellValueObj != null && scs != null) {
							cellValueStr = getStringValByObject(cellValueObj);
							if (!StringUtils.isNotBlank(cellValueStr)) {
								error = "第" + (i + 2) + "行：" + entry.getKey() + "列_不识别对象类型";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							}
							dbFiedName = scs.getDbFiedName();
							if (isMustMap.get(dbFiedName) != null && Boolean.TRUE.equals(isMustMap.get(dbFiedName))) {
								isMustMap.put(dbFiedName, false);
							}
							if (SalaryConstants.RELAY_SALARY_JAVA.equals(scs.getJavaFiedName())) {
								try {
									relaySalary = new BigDecimal(cellValueStr);
								} catch (Exception e) {
									error = "第" + (i + 2) + "行：应发工资：'" + cellValueStr + "'错误，请检查数据";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
							}
							if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(scs.getJavaFiedName())) {
								try {
									actualSalarySum = new BigDecimal(cellValueStr);
								} catch (Exception e) {
									error = "第" + (i + 2) + "行：实发工资：'" + cellValueStr + "'错误，请检查数据";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
							}
							if (SalaryConstants.PDEDUCTION_JAVA.equals(scs.getJavaFiedName())
									|| SalaryConstants.UDEDUCTION_JAVA.equals(scs.getJavaFiedName())) {
								try {
									new BigDecimal(cellValueStr);
								} catch (Exception ex) {
									error = "第" + (i + 2) + "行：个人、单位代扣，只能是金额！";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
							}
							if (SalaryConstants.EMP_NAME.equals(dbFiedName)) {
								empName = cellValueStr = cellValueStr.replaceAll(" ", "");
								if (isDuplicateName) {
									emp = empNameMap.get(empName);
								}
								newEmp.setEmpName(empName);
							}
							if (SalaryConstants.IF_NEW_EMPLOYEE.equals(dbFiedName)
									&& SalaryConstants.IS_NEW.equals(cellValueStr)) {
								isNewEmployee = true;
							}
							if (SalaryConstants.ID_NUMBER.equals(dbFiedName)) {
								if (checkIdNumberMap.get(cellValueStr) == null) {
									checkIdNumberMap.put(cellValueStr, (i + 2));
								} else {
									error = "第" + (i + 2) + "行与第：" + checkIdNumberMap.get(cellValueStr) + "行身份证重复:" + cellValueStr;
									errorList.add(new ErrorMessage((i + 2), error));
									break;
								}
								if (cellValueStr.indexOf("x") >= 0) {
									cellValueStr = cellValueStr.toUpperCase();
								}
								emp = empIdCardMap.get(cellValueStr);
								newEmp.setEmpIdcard(cellValueStr);
							}
							if (SalaryConstants.SALARY_GIVE_TIME.equals(cellValueStr)) {
								salaryGiveTimeFlag = false;
								entity.setSalaryGiveTime(CommonConstants.ONE_STRING);
							}
							field = fieldsMap.get(scs.getJavaFiedName());
							if (field == null) {
								try {
									cellValueBig = new BigDecimal(cellValueStr);
									cellValueBig = cellValueBig.setScale(2, BigDecimal.ROUND_HALF_UP); //四舍五入
									if (cellValueBig.toString().length() > 11) {
										error = "第" + (i + 2) + "行金额太大了，请检查一下:" + cellValueBig;
										errorList.add(new ErrorMessage((i + 2), error));
										break;
									}
									sai = new TSalaryAccountItemVo();
									sai.setCnName(dbFiedName);
									sai.setJavaFiedName(scs.getJavaFiedName());
									sai.setSalaryMoney(cellValueBig);
									if (scs.getIsTax() != null) {
										sai.setIsTax(scs.getIsTax());
									} else {
										sai.setIsTax(CommonConstants.ZERO_INT);
									}
									saiList.add(sai);
								} catch (NumberFormatException e) {
									//非数字，不保存
								}
							} else {
								attr = field.getAnnotation(ExcelAttribute.class);
								error = validateUtil(cellValueStr, attr, (i + 2));
								if (null != error) {
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
								fieldType = field.getType();
								if (fieldType == null) {
									continue;
								}
								setFields(field, cellValueStr, attr, fieldType, entity);
							}
						}
					}
					must = null;
					for (Map.Entry<String, Boolean> entry : isMustMap.entrySet()) {
						if (Boolean.TRUE.equals(entry.getValue())) {
							if (Common.isEmpty(must)) {
								must = entry.getKey();
							} else {
								must = must.concat("、").concat(entry.getKey());
							}
						}
					}
					if (Common.isNotNull(must)) {
						error = "第" + (i + 2) + "行：" + must + "列_不可缺少";
						errorList.add(new ErrorMessage((i + 2), error));
						continue;
					}

					if ("3".equals(salaryType) && actualSalarySum == null) {
						error = "第" + (i + 2) + "行：【实发劳务费】列_不可缺少";
						errorList.add(new ErrorMessage((i + 2), error));
						continue;
					}

					// 应发、实发、实发劳务费不可都为空
					if (relaySalary == null && actualSalarySum == null) {
						error = "第" + (i + 2) + "行：【应发工资】列_不可缺少";
						errorList.add(new ErrorMessage((i + 2), error));
						continue;
					}

					// 版本2.6.6判重：对同一“项目”、同一“结算月份”、同一“报表类型”、同一“工资月份”、同一“身份证号”、同一“应发金额”进行校验
					// 2.6.6:校验导入数据重复的Map格式：#身份证号_工资月份_报表类型_应发金额
					entity.setIsRepeat(CommonConstants.ZERO_INT);
					if (relaySalary != null) {
						relaySalary = relaySalary.setScale(2, BigDecimal.ROUND_HALF_UP);
						if (checkMap.get(entity.getEmpIdcard() + CommonConstants.DOWN_LINE_STRING + DateUtil.addMonth(configSalary.getSalaryMonth())
								+ CommonConstants.DOWN_LINE_STRING + salaryType + CommonConstants.DOWN_LINE_STRING + relaySalary) != null) {
							entity.setIsRepeat(CommonConstants.ONE_INT);
							if (repeatFlag == 0) {
								repeatList.add(new ErrorMessage((i + 2), "第" + (i + 2) + "行：同一项目、结算月份、报表类型、工资月份、身份证号、应发金额，存在相同数据"));
								continue;
							}
						}
					}
					if (null == error) {
						if (Common.isNotNull(entity.getSalaryTaxFlag()) && entity.getSalaryTaxFlag().length() > 1) {
							error = "第" + (i + 2) + "行：请检查‘薪资扣税（默认是）’列，允许值：（否/是/不填写），您的值：" + entity.getSalaryTaxFlag();
							errorList.add(new ErrorMessage((i + 2), error));
							continue;
						}
						if (Common.isNotNull(entity.getSalaryStyle())) {
							salaryStyle = entity.getSalaryStyle();
						} else if (configSalary.getGrantType() != null) {
							salaryStyle = String.valueOf(configSalary.getGrantType());
						}
						// 2021-8-31 hgw2.6.5新增手机号校验
						if (newEmp != null && Common.isNotNull(entity.getEmpPhone()) && Common.isEmpty(newEmp.getEmpPhone())) {
							newEmp.setEmpPhone(entity.getEmpPhone());
						}
						if (emp == null) {
							if (isNewEmployee) {
								//增加工资人员档案：（临时使用）
								if (newEmp != null) {
									if (Common.isEmpty(newEmp.getEmpName())) {
										error = "第" + (i + 2) + "行：新员工-姓名-不可为空！";
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}
									if (Common.isEmpty(newEmp.getEmpIdcard())) {
										error = "第" + (i + 2) + "行：新员工-身份证号-不可为空！";
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}

									// 2021-8-31 hgw2.6.5新增手机号校验
									if (Common.isEmpty(newEmp.getEmpPhone())) {
										error = "第" + (i + 2) + "行：新员工-手机号码-不可为空！";
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									} else if (!ValidityUtil.validateEmpPhone(newEmp.getEmpPhone())) {
										error = "第" + (i + 2) + "行：新员工-手机号码格式错误：" + newEmp.getEmpPhone();
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}
								}
								if (entity != null) {
									if (!"3".equals(salaryType)) {
										if (Common.isEmpty(entity.getTaxMonth())) {
											error = "第" + (i + 2) + "行：新员工-计税月份-不可为空！";
											errorList.add(new ErrorMessage((i + 2), error));
											continue;
										} else if (entity.getTaxMonth().length() < CommonConstants.dingleDigitIntArray[6]) {
											error = "第" + (i + 2) + "行：新员工-计税月份-长度小于6：" + entity.getTaxMonth();
											errorList.add(new ErrorMessage((i + 2), error));
											continue;
										} else if (DateUtil.compareYearMonth(entity.getTaxMonth(), nowMonth)) {
											error = "第" + (i + 2) + "行：新员工-计税月份-大于当前年月或错误，请调整：" + entity.getTaxMonth();
											errorList.add(new ErrorMessage((i + 2), error));
											continue;
										} else {
											newEmp.setTaxMonth(entity.getTaxMonth());
										}
									}
									//工资发放方式（0现金/1银行）/2线下 && salaryGiveTime == true :立即发；false：暂停发：则不考虑开户行等
									//银行+立即发，则考虑和开户行卡号
									if (SalaryConstants.SALARY_STYLE_BANK.equals(salaryStyle) && salaryGiveTimeFlag) {
										if (Common.isEmpty(entity.getBankName())) {
											error = "第" + (i + 2) + "行：新员工-开户行-不可为空！";
											errorList.add(new ErrorMessage((i + 2), error));
											continue;
										} else {
											newEmp.setBankName(entity.getBankName());
										}
										if (Common.isEmpty(entity.getBankNo())) {
											error = "第" + (i + 2) + "行：新员工-卡号-不可为空！";
											errorList.add(new ErrorMessage((i + 2), error));
											continue;
										} else {
											newEmp.setBankNo(entity.getBankNo());
										}
									} else {
										if (Common.isNotNull(entity.getBankName())) {
											newEmp.setBankName(entity.getBankName());
										}
										if (Common.isNotNull(entity.getBankNo())) {
											newEmp.setBankNo(entity.getBankNo());
										}
									}
								}
								newEmp.setFileStatus(CommonConstants.ZERO_INT);  //临时
								newEmp.setDeptId(dept.getId());
								newEmp.setDeptName(dept.getDepartName());
								newEmp.setDeptNo(dept.getDepartNo());
								newEmp.setUnitId(dept.getCustomerId());
								newEmp.setUnitName(dept.getCustomerName());
								newEmp.setUnitNo(dept.getCustomerCode());
								newEmp.setCreateBy(String.valueOf(user.getId()));
								newEmp.setCreateName(user.getNickname());
								if (!"3".equals(salaryType)) {
									minTaxMonth = tSalaryAccountService.getMinTaxMonthByNowYear(newEmp.getEmpIdcard(), nowYear);
									if (Common.isNotNull(minTaxMonth)
											&& !minTaxMonth.equals(entity.getTaxMonth())) {
										error = "第" + (i + 2) + "行：该员工已有发薪记录，计税月份请填写：【" + minTaxMonth + "】" + "，你填写了计税月：【" + entity.getTaxMonth() + "】";
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}
								}
								tSalaryEmployeeService.save(newEmp);
								emp = newEmp;
							} else {
								error = "第" + (i + 2) + "行：该项目下无此员工，请添加<是否新员工（默认否）>列，并录入身份证号、开户行总行、卡号、计税月份、手机号码！！";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							}
						}
						if (emp != null) {
							if (Common.isEmpty(emp.getEmpName())) {
								error = "第" + (i + 2) + "行：档案员工-姓名-为空，请去档案更新！";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							} else if (Common.isEmpty(empName)) {
								error = "第" + (i + 2) + "行：模板-员工姓名-为空，请添加姓名列！";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							} else if (!empName.equals(emp.getEmpName())) {
								error = "第" + (i + 2) + "行：员工-姓名与身份证-不匹配，请确认员工信息！";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							}
							if (Common.isEmpty(emp.getEmpPhone())) {
								error = "第" + (i + 2) + "行：档案员工-手机号码-为空，请去档案更新！";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							} else if (!ValidityUtil.validateEmpPhone(emp.getEmpPhone())) {
								error = "第" + (i + 2) + "行：档案员工-手机号码格式错误，请去档案更新:" + emp.getEmpPhone();
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							}
							if (Common.isEmpty(emp.getTaxMonth()) && !"3".equals(salaryType)) {
								if (Common.isNotNull(entity.getTaxMonth())) {
									if (entity.getTaxMonth().length() > CommonConstants.dingleDigitIntArray[6]) {
										entity.setTaxMonth(emp.getTaxMonth().substring(0, 6));
									} else if (entity.getTaxMonth().length() < CommonConstants.dingleDigitIntArray[6]) {
										error = "第" + (i + 2) + "行：工资模板里-计税月份-长度小于6：" + entity.getTaxMonth() + "，请在工资模板修改！";
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}
									if (DateUtil.compareYearMonth(entity.getTaxMonth(), nowMonth)) {
										error = "第" + (i + 2) + "行：工资模板里-计税月份-大于当前年月或错误，请调整：" + entity.getTaxMonth();
										errorList.add(new ErrorMessage((i + 2), error));
										continue;
									}
									emp.setTaxMonth(entity.getTaxMonth());
									tSalaryEmployeeService.updateById(emp);
								} else {
									error = "第" + (i + 2) + "行：档案员工-计税月份-为空，请在工资模板填写-计税月份-列的内容！";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
							}
							if (ownEmployeeMap.get(emp.getEmpIdcard()) != null
									|| (isNewEmployee && ownDeptMap.get(dept.getId()) != null)) {
								// 自有员工
								entity.setOwnFlag(CommonConstants.ONE_INT);
							} else {
								// 普通员工
								entity.setOwnFlag(CommonConstants.ZERO_INT);
							}
							entity.setProvince(dept.getProvince());
							entity.setCity(dept.getCity());
							entity.setTown(dept.getTown());

							entity.setEmpId(emp.getId());
							entity.setEmpIdcard(emp.getEmpIdcard());
							entity.setEmpName(emp.getEmpName());
							entity.setEmpPhone(emp.getEmpPhone());
							if (SalaryConstants.SALARY_STYLE_BANK.equals(salaryStyle) && salaryGiveTimeFlag) {
								if (Common.isEmpty(emp.getBankName())) {
									error = "第" + (i + 2) + "行：员工：" + emp.getEmpIdcard() + "-发放方式为银行发放，但是-开户行-为空，请去档案更新！";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
								if (Common.isEmpty(emp.getBankNo())) {
									error = "第" + (i + 2) + "行：员工：" + emp.getEmpIdcard() + "-发放方式为银行发放，但是-银行卡号-为空，请去档案更新！";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
								entity.setBankName(emp.getBankName());
								entity.setBankNo(emp.getBankNo());
							} else {
								if (Common.isNotNull(emp.getBankName())) {
									entity.setBankName(emp.getBankName());
								} else {
									entity.setBankName(null);
								}
								if (Common.isNotNull(emp.getBankNo())) {
									entity.setBankNo(emp.getBankNo());
								} else {
									entity.setBankNo(null);
								}
							}
							if (!"3".equals(salaryType)) {
								if (emp.getTaxMonth().length() > CommonConstants.dingleDigitIntArray[6]) {
									entity.setTaxMonth(emp.getTaxMonth().substring(0, 6));
								} else if (emp.getTaxMonth().length() < CommonConstants.dingleDigitIntArray[6]) {
									error = "第" + (i + 2) + "行：档案员工-计税月份-长度小于6：" + entity.getTaxMonth() + "，请去档案更新！在工资模板修改无效！";
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								} else {
									entity.setTaxMonth(emp.getTaxMonth());
								}
								if (DateUtil.compareYearMonth(entity.getTaxMonth(), nowMonth)) {
									error = "第" + (i + 2) + "行：档案员工-计税月份-大于当前年月或错误，请调整：" + entity.getTaxMonth();
									errorList.add(new ErrorMessage((i + 2), error));
									continue;
								}
								sai = new TSalaryAccountItemVo();
								sai.setCnName(SalaryConstants.COST_REDUCTION);
								sai.setJavaFiedName(SalaryConstants.COST_REDUCTION_JAVA);
								sai.setSalaryMoney(DateUtil.getTaxMonthMoney(entity.getTaxMonth()));
								sai.setIsTax(CommonConstants.ZERO_INT);
								saiList.add(sai);
							}
						} else {
							error = "第" + (i + 2) + "行：该项目下无此员工，请去档案添加，或添加<是否新员工（默认否）>列，并录入身份证、开户行、卡号、计税月份、手机号码！";
							errorList.add(new ErrorMessage((i + 2), error));
							continue;
						}
						if (saiList != null && !saiList.isEmpty()) {
							entity.setSaiList(saiList);
						}
						if (Common.isEmpty(entity.getSalaryStyle())) {
							entity.setSalaryStyle(salaryStyle);
						}
						SalaryCommonUtil.setConfigSalary(configSalary, entity);
						// 填充基本数据
						SalaryCommonUtil.setAccountBaseInfo(salaryType, dept, entity, salaryGiveTimeFlag);
						if ("3".equals(salaryType)) {
							if (CommonConstants.dingleDigitStrArray[1].equals(entity.getIsDeductSocial())
									|| CommonConstants.dingleDigitStrArray[1].equals(entity.getIsDeductFund())) {
								error = "第" + (i + 2) + "行：劳务费不可扣社保、公积金，请去除【是否扣除社保】列，或写【否】";
								errorList.add(new ErrorMessage((i + 2), error));
								continue;
							} else {
								entity.setIsDeductSocial("0");
								entity.setIsDeductFund("0");
							}
						}
						//验证扣社保以及扣公积金时的关联关系
						if (CommonConstants.dingleDigitStrArray[1].equals(entity.getIsDeductSocial()) && Common.isEmpty(entity.getDeduSocialMonth())) {
							error = "第" + (i + 2) + "行：扣社保无社保扣缴月份";
							errorList.add(new ErrorMessage((i + 2), error));
							continue;
						}
						if (CommonConstants.dingleDigitStrArray[1].equals(entity.getIsDeductFund()) && Common.isEmpty(entity.getDeduProvidentMonth())) {
							error = "第" + (i + 2) + "行：扣公积金无公积金扣缴月份";
							errorList.add(new ErrorMessage((i + 2), error));
							continue;
						}
						entity.setInvoiceTitle(invoiceTitle);
						// 2022-4-29 19:31:52 hgw五一前，运营中心先发公告，紧急更新：
						entity.setSalaryTaxFlag("1");
						if (entity != null) {
							tList.add(entity);
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("将jsonString数据源的数据导入到list异常!");
			throw new ExcelException("工资导入-将jsonString数据源的数据导入到list异常!", e);
		}
		this.setEntityList(tList);
		this.setErrorInfo(errorList);
		this.setRepeatInfo(repeatList);
	}

	/**
	 * 按类型统一返回String内容
	 *
	 * @param param
	 * @return
	 */
	private static String getStringValByObject(Object param) {
		if (null == param) {
			return null;
		} else if (param instanceof Integer) {
			return Integer.toString(((Integer) param).intValue());
		} else if (param instanceof String) {
			return (String) param;
		} else if (param instanceof Double) {
			return Double.toString(((Double) param).doubleValue());
		} else if (param instanceof Float) {
			return Float.toString(((Float) param).floatValue());
		} else if (param instanceof Long) {
			return Long.toString(((Long) param).longValue());
		} else if (param instanceof Boolean) {
			return Boolean.toString(((Boolean) param).booleanValue());
		} else if (param instanceof Date) {
			return DateUtil.dateToString((Date) param);
		} else if (param instanceof LocalDateTime) {
			return LocalDateTimeUtils.formatTime((LocalDateTime) param, DateUtil.DATETIME_PATTERN_SECOND);
		} else {
			return param.toString();
		}
	}

	/**
	 * 根据属性名获取属性值
	 *
	 * @param fieldName
	 * @param hashMap
	 * @return
	 */
	private static Object getFieldValueByName(String fieldName, HashMap hashMap) {
		try {
			return hashMap.get(fieldName);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @param fieldName 字段名
	 * @param o         对象
	 * @return 字段值
	 * @MethodName : getFieldValueByName
	 * @Description : 根据字段名获取字段值
	 */
	public static Object getFieldValueByName(String fieldName, Object o, String dateFormat) {

		Object value = null;
		Field field = null;
		if (o == null) {
			return "";
		}
		field = getFieldByName(fieldName, o.getClass());
		String type = getFieldType(fieldName, o.getClass());
		if (field != null) {
			field.setAccessible(true);
			try {
				if (null != type && type.equals("Date")) {
					Date date = (Date) field.get(o);
					return DateUtil.dateToString(date, dateFormat == null ? "yyyy-MM-dd" : dateFormat);
				} else {
					value = field.get(o);
				}
			} catch (IllegalAccessException e) {
				log.error("根据字段名获取字段值异常：", e);
				e.printStackTrace();
			}
		} else {
			log.info(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);
		}

		return value;
	}

	/**
	 * @param fieldName 字段名
	 * @param clazz     包含该字段的类
	 * @return 字段
	 * @MethodName : getFieldByName
	 * @Description : 根据字段名获取字段
	 */
	private static Field getFieldByName(String fieldName, Class<?> clazz) {
		// 拿到本类的所有字段
		Field[] selfFields = clazz.getDeclaredFields();

		// 如果本类中存在该字段，则返回
		for (Field field : selfFields) {
			if (field.getName().equals(fieldName)) {
				return field;
			}
		}
		// 否则，查看父类中是否存在此字段，如果有则返回
		Class<?> superClazz = clazz.getSuperclass();
		if (superClazz != null && superClazz != Object.class) {
			return getFieldByName(fieldName, superClazz);
		}

		// 如果本类和父类都没有，则返回空
		return null;
	}

	/**
	 * @param fieldName 字段名
	 * @param clazz     包含该字段的类
	 * @return 字段
	 * @MethodName : getFieldType
	 * @Description : 根据字段名获取字段类型
	 */
	private static String getFieldType(String fieldName, Class<?> clazz) {
		// 拿到本类的所有字段
		Field[] selfFields = clazz.getDeclaredFields();

		// 如果本类中存在该字段，则返回
		for (Field field : selfFields) {
			if (field.getName().equals(fieldName)) {
				//如果type是类类型，则前面包含"class "，后面跟类名
				String type = field.getGenericType().toString();
				if (type.equals("class java.lang.String")) {
					return "String";
				} else if (type.equals("class java.lang.Integer")) {
					return "Integer";
				} else if (type.equals("class java.lang.Short")) {
					return "Short";
				} else if (type.equals("class java.lang.Double")) {
					return "Double";
				} else if (type.equals("class java.lang.Boolean")) {
					return "Boolean";
				} else if (type.equals("class java.util.Date")) {
					return "Date";
				} else {
					return null;
				}
			}
		}
		// 否则，查看父类中是否存在此字段，如果有则返回
		Class<?> superClazz = clazz.getSuperclass();
		if (superClazz != null && superClazz != Object.class) {
			return getFieldType(fieldName, superClazz);
		}
		// 如果本类和父类都没有，则返回空
		return null;
	}

	/**
	 * 输出错误数据
	 *
	 * @param attr
	 * @param msg
	 * @param i
	 * @return
	 */
	private String errorInfo(ExcelAttribute attr, String msg, Integer i) {
		if (Common.isNotNull(msg)) {
			return "第" + i + "行：" + attr.name() + msg;
		} else if (Common.isNotNull(attr.errorInfo())) {
			return "第" + i + "行：" + attr.errorInfo();
		}
		return "";
	}

	/**
	 * 实现各种校验方式的错误返回新
	 *
	 * @param c
	 * @param attr
	 * @param i
	 * @return
	 */
	public String validateUtil(String c, ExcelAttribute attr, int i) {
		//非空校验
		if (attr.isNotEmpty() && Common.isEmpty(c)) {
			return errorInfo(attr, "_字段不可为空", i);
		}
		if (Common.isNotNull(c)) {
			//日期格式校验
			if (attr.isDate()) {
				DateUtil.stringToDate(c.trim(), attr.dateFormat());
			}
			//手机号码校验
			if (attr.isPhone() && getMatchRes(c, attr, ValidityConstants.MOBILE_PATTERN)) {
				return errorInfo(attr, "_手机号码有误", i);
			}
			//身份证校验
			if (attr.isIdCard() && getMatchRes(c, attr, ValidityConstants.IDCARD_PATTERN)) {
				return errorInfo(attr, "_身份证格式有误", i);
			}
			//邮箱验证
			if (attr.isEmail() && getMatchRes(c, attr, ValidityConstants.EMAIL_PATTERN)) {
				return errorInfo(attr, "_邮箱格式有误", i);
			}
			//integer 验证
			if (attr.isInteger() && getMatchRes(c, attr, ValidityConstants.INTEGER_PATTERN)) {
				return errorInfo(attr, "_整数格式有误", i);
			}
			//float、double 验证
			if (attr.isFloat() && getMatchRes(c, attr, ValidityConstants.FLOAT_PATTERN)) {
				return errorInfo(attr, "_数字格式有误", i);
			}
			//最大长度校验
			if (attr.maxLength() > 0 && c.length() > attr.maxLength()) {
				return errorInfo(attr, "_超出最大长度", i);
			}
			//最大值校验
			if (Integer.parseInt(attr.max()) > 0) {
				if (Common.isNumber(c)) {
					if (Integer.parseInt(c) > attr.maxLength()) {
						return errorInfo(attr, "_超出最大值", i);
					}
				} else {
					return "第" + i + "行：" + "_必须为数字";
				}
			}
			//最小值校验
			if (attr.min() > 0) {
				if (Common.isNumber(c)) {
					if (Integer.valueOf(c).intValue() > attr.maxLength()) {
						return errorInfo(attr, "_小于最小值", i);
					}
				} else {
					return "第" + (i + 2) + "行：" + "_必须为数字";
				}
			}
		}
		return null;
	}

	/**
	 * 正则匹配返回
	 *
	 * @param c
	 * @param attr
	 * @param pattern
	 * @return
	 * @Author fxj
	 * @Date 2019-08-06
	 **/
	private boolean getMatchRes(String c, ExcelAttribute attr, String pattern) {
		return !c.matches(Common.isEmpty(attr.pattern()) ? pattern : attr.pattern());
	}

	/**
	 * @param from 源
	 * @param to   反射后的目标
	 * @Description: 反射实体类
	 * @Author: hgw
	 * @Date: 2019/11/1 16:38
	 * @return: void
	 **/
	public static void reflectionAttr(Object from, Object to) {
		try {
			Class clazz1 = Class.forName(from.getClass().getName());
			Class clazz2 = Class.forName(to.getClass().getName());
			// 获取两个实体类的所有属性
			Field[] fields1 = clazz1.getDeclaredFields();
			Field[] fields2 = clazz2.getDeclaredFields();
			SalaryAccountUtil cr = new SalaryAccountUtil();
			// 遍历class1Bean，获取逐个属性值，然后遍历class2Bean查找是否有相同的属性，如有相同则赋值
			for (Field f1 : fields1) {
				if (f1.getName().equals("id"))
					continue;
				Object value = cr.invokeGetMethod(from, f1.getName(), null);
				for (Field f2 : fields2) {
					if (f1.getName().equals(f2.getName()) && !f2.getName().equals("serialVersionUID")
							&& !f2.getName().equals("saiList")) {
						Object[] obj = new Object[1];
						obj[0] = value;
						cr.invokeSetMethod(to, f2.getName(), obj);
					}
				}
			}
		} catch (Exception e) {
			log.error("反射失败", e);
			e.printStackTrace();
		}
	}

	/**
	 * 执行某个Field的getField方法
	 *
	 * @param clazz     类
	 * @param fieldName 类的属性名称
	 * @param args      参数，默认为null
	 * @return
	 */
	public Object invokeGetMethod(Object clazz, String fieldName, Object[] args) {
		String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		Method method = null;
		try {
			if (methodName.equals("SerialVersionUID")) {
				return "";
			}
			method = Class.forName(clazz.getClass().getName()).getDeclaredMethod("get" + methodName);
			return method.invoke(clazz);
		} catch (Exception e) {
			log.error("执行某个Field的getField方法异常!", e);
			return "";
		}
	}

	/**
	 * 执行某个Field的setField方法
	 *
	 * @param clazz     类
	 * @param fieldName 类的属性名称
	 * @param args      参数，默认为null
	 * @return
	 */
	@SuppressWarnings({"unchecked", "rawtypes"})
	private Object invokeSetMethod(Object clazz, String fieldName, Object[] args) {
		String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		Method method = null;
		try {
			Class[] parameterTypes = new Class[1];
			Class c = Class.forName(clazz.getClass().getName());
			Field field = c.getDeclaredField(fieldName);
			parameterTypes[0] = field.getType();
			method = c.getDeclaredMethod("set" + methodName, parameterTypes);
			return method.invoke(clazz, args);
		} catch (Exception e) {
			log.error("执行某个Field的setField方法异常!", e);
			return "";
		}
	}

}
