package com.yifu.cloud.plus.v1.yifu.salary.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TSettleDomain;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ResultConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants;
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.common.dapr.config.DaprArchivesProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprSocialProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.HttpDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.*;
import com.yifu.cloud.plus.v1.yifu.salary.mapper.SysConfigLimitMapper;
import com.yifu.cloud.plus.v1.yifu.salary.mapper.TSalaryStandardMapper;
import com.yifu.cloud.plus.v1.yifu.salary.service.*;
import com.yifu.cloud.plus.v1.yifu.salary.util.SalaryAccountUtil;
import com.yifu.cloud.plus.v1.yifu.salary.util.SalaryConstants;
import com.yifu.cloud.plus.v1.yifu.salary.vo.*;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 标准薪酬工资表
 *
 * @author hgw
 * @date 2019-07-30 15:00:05
 */
@Log4j2
@AllArgsConstructor
@Service("salaryUploadService")
@EnableConfigurationProperties({DaprArchivesProperties.class, DaprSocialProperties.class})
public class SalaryUploadServiceImpl extends ServiceImpl<TSalaryStandardMapper, TSalaryStandard> implements SalaryUploadService {

	private final DaprArchivesProperties archivesProperties;

	private final DaprSocialProperties socialProperties;

	private final TSalaryStandardService tSalaryStandardService;

	private final MSalaryEstimateService mSalaryEstimateService;

	private final TSalaryAccountService tSalaryAccountService;

	private final TSalaryAccountItemService tSalaryAccountItemService;

	private final TSalaryConfigStandardService tSalaryConfigStandardService;

	//配置-工资
	private final TConfigSalaryService configSalaryService;

	private final TSpecialDeducationSumService tSpecialDeducationSumService;

	private final TSalaryTaxConfigService tSalaryTaxConfigService;

	private final TPauseSalaryService tPauseSalaryService;

	private final TSalaryEmployeeService employeeService;

	private final TSalaryStandardSetService tSalaryStandardSetService;

	private final TOwnDeptService tOwnDeptService;

	private final TSalaryLockService salaryLockService;

	private final TSalaryAttaService tSalaryAttaService;

	private final TApprovalRecordService auditLogService;

	private final TSalaryStandardIssueResService tSalaryStandardIssueResService;

	private final TBankSetService tBankSetService;

	// 缓存信息
	private final CacheManager cacheManager;

	private final AtomicInteger importTwoAtomicInteger = new AtomicInteger(0);

	private final SysConfigLimitMapper configLimitMapper;

	/**
	 * vo.jsonString 客户原表数据
	 * repeatFlag 默认 0：不允许重复导入已存在系统内的数据；1：允许重复导入
	 * @Description: 普通工资上传
	 * @Author: hgw
	 * @Date: 2019/9/4 15:58
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	@Override
	public R<List<ErrorMessage>> salaryUpload(SalaryUploadParamVo vo) {
		Integer maxLimit = configLimitMapper.getSysConfigLimitByKey("IMPORT_SALARY_TWO_LIMIT");
		if (Common.isEmpty(maxLimit)) {
			maxLimit = 10;
		}
		if (importTwoAtomicInteger.incrementAndGet() <= maxLimit){
			try {
				return this.salaryUploadCore(vo);
			} catch (Exception e){
				log.error("薪资导入异常：",e);
				return R.failed("薪资导入异常，请检查表数据");
			} finally {
				importTwoAtomicInteger.decrementAndGet();
			}
		} else {
			// 前面做了+1（atomicInteger.incrementAndGet()）这里也要-1
			importTwoAtomicInteger.decrementAndGet();
			log.error("超出阈值："+ ResultConstants.IMPORT_DOWN_LOAD_DATA);
			return R.failed("薪资导入，" + ResultConstants.IMPORT_DOWN_LOAD_DATA);
		}

	}

	private R<List<ErrorMessage>> salaryUploadCore(SalaryUploadParamVo vo) {
	// R<List<ErrorMessage>> salaryUpload(String jsonString, String settleDepart, String configId, String salaryType, String orderId)
		String jsonString = vo.getJsonString();
		String settleDepart = vo.getSettleDepart();
		String configId = vo.getConfigId();
		String salaryType = vo.getSalaryType();
		String orderId = vo.getOrderId();
		if (Common.isNotNull(jsonString) && Common.isNotNull(settleDepart) && Common.isNotNull(salaryType)) {

			R<TSettleDomainSelectVo> sdr = HttpDaprUtil.invokeMethodPost(archivesProperties.getAppUrl(), archivesProperties.getAppId()
					, "/tsettledomain/inner/getSettleDomainVoById", settleDepart, TSettleDomainSelectVo.class, SecurityConstants.FROM_IN);
			// 结算主体
			TSettleDomainSelectVo dept = null;
			if (sdr != null && sdr.getData() != null) {
				dept = sdr.getData();
			}

			// 薪资识别配置（原表-标准模板）
			List<TSalaryConfigStandard> salaryAccountList = tSalaryConfigStandardService.list();
			Map<String, TSalaryConfigStandard> salaryConfigMap = new HashMap<>();  //存放所有字段
			Map<String, Boolean> isMustMap = new HashMap<>();  //存放必填字段
			for (TSalaryConfigStandard sc : salaryAccountList) {
				salaryConfigMap.put(sc.getCnName(), sc);
				if (Common.isNotNull(sc.getIsMustNeed()) && SalaryConstants.IS_MUST.equals(sc.getIsMustNeed())) {
					isMustMap.put(sc.getDbFiedName(), true);
				}
			}

			if (dept == null || dept.getId() == null) {
				return R.failed("新建工资主表失败-获取结算主体信息为空");
			}
			// 2020-3-29 11:24:14变更为结算主体的封面抬头
			String invoiceTitle = dept.getBusinessSubjectName();
			if (Common.isEmpty(invoiceTitle)) {
				return R.failed("上传失败-获取结算主体的-封面抬头-信息为空，请去<EKP系统-项目>模块，编辑封面抬头后再导入");
			}

			YifuUser user = SecurityUtils.getUser();
			if (null == user || null == user.getId()) {
				return R.failed("获取登录用户信息失败！");
			}

			TConfigSalary configSalary;

			if (Common.isNotNull(configId)) {
				// 薪资配置-结算月、社保月等信息
				configSalary = configSalaryService.getById(configId);
			} else {
				configSalary = configSalaryService.getById(CommonConstants.ONE_STRING);
				if(Common.isEmpty(configSalary)) {
					configSalary = new TConfigSalary();
				}
			}
			try {
				String json = jsonString.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
				jsonString = URLDecoder.decode(json, "UTF-8").replace("=", "");
				vo.setJsonString(jsonString);
				SalaryAccountUtil util1 = new SalaryAccountUtil();

				TSalaryEmployee empSearch = new TSalaryEmployee();
				empSearch.setUnitId(dept.getCustomerId());
				List<TSalaryEmployee> empList = employeeService.list(Wrappers.<TSalaryEmployee>query().lambda()
						.eq(TSalaryEmployee::getUnitId, dept.getCustomerId()));
				Map<String, TSalaryEmployee> empIdCardMap = new HashMap<>();
				Map<String, TSalaryEmployee> empNameMap = new HashMap<>();
				boolean isDuplicateName = false;
				if (empList != null) {
					TSalaryEmployee es;
					//  筛选人员，添加判断：非在职，或开户行为空，或 结算主体等于选择的结算主体且在职，都可以存入Map优先备用
					// 2022-10-18 17:14:37 hgw变更：开户行省不为空且是导入部门，优先取用
					for (TSalaryEmployee e : empList) {
						es = empIdCardMap.get(e.getEmpIdcard());
						if (es == null || (e.getDeptId().equals(settleDepart) && Common.isNotNull(e.getBankProvince()))) {
							empIdCardMap.put(e.getEmpIdcard(), e);
							empNameMap.put(e.getEmpName().replace(" ", ""), e);
						}
					}
					if (empNameMap.size() == empIdCardMap.size()) {
						isDuplicateName = true;
					}
				}
				// 自有员工结算主体id，新员工使用
				Map<String, Integer> ownDeptMap = tOwnDeptService.getOwnDeptMap();
				// 自有员工所在结算主体Map
				Map<String, Integer> ownEmployeeMap = tOwnDeptService.getOwnEmpMap();

				// 2.6.6:校验导入数据重复的Map格式：#身份证号_工资月份_报表类型_应发金额
				Map<String, Integer> checkMap = tSalaryAccountService.getAccountCheckMap(dept.getId(), DateUtil.addMonth(configSalary.getSalaryMonth()), salaryType);

				Map<String, BigDecimal> specialMap = tSalaryAccountService.getAccountSpecialMap(invoiceTitle, dept.getCustomerId(), DateUtil.addMonth(configSalary.getSalaryMonth()));

				List<String> checkListY = new ArrayList<>();
				// 劳务费和稿酬 薪资类型互斥校验Map格式：本年度#身份证号
				if ((CommonConstants.THREE_STRING.equals(salaryType) || CommonConstants.FOUR_STRING.equals(salaryType)) && Common.isNotNull(configSalary)) {
					checkListY = tSalaryAccountService.getAccountYearCheckMap();
				}

				if (Common.isNotNull(vo.getIsIssue()) && vo.getIsIssue() == 1 && vo.getResList() != null && !vo.getResList().isEmpty()) {
					for (TSalaryStandardIssueRes res : vo.getResList()) {
						if (Common.isEmpty(res.getIssueId())) {
							return R.failed("代发户配置id不可为空");
						}
						if (Common.isEmpty(res.getBankName())) {
							return R.failed("代发户开户行不可为空");
						}
						if (Common.isEmpty(res.getBankNo())) {
							return R.failed("代发户卡号不可为空");
						}
						if (Common.isEmpty(res.getBankProvince()) || Common.isEmpty(res.getBankProvinceName())
								|| Common.isEmpty(res.getBankCity()) || Common.isEmpty(res.getBankCityName())) {
							return R.failed("代发户开户行省、市不可为空");
						}
					}
				}
				Map<String, String> bankMap = tBankSetService.getBankMap(null);

				util1.getJsonStringToList(user, vo, dept, configSalary, salaryConfigMap, isMustMap,
						empIdCardMap, empNameMap, isDuplicateName, checkListY, invoiceTitle,
						employeeService, checkMap, specialMap, ownEmployeeMap, ownDeptMap, tSalaryAccountService, bankMap);
				List<TSalaryAccountVo> saList = util1.getEntityList();

				if ((null != util1.getErrorInfo() && !util1.getErrorInfo().isEmpty())) {
					return R.failed(util1.getErrorInfo());
				} else {
					if (null != saList && !saList.isEmpty()) {
						// return R.ok(saList)
						//薪资导入
						if (CommonConstants.ZERO_STRING.equals(salaryType)) {
							return this.saveAndSubmit(configSalary, saList, vo, dept);
						}
						//劳务费和稿酬导入
						if (CommonConstants.THREE_STRING.equals(salaryType) || CommonConstants.FOUR_STRING.equals(salaryType)) {
							return this.saveLaborSubmit(configSalary, saList, vo, dept);
						}
					} else {
						return R.failed("导入数据不可为空");
					}
				}
			} catch (Exception e) {
				log.error("薪资导入异常：",e);
				return R.failed("数据导入解析失败！");
			}

		}
		return R.failed("导入数据不可为空");
	}

	/**
	 * @param sav  报账表vo
	 * @param dept 结算主体
	 * @param user 登录人
	 * @Description: 新建工资主表
	 * @Author: hgw
	 * @Date: 2019/9/26 9:44
	 * @return: com.yifu.cloud.v1.hrms.api.entity.TSalaryStandard
	 **/
	public R<TSalaryStandard> saveNewTSalary(TConfigSalary configSalary, TSalaryAccountVo sav, TSettleDomainSelectVo dept
			, YifuUser user, LocalDateTime nowTime, String invoiceTitle, String newEmpUpdateFlag) {
		TSalaryStandard s = null;
		if (sav != null) {
			if (null == user || null == user.getId()) {
				return null;
			}
			s = new TSalaryStandard();
			if (Common.isNotNull(newEmpUpdateFlag)) {
				s.setNewEmpUpdateFlag(newEmpUpdateFlag);
			}
			s.setInvoiceTitle(invoiceTitle);
			s.setType(CommonConstants.ZERO_INT);
			s.setBelongDeptId(String.valueOf(user.getDeptId()));
			if (Common.isNotNull(user.getDeptName())) {
				s.setBelongDeptCode(user.getDeptName());
			} else {
				s.setBelongDeptCode("未获取到员工的DeptName");
			}
			s.setCreateTime(nowTime);
			s.setDeleteFlag(SalaryConstants.NOT_DELETE);
			s.setDeptId(dept.getId());
			s.setDeptName(dept.getDepartName());
			s.setDeptNo(dept.getDepartNo());
			s.setUnitId(dept.getCustomerId());
			s.setUnitName(dept.getCustomerName());
			s.setUnitNo(dept.getCustomerCode());
			if (dept.getProvince() != null) {
				s.setProvince(dept.getProvince());
			}
			if (dept.getCity() != null) {
				s.setCity(dept.getCity());
			}
			if (dept.getTown() != null) {
				s.setTown(dept.getTown());
			}
			s.setFormType(sav.getFormType());
			s.setMoneyFrom(CommonConstants.ZERO_INT);
			s.setSalaryMonth(sav.getSalaryMonth());
			s.setSettlementMonth(sav.getSettlementMonth());
			//s.setSettlementAmount()
			s.setStatus(SalaryConstants.AUDIT_STATUS[0]);
			s.setBpoFlag(dept.getBpoFlag());
			s.setIncomeMonth(sav.getSalaryMonth());
			s.setBusinessPrimaryType(dept.getBusinessPrimaryType());
			s.setBusinessSecondType(dept.getBusinessSecondType());
			s.setBusinessThirdType(dept.getBusinessThirdType());
			if (configSalary != null) {
				s.setSetId(configSalary.getId());
				s.setSetName(configSalary.getName());
				if (Common.isNotNull(configSalary.getIncomeMonth())) {
					s.setIncomeMonth(DateUtil.addMonth(configSalary.getIncomeMonth()));
				}
			}
		}
		return new R<>(s);
	}

	/**
	 * @param savList 报账表Vo
	 * @Description: 保存并提交
	 * @Author: hgw
	 * @Date: 2019/9/20 17:05
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	private R saveAndSubmit(TConfigSalary configSalary, List<TSalaryAccountVo> savList, SalaryUploadParamVo vo, TSettleDomainSelectVo dept) {
		if (Common.isNotNull(savList) && !savList.isEmpty()) {
			String orderId = vo.getOrderId();
			// 代发户
			Integer isIssue = vo.getIsIssue();
			// 代发户与薪资关联表
			List<TSalaryStandardIssueRes> resList = vo.getResList();
			TSalaryAccountVo salaryAccountVo = savList.get(0);
			List<TSalaryAccountItem> saiList = null;  //报账明细List
			String invoiceTitle = dept.getBusinessSubjectName();
			if (Common.isEmpty(invoiceTitle)) {
				return R.failed("新建工资主表失败-获取结算主体的-封面抬头-信息为空，请去<EKP系统-项目>模块，编辑封面抬头后再导入");
			}
			YifuUser user = SecurityUtils.getUser();
			if (null == user || null == user.getId()) {
				return R.failed("新建工资主表失败-获取登录人信息为空");
			}
			LocalDateTime nowTime = LocalDateTime.now();
			TSalaryStandard salary;
			//工资主表
			R<TSalaryStandard> sr = this.saveNewTSalary(configSalary, salaryAccountVo, dept, user, nowTime, invoiceTitle
					, vo.getNewEmpUpdateFlag());  //工资主表
			if (sr == null || sr.getCode() == CommonConstants.FAIL) {
				return sr;
			} else {
				salary = sr.getData();
			}
			boolean isActual = false;  //false：应发导入； true：实发 倒推导入
			List<TSalaryAccountItemVo> itemList = salaryAccountVo.getSaiList();
			for (TSalaryAccountItemVo item : itemList) {
				if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
					isActual = true;
					break;
				}
			}
			if (salary != null) {
				if (Common.isNotNull(vo.getExcelType())) {
					salary.setExcelType(vo.getExcelType());
				}
				if (Common.isNotNull(vo.getOriginalSetName())){
					salary.setOriginalSetName(vo.getOriginalSetName());
				}
				if (Common.isNotNull(vo.getIsFixedColumn())){
					salary.setIsFixedColumn(vo.getIsFixedColumn());
				}
				// 薪资导入、删除前加锁：
				TSalaryLock lock = salaryLockService.lambdaQuery()
						.eq(TSalaryLock::getDeptId, dept.getId())
						.eq(TSalaryLock::getDeleteFlag, CommonConstants.ZERO_INT)
						.last("limit 1").one();
				if (lock != null && Common.isNotNull(lock.getId())) {
					return R.failed("当前结算主体已被用户锁定，请稍等！超过10分钟还没释放，请联系管理员！当前时间：" + nowTime);
				} else {
					lock = new TSalaryLock();
					lock.setCreateTime(nowTime);
					lock.setDeleteFlag(CommonConstants.ZERO_INT);
					lock.setDeptId(dept.getId());
					lock.setDeptName(dept.getDepartName());
					lock.setSettleMonth(salaryAccountVo.getSettlementMonth());
					lock.setType(CommonConstants.ZERO_INT);
					salaryLockService.save(lock);
					TSalaryLock lockUpdate;
					try {
						//设置订单号  20220831
						salary.setOrderId(orderId);
						// 薪资核心导入代码
						return this.doCoreSalary(savList, salaryAccountVo, saiList, dept, invoiceTitle, user, nowTime
								, salary, isActual, isIssue, resList);
					} catch (Exception e) {
						lockUpdate = new TSalaryLock();
						lockUpdate.setId(lock.getId());
						lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
						salaryLockService.updateById(lockUpdate);
						throw new RuntimeException(e.getMessage() == null ? "薪资导入失败！" : e.getMessage());
					} finally {
						lockUpdate = new TSalaryLock();
						lockUpdate.setId(lock.getId());
						lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
						if (Common.isNotNull(salary.getId())) {
							lockUpdate.setSalaryId(salary.getId());
							lockUpdate.setSettleMoney(salary.getSettlementAmount());
						}
						salaryLockService.updateById(lockUpdate);
					}
				}
			} else {
				return R.failed("新建工资主表失败");
			}
		}
		return R.failed("提交的数据不可为空");
	}

	/**
	 * @Description: 薪资导入核心代码
	 * @Author: hgw
	 * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.String>
	 **/
	@Transactional
	public R doCoreSalary(List<TSalaryAccountVo> savList, TSalaryAccountVo salaryAccountVo
			, List<TSalaryAccountItem> saiList, TSettleDomainSelectVo dept
			, String invoiceTitle, YifuUser user, LocalDateTime nowTime, TSalaryStandard salary
			, boolean isActual, Integer isIssue, List<TSalaryStandardIssueRes> resList) {
		// 社保类型0：缴费库；1：预估库
		String socialType = CommonConstants.ZERO_STRING;
		if (Common.isNotNull(dept.getSocialType())) {
			socialType = dept.getSocialType();
		}
		// 公积金类型0：缴费库；1：预估库
		String fundType = CommonConstants.ZERO_STRING;
		if (Common.isNotNull(dept.getFundType())) {
			fundType = dept.getFundType();
		}

		List<TSalaryAccount> aList;
		TSalaryAccount a;
		//定库：
		List<TPaymentBySalaryVo> socialEstmateList = null;  //社保缴费库
		List<TPaymentBySalaryVo> fundEstmateList = null;  //公积金缴费库
		List<TPaymentBySalaryVo> socialForecastList = null;  //社保预估库
		List<TPaymentBySalaryVo> fundForecastList = null;  //公积金预估库
		TPaymentBySalaryVo forecast = new TPaymentBySalaryVo();
		//不扣社保
		if (salaryAccountVo != null && !CommonConstants.ZERO_STRING.equals(salaryAccountVo.getIsDeductSocial())) {
			forecast.setSettleDomainId(dept.getId());
			if (SalaryConstants.PRIORITY_ZERO.equals(salaryAccountVo.getSocialPriority())) {
				forecast.setSocialCreateMonth(salaryAccountVo.getDeduSocialMonth());
			} else if (SalaryConstants.PRIORITY_ONE.equals(salaryAccountVo.getSocialPriority())) {
				forecast.setSocialPayMonth(salaryAccountVo.getDeduSocialMonth());
			} else {
				forecast.setSocialPayMonth(SalaryConstants.PRIORITY_ZERO); //没优先级，则限制住
			}
			if (CommonConstants.ZERO_STRING.equals(socialType)) {
				R<TPaymentVo> tPaymentVoR = HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
						, "/tpaymentinfo/inner/selectTPaymentBySalaryVo", forecast, TPaymentVo.class, SecurityConstants.FROM_IN);
				if (tPaymentVoR != null && tPaymentVoR.getData() != null && tPaymentVoR.getData().getPaymentList() != null) {
					socialEstmateList = tPaymentVoR.getData().getPaymentList();
				}
			}
			if (CommonConstants.ONE_STRING.equals(socialType)) {
				// 预估数据
				R<TPaymentVo> tForecastVoR = HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
						, "/tforecastlibrary/inner/selectTForecastBySalaryVo", forecast, TPaymentVo.class, SecurityConstants.FROM_IN);
				if (tForecastVoR != null && tForecastVoR.getData() != null && tForecastVoR.getData().getPaymentList() != null) {
					socialForecastList = tForecastVoR.getData().getPaymentList();
				}
			}
		}
		if (salaryAccountVo != null && !CommonConstants.ZERO_STRING.equals(salaryAccountVo.getIsDeductFund())) {
			forecast = new TPaymentBySalaryVo();
			forecast.setSettleDomainId(dept.getId());
			if (SalaryConstants.PRIORITY_ZERO.equals(salaryAccountVo.getFundPriority())) {
				forecast.setProvidentCreateMonth(salaryAccountVo.getDeduProvidentMonth());
			} else if (SalaryConstants.PRIORITY_ONE.equals(salaryAccountVo.getFundPriority())) {
				forecast.setProvidentPayMonth(salaryAccountVo.getDeduProvidentMonth());
			} else {
				forecast.setProvidentPayMonth(SalaryConstants.PRIORITY_ZERO); //没优先级，则限制住
			}
			if (CommonConstants.ZERO_STRING.equals(fundType)) {
				R<TPaymentVo> tPaymentVoR = HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
						, "/tpaymentinfo/inner/selectTPaymentBySalaryVo", forecast, TPaymentVo.class, SecurityConstants.FROM_IN);
				if (tPaymentVoR != null && tPaymentVoR.getData() != null && tPaymentVoR.getData().getPaymentList() != null) {
					fundEstmateList = tPaymentVoR.getData().getPaymentList();
				}
			}
			if (CommonConstants.ONE_STRING.equals(fundType)) {
				// 预估数据
				R<TPaymentVo> tForecastVoR = HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
						, "/tforecastlibrary/inner/selectTForecastBySalaryVo", forecast, TPaymentVo.class, SecurityConstants.FROM_IN);
				if (tForecastVoR != null && tForecastVoR.getData() != null && tForecastVoR.getData().getPaymentList() != null) {
					fundForecastList = tForecastVoR.getData().getPaymentList();
				}
			}
		}
		aList = new ArrayList<>();
		//true：从缴费库等扣社保标识；false：走代扣
		boolean modelPersonSocialFlag;
		boolean modelPersonFundFlag;
		boolean modelUnitSocialFlag;
		boolean modelUnitFundFlag;

		Set<String> socialList = new HashSet<>();  //社保需要存储的id
		Set<String> fundList = new HashSet<>();  //公积金需要存储的id
		Set<String> forecastSocialList = new HashSet<>();  //预估de社保需要存储的id
		Set<String> forecastFundList = new HashSet<>();  //预估de公积金需要存储的id
		BigDecimal relaySalary;  //工资应发
		BigDecimal relaySalarySum = BigDecimal.ZERO;  //工资应发
		BigDecimal personalDebt;  //个人社保、公积金欠款
		//前次个人待补足
		String preMonth = DateUtil.addMonth(-1);
		List<TSalaryAccountItem> preSupplyList = tSalaryAccountItemService.getAllTSalaryAccountItem(
				dept.getId(), preMonth, SalaryConstants.PRE_CURRENT_SUPPLY_JAVA, null, null, null);
		BigDecimal preSupply;  //前次个人待补足

		//年终奖list-验证年终奖次数
		List<TSalaryAccountItem> annualBonusList;
		BigDecimal annualBonus;
		TSpecialDeducationSum sds;
		String nowYearMonth = DateUtil.getCurrentDateString("yyyyMM");
		BigDecimal sdSum;  // 专项扣除汇总金额
		BigDecimal costReduction;  //减除费用
		String maxYearMonth = null;  //起始计税月（例如：计税月是今年之前的，则取值今年1月，否则=计税月）
		List<TSalaryAccountItem> asList;  //累计扣税
		String checkYearFinalStyle;  //薪资和年终奖扣税方案(0：合并；1：单独)
		List<TSalaryTaxConfig> personTax = tSalaryTaxConfigService.getTaxConfigByPersonList(new TSalaryTaxConfig());
		List<TSalaryTaxConfig> annousTax = tSalaryTaxConfigService.getTaxConfigByAnnualBonusList(new TSalaryTaxConfig());
		List<TSalaryTaxConfig> actualTax = tSalaryTaxConfigService.getTaxConfigByActualList(new TSalaryTaxConfig());
		int size = savList.size();
		TSalaryAccountItem annousSai;
		// 自有员工人数
		int ownNum = 0;
		// 自有员工应发金额
		BigDecimal ownMoney = BigDecimal.ZERO;

		// 年终奖是否已存在 （true：已存在，不可导入）
		boolean yearEndError = false;
		// 年终奖错误信息合计：
		List<ErrorMessage> errorInfo = new ArrayList<>();
		// 劳务费、稿酬是否含有发薪false：否；true：是
		boolean haveSalaryFlag = false;
		// 是否含有特殊金额false：否；true：是
		boolean haveSpecialFlag = false;
		// 是否重复金额false：否；true：是
		boolean repeatFlag = false;
		List<String> idCardList = new ArrayList<>();
		for (TSalaryAccountVo vo : savList) {
			if (Common.isNotNull(vo.getEmpIdcard())) {
				idCardList.add(vo.getEmpIdcard());
			}
		}
		// 工资查询所需的全部list，组装Map来使用
		Map<String, TSpecialDeducationSum> sdsMap = tSpecialDeducationSumService.getTSpecialDeducationSumMap(nowYearMonth, idCardList);
		Map<String, List<TSalaryAccountItem>> itemMap = tSalaryAccountItemService.getAllItemVoList(idCardList, invoiceTitle);

		// 是否劳务费，true:是
		boolean isLabor = CommonConstants.THREE_STRING.equals(salaryAccountVo.getFormType());
		TSalaryAccountItem sai;
		for (int i = CommonConstants.ZERO_INT; i < size; i++) {
			modelPersonSocialFlag = true;
			modelPersonFundFlag = true;
			modelUnitSocialFlag = true;
			modelUnitFundFlag = true;
			relaySalary = BigDecimal.ZERO;
			personalDebt = BigDecimal.ZERO;
			preSupply = BigDecimal.ZERO;
			annualBonus = null;
			sdSum = BigDecimal.ZERO;
			a = new TSalaryAccount();
			costReduction = BigDecimal.ZERO;
			annousSai = null;
			try {
				SalaryAccountUtil.reflectionAttr(savList.get(i), a);
				if (!haveSalaryFlag && a.getHaveSalaryFlag() != null && a.getHaveSalaryFlag() == CommonConstants.ONE_INT) {
					haveSalaryFlag = true;
				}
				if (!haveSpecialFlag && a.getHaveSpecialFlag() != null && a.getHaveSpecialFlag() == CommonConstants.ONE_INT) {
					haveSpecialFlag = true;
				}
				if (!repeatFlag && a.getIsRepeat() != null && a.getIsRepeat() == CommonConstants.ONE_INT) {
					repeatFlag = true;
				}
				checkYearFinalStyle = a.getAnnualBonusType();
				if (Common.isNotNull(a.getTaxMonth())) {
					maxYearMonth = DateUtil.getMaxYearMonth(a.getTaxMonth());
				} else if (!isLabor) {
					return R.failed("获取计税月错误");
				}
				if (savList.get(i).getSaiList() != null && !savList.get(i).getSaiList().isEmpty()) {
					saiList = new ArrayList<>();
					annousSai = null;
					for (int j = 0; j < savList.get(i).getSaiList().size(); j++) {
						sai = new TSalaryAccountItem();
						SalaryAccountUtil.reflectionAttr(savList.get(i).getSaiList().get(j), sai);
						if (sai.getIsTax() == null) {
							sai.setIsTax(CommonConstants.ZERO_INT);
						}
						//代扣个人社保
						if (SalaryConstants.WITHHOLIDING_PERSON_SOCIAL.equals(sai.getJavaFiedName())) {
							modelPersonSocialFlag = false;
							personalDebt = personalDebt.add(sai.getSalaryMoney());
							sai.setIsTax(CommonConstants.ONE_INT);
							a.setPersonSocial(sai.getSalaryMoney());
						}
						//代扣个人公积金
						if (SalaryConstants.WITHHOLIDING_PERSON_FUND.equals(sai.getJavaFiedName())) {
							modelPersonFundFlag = false;
							personalDebt = personalDebt.add(sai.getSalaryMoney());
							sai.setIsTax(CommonConstants.ONE_INT);
							a.setPersonFund(sai.getSalaryMoney());
						}
						//个人代扣：李靖2020-6-16 18:16:09提的需求：
						if (SalaryConstants.PDEDUCTION_JAVA.equals(sai.getJavaFiedName())) {
							personalDebt = personalDebt.add(sai.getSalaryMoney());
						}
						//代扣单位社保
						if (SalaryConstants.WITHHOLIDING_UNIT_SOCIAL.equals(sai.getJavaFiedName())) {
							modelUnitSocialFlag = false;
							a.setUnitSocial(sai.getSalaryMoney());
						}
						//代扣单位公积金
						if (SalaryConstants.WITHHOLIDING_UNIT_FUND.equals(sai.getJavaFiedName())) {
							modelUnitFundFlag = false;
							a.setUnitFund(sai.getSalaryMoney());
						}
						saiList.add(sai);
						//工资应发
						if (SalaryConstants.RELAY_SALARY_JAVA.equals(sai.getJavaFiedName())) {
							relaySalary = sai.getSalaryMoney();
						}
						//减除费用
						if (SalaryConstants.COST_REDUCTION_JAVA.equals(sai.getJavaFiedName())) {
							costReduction = sai.getSalaryMoney();
							a.setCostReduction(costReduction);
						}
						//年终奖
						if (SalaryConstants.ANNUAL_BONUS_JAVA.equals(sai.getJavaFiedName())) {
							annualBonus = sai.getSalaryMoney();
							annousSai = sai;
						}
					}
					if (Common.isEmpty(a.getIsDeductSocial()) || SalaryConstants.IS_DEDUCT_ONE.equals(a.getIsDeductSocial())) {
						a.setSocialType(socialType);
						a.setIsDeductSocial(SalaryConstants.IS_DEDUCT_ONE);
						//社保公积金金额扣缴：   true : 从库里扣除社保等;false : 走代扣
						if (modelPersonSocialFlag) {
							personalDebt = personalDebt.add(this.saveNewItems(saiList, SalaryConstants.PERSONAL_SOCIAL,
									SalaryConstants.PERSONAL_SOCIAL_JAVA,
									this.getSocialOrFundMoneyForForecast(socialType, dept, a, socialEstmateList, socialForecastList, true, true, socialList, fundList, forecastSocialList, forecastFundList), CommonConstants.ONE_INT));
						}
						if (modelUnitSocialFlag) {
							this.saveNewItems(saiList, SalaryConstants.UNIT_SOCIAL,
									SalaryConstants.UNIT_SOCIAL_JAVA,
									this.getSocialOrFundMoneyForForecast(socialType, dept, a, socialEstmateList, socialForecastList, true, false, socialList, fundList, forecastSocialList, forecastFundList), CommonConstants.ZERO_INT);
						}
					}
					if (Common.isEmpty(a.getIsDeductFund()) || SalaryConstants.IS_DEDUCT_ONE.equals(a.getIsDeductFund())) {
						a.setFundType(fundType);
						a.setIsDeductFund(SalaryConstants.IS_DEDUCT_ONE);
						if (modelPersonFundFlag) {
							personalDebt = personalDebt.add(this.saveNewItems(saiList, SalaryConstants.PERSONAL_FUND,
									SalaryConstants.PERSONAL_FUND_JAVA,
									this.getSocialOrFundMoneyForForecast(fundType, dept, a, fundEstmateList, fundForecastList, false, true, socialList, fundList, forecastSocialList, forecastFundList), CommonConstants.ONE_INT));
						}
						if (modelUnitFundFlag) {
							this.saveNewItems(saiList, SalaryConstants.UNIT_FUND,
									SalaryConstants.UNIT_FUND_JAVA,
									this.getSocialOrFundMoneyForForecast(fundType, dept, a, fundEstmateList, fundForecastList, false, false, socialList, fundList, forecastSocialList, forecastFundList), CommonConstants.ZERO_INT);
						}
					}
				}

				// 自有员工以及自有员工应发金额
				if (Common.isNotNull(a.getOwnFlag()) && a.getOwnFlag() == 1) {
					ownNum++;
					ownMoney = ownMoney.add(relaySalary);
				}

				//2019-9-29 17:56:10：与主管确认取消这一项_个人社保卡费
				//account.setPsocialCardMoney(calculationPSocialCardMoney(account))// 个人社保卡费

				//前次个人待补足
				for (TSalaryAccountItem saips : preSupplyList) {
					preSupply = preSupply.add(saips.getSalaryMoney());
				}
				if (preSupply.compareTo(SalaryConstants.B_ZERO) != SalaryConstants.EQUAL) {
					this.saveNewItems(saiList, SalaryConstants.PRE_CURRENT_SUPPLY,
							SalaryConstants.PRE_CURRENT_SUPPLY_JAVA, preSupply, CommonConstants.ZERO_INT);
				}
				//专项信息
				sds = sdsMap.get(a.getEmpIdcard() + CommonConstants.DOWN_LINE_STRING + invoiceTitle);
				if (sds != null && Common.isNotNull(sds.getId())) {
					//累计子女教育
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_CHILD_EDU_MONEY,
							SalaryConstants.SUM_CHILD_EDU_MONEY_JAVA, sds.getSumChildEduMoney(), CommonConstants.ZERO_INT));
					a.setSumChildEduMoney(sds.getSumChildEduMoney());
					//累计住房贷款利息
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_HOUSING_LOAN_MONEY,
							SalaryConstants.SUM_HOUSING_LOAN_MONEY_JAVA, sds.getSumHousingLoanMoney(), CommonConstants.ZERO_INT));
					a.setSumHousingLoanMoney(sds.getSumHousingLoanMoney());
					//累计住房租金
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_HOUSING_RENT_MONEY,
							SalaryConstants.SUM_HOUSING_RENT_MONEY_JAVA, sds.getSumHousingRentMoney(), CommonConstants.ZERO_INT));
					a.setSumHousingRentMoney(sds.getSumHousingRentMoney());
					//累计赡养老人
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_SUPPORT_ELDERLY_MONEY,
							SalaryConstants.SUM_SUPPORT_ELDERLY_MONEY_JAVA, sds.getSumSupportElderlyMoney(), CommonConstants.ZERO_INT));
					a.setSumSupportElderlyMoney(sds.getSumSupportElderlyMoney());
					//累计继续教育
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_CONTINUING_EDUCATION_MONEY,
							SalaryConstants.SUM_CONTINUING_EDUCATION_MONEY_JAVA, sds.getSumContinuingEducationMoney(), CommonConstants.ZERO_INT));
					a.setSumContinuingEducationMoney(sds.getSumContinuingEducationMoney());
					//累计3岁以下婴幼儿照护
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_BABY_MONEY,
							SalaryConstants.SUM_BABY_MONEY_JAVA, sds.getSumBabyMoney(), CommonConstants.ZERO_INT));
					a.setSumBabyMoney(sds.getSumBabyMoney());
					//累计个人养老
					sdSum = sdSum.add(this.saveNewItems(saiList, SalaryConstants.SUM_PRIVATE_PENSION,
							SalaryConstants.SUM_PRIVATE_PENSION_JAVA, sds.getSumPrivatePension(), CommonConstants.ZERO_INT));
					a.setSumPrivatePension(sds.getSumPrivatePension());
					//累计专项扣除总额
					this.saveNewItems(saiList, SalaryConstants.SPECIAL_DEDU_MONEY_SUM,
							SalaryConstants.SPECIAL_DEDU_MONEY_SUM_JAVA, sdSum, CommonConstants.ZERO_INT);
				}
				//累计扣税list
				// 2022-1-19 18:01:31 根据樊青青、王成，修改为去除姓名校验
				// asList = tSalaryAccountItemService.getEmpAllSalaryAccountItem(a.getEmpIdcard(), maxYearMonth, invoiceTitle)
				if (!isLabor) {
					asList = this.getAsList(itemMap.get(a.getEmpIdcard()), Integer.parseInt(maxYearMonth));
				} else {
					asList = this.getLaborAsList(itemMap.get(a.getEmpIdcard()), a.getSettlementMonth());
				}

				//验证年终奖计算
				// 2021-12-30 17:09:29王成说年终奖按结算月的年来计算
				if (annualBonus != null && annualBonus.compareTo(SalaryConstants.B_ZERO) != SalaryConstants.EQUAL) {
					annualBonusList = tSalaryAccountItemService.getAllTSalaryAccountItem(
							null, null, SalaryConstants.ANNUAL_BONUS_JAVA,
							a.getSettlementMonth().substring(0, 4), a.getEmpIdcard(), null);
					if (annualBonusList != null && !annualBonusList.isEmpty()) {
						if (!yearEndError) {
							yearEndError = true;
						}
						errorInfo.add(new ErrorMessage((i + 2), a.getEmpIdcard() + "年终奖重复发放"));
					} else {
						//年终奖优化方案 2：自动计算
						if (CommonConstants.TWO_STRING.equals(checkYearFinalStyle)) {
							checkYearFinalStyle = checkYearFinalStyle(isActual, asList, sdSum
									, costReduction, personTax, actualTax, saiList, annualBonus, annousTax, a);
						}
						//年终奖单独扣税
						if (CommonConstants.ONE_STRING.equals(checkYearFinalStyle)) {
							if (!isActual) {
								personalDebt = personalDebt.add(this.saveNewItems(saiList, SalaryConstants.ANNUAL_BONUS_TAX,
										SalaryConstants.ANNUAL_BONUS_TAX_JAVA, calculation2FinalSalary(a, annualBonus, annousTax), CommonConstants.ZERO_INT));
							} else {
								this.saveNewItems(saiList, SalaryConstants.ANNUAL_BONUS_TAX,
										SalaryConstants.ANNUAL_BONUS_TAX_JAVA, calculation2FinalSalary(a, annualBonus, annousTax), CommonConstants.ZERO_INT);
							}
							if (annousSai != null) {
								annousSai.setIsTax(CommonConstants.ONE_INT);
							}
						}
					}
				}
				// 薪资扣税 1：扣税
				// 应发顺推个税
				if (!isActual) {
					personalDebt = personalDebt.add(this.saveNewItems(saiList, SalaryConstants.SALARY_TAX,
							SalaryConstants.SALARY_TAX_JAVA,
							calculation2PersonSalary(isActual, saiList, asList, sdSum
									, costReduction, personTax, actualTax, saiList, a), CommonConstants.ZERO_INT));
				} else {
					// 实发倒推个税应发
					if (!isLabor) {
						this.saveNewItems(saiList, SalaryConstants.SALARY_TAX,
								SalaryConstants.SALARY_TAX_JAVA,
								calculation2PersonSalary(isActual, saiList, asList, sdSum
										, costReduction, personTax, actualTax, saiList, a), CommonConstants.ZERO_INT);
					} else {
						// 实发劳务费，按月累计扣税 2022-3-2 17:32:40 樊青青提的需求
						this.saveNewItems(saiList, SalaryConstants.SALARY_TAX,
								SalaryConstants.SALARY_TAX_JAVA,
								calculation2Labor(saiList, asList
										, saiList), CommonConstants.ZERO_INT);
					}
				}

				if (!isActual) {  //导入应发，顺推实发
					// 个人实发合计
					this.saveNewItems(saiList, SalaryConstants.ACTUAL_SALARY_SUM,
							SalaryConstants.ACTUAL_SALARY_SUM_JAVA,
							calculation(a, relaySalary, saiList), CommonConstants.ZERO_INT);
				}
				if (relaySalary.compareTo(BigDecimal.ZERO) <= 0) {
					relaySalary = a.getRelaySalary();
				}
				//计算个人社保、公积金欠款————工资不够扣缴社保的
				if (relaySalary.compareTo(personalDebt) < SalaryConstants.EQUAL) {
					this.saveNewItems(saiList, SalaryConstants.PERSONAL_DEBT,
							SalaryConstants.PERSONAL_DEBT_JAVA, relaySalary.subtract(personalDebt), CommonConstants.ZERO_INT);
				}
				a.setSaiList(saiList);
				relaySalarySum = relaySalarySum.add(a.getRelaySalary());
				aList.add(a);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (yearEndError) {
			return new R<>(CommonConstants.TWO_INT, "年终奖重复", errorInfo);
		}
		salary.setOwnNums(ownNum);
		salary.setOwnMoney(ownMoney);
		TSalaryDetailVo salaryDetailVo = new TSalaryDetailVo();
		salaryDetailVo.setSalaryAccountList(aList);
		salary.setSettlementAmount(relaySalarySum);
		salary.setHaveSalaryFlag(CommonConstants.ZERO_INT);
		salary.setHaveSpecialFlag(CommonConstants.ZERO_INT);
		salary.setIsRepeat(CommonConstants.ZERO_INT);
		salary.setStatus(SalaryConstants.AUDIT_STATUS[0]);
		if (haveSalaryFlag || haveSpecialFlag || ownNum > 0 || repeatFlag) {
			if (haveSalaryFlag) {
				salary.setHaveSalaryFlag(CommonConstants.ONE_INT);
			}
			if (haveSpecialFlag) {
				salary.setHaveSpecialFlag(CommonConstants.ONE_INT);
			}
			if (repeatFlag) {
				salary.setIsRepeat(CommonConstants.ONE_INT);
			}
		}
		if (!socialList.isEmpty()) {
			//更新社保状态为-已结算
			HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
					, "/tpaymentinfo/inner/updatePaymentSocialStatusToSettle", socialList, Integer.class, SecurityConstants.FROM_IN);
		}
		if (!fundList.isEmpty()) {
			//更新公积金状态为-已结算
			HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
					, "/tpaymentinfo/inner/updatePaymentFundStatusToSettle", fundList, Integer.class, SecurityConstants.FROM_IN);
		}
		if (!forecastSocialList.isEmpty()) {
			//更新社保状态为-已结算
			HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
					, "/tforecastlibrary/inner/updateForecastSocialStatusToSettle", forecastSocialList, Integer.class, SecurityConstants.FROM_IN);
		}
		if (!forecastFundList.isEmpty()) {
			//更新公积金状态为-已结算
			HttpDaprUtil.invokeMethodPost(socialProperties.getAppUrl(), socialProperties.getAppId()
					, "/tforecastlibrary/inner/updateForecastFundStatusToSettle", forecastFundList, Integer.class, SecurityConstants.FROM_IN);
		}
		if (Common.isEmpty(salary.getApplyNo())) {
			salary.setApplyNo(this.getCode());
		}
		salary.setIssueStatus(isIssue);
		//保存工资表
		tSalaryStandardService.save(salary);
		// 是代发户且选了代发户卡号，要保存关联表
		if (Common.isNotNull(isIssue) && isIssue == 1 && resList != null && !resList.isEmpty()) {
			for (TSalaryStandardIssueRes res : resList) {
				res.setSalaryId(salary.getId());
			}
			tSalaryStandardIssueResService.saveBatch(resList);
		}
		TApprovalRecord tApprovalRecord = new TApprovalRecord();
		tApprovalRecord.setApprovalResult(CommonConstants.TWO_STRING);
		tApprovalRecord.setApprovalOpinion("新建表单");
		tApprovalRecord.setSalaryId(salary.getId());
		tApprovalRecord.setNodeId("待提交");
		tApprovalRecord.setApprovalMan(user.getId());
		tApprovalRecord.setApprovalManName(user.getNickname());
		tApprovalRecord.setApprovalTime(DateUtil.getCurrentDateTime());
		auditLogService.save(tApprovalRecord);

		// 获取上一个工资条顺序，复制：
		tSalaryStandardSetService.copyLastSetByDeptId(salary.getId(), dept.getId(), String.valueOf(user.getId()));

		salaryDetailVo.setSalary(salary);
		MSalaryEstimate se;

		// 新增一步：增加同步表
		if (!socialList.isEmpty()) {
			for (String estId : socialList) {
				se = new MSalaryEstimate();
				se.setSalaryId(salary.getId());
				se.setEstimateId(estId);
				se.setIsSocial(SalaryConstants.IS_SOCIAL_ZERO);
				se.setIsNoSalary(SalaryConstants.NOT_IS_NO_SALARY_ZERO);
				se.setType(CommonConstants.ZERO_INT);
				mSalaryEstimateService.save(se);
			}
		}
		if (!fundList.isEmpty()) {
			for (String estId : fundList) {
				se = new MSalaryEstimate();
				se.setSalaryId(salary.getId());
				se.setEstimateId(estId);
				se.setIsSocial(SalaryConstants.IS_FUND_ONE);
				se.setIsNoSalary(SalaryConstants.NOT_IS_NO_SALARY_ZERO);
				se.setType(CommonConstants.ZERO_INT);
				mSalaryEstimateService.save(se);
			}
		}
		if (!forecastSocialList.isEmpty()) {
			for (String estId : forecastSocialList) {
				se = new MSalaryEstimate();
				se.setSalaryId(salary.getId());
				se.setEstimateId(estId);
				se.setIsSocial(SalaryConstants.IS_SOCIAL_ZERO);
				se.setIsNoSalary(SalaryConstants.NOT_IS_NO_SALARY_ZERO);
				se.setType(CommonConstants.ONE_INT);
				mSalaryEstimateService.save(se);
			}
		}
		if (!forecastFundList.isEmpty()) {
			for (String estId : forecastFundList) {
				se = new MSalaryEstimate();
				se.setSalaryId(salary.getId());
				se.setEstimateId(estId);
				se.setIsSocial(SalaryConstants.IS_FUND_ONE);
				se.setIsNoSalary(SalaryConstants.NOT_IS_NO_SALARY_ZERO);
				se.setType(CommonConstants.ONE_INT);
				mSalaryEstimateService.save(se);
			}
		}
		int  i =1;
		for (TSalaryAccount account : aList) {
			account.setSalaryFormId(salary.getId());
			account.setOrderId(salary.getOrderId());
			account.setRowIndex(i);
			i++;
		}
		tSalaryAccountService.saveBatch(aList);
		List<TSalaryAccountItem> saveSaiList = new ArrayList<>();
		for (TSalaryAccount account : aList) {
			saiList = account.getSaiList();
			for (TSalaryAccountItem item : saiList) {
				item.setSalaryAccountId(account.getId());
			}
			saveSaiList.addAll(saiList);
		}
		tSalaryAccountItemService.saveBatch(saveSaiList);
		return R.ok(salaryDetailVo);
	}

	/**
	 * @param itemList
	 * @param maxYearMonth
	 * @Description: 循环获取符合条件的报账
	 * @Author: hgw
	 * @Date: 2022/1/27 17:32
	 * @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TSalaryAccountItem>
	 **/
	private List<TSalaryAccountItem> getAsList(List<TSalaryAccountItem> itemList, int maxYearMonth) {
		List<TSalaryAccountItem> backList = new ArrayList<>();
		if (itemList != null && !itemList.isEmpty()) {
			for (TSalaryAccountItem item : itemList) {
				if (!"3".equals(item.getFormType()) && Integer.parseInt(item.getSettlementMonth()) >= maxYearMonth) {
					backList.add(item);
				}
			}
		}
		return backList;
	}

	/**
	 * @param itemList
	 * @param settleMonth
	 * @Description: 循环获取符合条件的报账
	 * @Author: hgw
	 * @Date: 2022/1/27 17:32
	 * @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TSalaryAccountItem>
	 **/
	private List<TSalaryAccountItem> getLaborAsList(List<TSalaryAccountItem> itemList, String settleMonth) {
		List<TSalaryAccountItem> backList = new ArrayList<>();
		if (itemList != null && !itemList.isEmpty()) {
			for (TSalaryAccountItem item : itemList) {
				if (("3".equals(item.getFormType()))
						&& settleMonth.equals(item.getSettlementMonth())) {
					backList.add(item);
				}
			}
		}
		return backList;
	}

	/**
	 * @param realSalary 应发工资
	 * @param saiList    报账详情表list
	 * @Description: 计算个人实发合计
	 * @Author: hgw
	 * @Date: 2019/10/9 15:14
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal calculation(TSalaryAccount a, BigDecimal realSalary, List<TSalaryAccountItem> saiList) {
		// 实际发放工资 = 应发工资合计-
		// 个人社保扣缴 -个人公积金扣缴-薪资扣税-年终奖扣税-代扣风险抵押金
		// -个人其他费用(就是工资表中的其他费用1+其他费用2+其他费用3) -前次个人待补足 -单位补足扣返
		// -个人代扣-免个税个人代扣 - 企业（职业）年金 - 代扣个人社保 - 代扣个人公积金
		// -个人社保卡费(暂无)
		BigDecimal sum = SalaryConstants.B_ZERO;
		for (TSalaryAccountItem item : saiList) {
			if (SalaryConstants.PERSONAL_SOCIAL_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.PERSONAL_FUND_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.SALARY_TAX_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.ANNUAL_BONUS_TAX_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.RISK_MORTGAGE_MONEY_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.OTHER_MONEY_ONE_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.OTHER_MONEY_TWO_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.OTHER_MONEY_THREE_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.PRE_CURRENT_SUPPLY_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.UNIT_SUPPLY_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.PDEDUCTION_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.EXEMPTION_PERSION_TAX_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.ENTERPRISE_ANNUITY_JAVA.equals(item.getJavaFiedName())
					|| SalaryConstants.WITHHOLIDING_PERSON_SOCIAL.equals(item.getJavaFiedName())
					|| SalaryConstants.WITHHOLIDING_PERSON_FUND.equals(item.getJavaFiedName())) {
				sum = sum.add(item.getSalaryMoney()).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
			}
		}
		sum = realSalary.subtract(sum).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		if (sum.compareTo(SalaryConstants.B_ZERO) < SalaryConstants.EQUAL) {
			sum = SalaryConstants.B_ZERO;
		}
		a.setActualSalary(sum);
		return sum;
	}

	/**
	 * @param yearFinal 年终奖
	 * @param annousTax 税率
	 * @Description: 计算年终奖个税
	 * @Author: hgw
	 * @Date: 2019/10/8 15:11
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal calculation2FinalSalary(TSalaryAccount a, BigDecimal yearFinal, List<TSalaryTaxConfig> annousTax) {
		//年终奖
		if (yearFinal != null && yearFinal.compareTo(SalaryConstants.B_ZERO) > SalaryConstants.EQUAL
				&& annousTax != null && annousTax.size() > CommonConstants.ZERO_INT) {
			BigDecimal month = yearFinal.divide(SalaryConstants.B_TWELVE, SalaryConstants.TAX_FEE_PLACES, BigDecimal.ROUND_HALF_UP);
			// 应纳税额
			BigDecimal annualBonusTax;
			for (TSalaryTaxConfig sub : annousTax) {
				if (month.compareTo(sub.getMinIncome()) > SalaryConstants.EQUAL
						&& month.compareTo(sub.getMaxIncome()) <= SalaryConstants.EQUAL) {
					annualBonusTax = yearFinal.multiply(new BigDecimal(sub.getWithholdingRate()).divide(
									SalaryConstants.B_ONEHUNDRED, SalaryConstants.TAX_FEE_PLACES, BigDecimal.ROUND_HALF_UP))
							.subtract(sub.getQuickDeducation());
					a.setAnnualBonusTax(annualBonusTax);
					return annualBonusTax;
				}
			}
		}
		return SalaryConstants.B_ZERO;
	}

	/**
	 * @param saiList  报账明细list
	 * @param cnName   中文名-表头名
	 * @param javaName 属性
	 * @param money    金额
	 * @param isTax    是否进行计算扣税：1：计算；0：不计算
	 * @Description: 保存报账明细
	 * @Author: hgw
	 * @Date: 2019/9/30 17:02
	 * @return: java.math.BigDecimal - 报账明细金额
	 **/
	private BigDecimal saveNewItems(List<TSalaryAccountItem> saiList,
									String cnName, String javaName, BigDecimal money, Integer isTax) {
		TSalaryAccountItem sai = new TSalaryAccountItem();
		sai.setCnName(cnName);
		sai.setJavaFiedName(javaName);
		if (money == null) {
			money = new BigDecimal("0");
		}
		sai.setSalaryMoney(money);
		if (isTax != null) {
			sai.setIsTax(isTax);
		} else {
			sai.setIsTax(CommonConstants.ZERO_INT);
		}
		saiList.add(sai);
		return money;
	}

	/**
	 * @param estmateList 预估库数据列表
	 * @param a ：    身份证
	 * @param isSocial    true:社保 false:公积金
	 * @param isPerson    true:个人 false:单位
	 * @param socialList  预估库id,社保list
	 * @param fundList    预估库id,公积金list
	 * @Description: 获取预估库-金额
	 * @Author: hgw
	 * @Date: 2019/9/26 15:38
	 * @return: java.math.BigDecimal
	 **/
	public BigDecimal getSocialOrFundMoneyForForecast(String socialFundType, TSettleDomain dept, TSalaryAccount a
			, List<TPaymentBySalaryVo> estmateList, List<TPaymentBySalaryVo> forecastList, boolean isSocial, boolean isPerson
			, Set<String> socialList, Set<String> fundList, Set<String> forecastSocialList, Set<String> forecastFundList) {
		BigDecimal money = SalaryConstants.B_ZERO;
		BigDecimal sub = SalaryConstants.B_ZERO;
		if (isSocial && dept.getUnitSeriousIllnessProp() != null
				&& dept.getUnitSeriousIllnessProp().compareTo(SalaryConstants.B_ONEHUNDRED) < SalaryConstants.EQUAL) {
			sub = (new BigDecimal("100").subtract(dept.getUnitSeriousIllnessProp()))
					.divide(SalaryConstants.B_ONEHUNDRED, SalaryConstants.PLACES, BigDecimal.ROUND_HALF_UP);
		}
		if (CommonConstants.ZERO_STRING.equals(socialFundType) && estmateList != null && !estmateList.isEmpty()) {
			money = this.getSocialFundMoney(a, estmateList, isSocial, isPerson, socialList, fundList, money, sub);
		}
		// 缴费库没找到，从预估库找
		if (CommonConstants.ONE_STRING.equals(socialFundType) && forecastList != null && !forecastList.isEmpty()) {
			money = this.getSocialFundMoney(a, forecastList, isSocial, isPerson, forecastSocialList, forecastFundList, money, sub);
		}
		return money;
	}

	/**
	 * @Description: 按类型拉取社保公积金
	 * @Author: hgw
	 * @Date: 2022/8/17 11:38
	 * @return: java.math.BigDecimal
	 **/
	private BigDecimal getSocialFundMoney(TSalaryAccount a, List<TPaymentBySalaryVo> estmateList, boolean isSocial
			, boolean isPerson, Set<String> socialList, Set<String> fundList, BigDecimal money, BigDecimal sub) {
		money = money.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		for (TPaymentBySalaryVo m : estmateList) {
			if (Common.isNotNull(a.getEmpIdcard()) && a.getEmpIdcard().equals(m.getEmpIdcard())) {
				//社保
				if (isSocial && (!Common.isNotNull(m.getSalarySocialFlag()) || CommonConstants.ZERO_STRING.equals(m.getSalarySocialFlag()))
						&& (m.getPersonalSocialSum() != null || m.getUnitSocialSum() != null)) {
					if (isPerson && m.getPersonalSocialSum() != null) {
						money = money.add(m.getPersonalSocialSum());
						if (sub.compareTo(SalaryConstants.B_ZERO) != SalaryConstants.EQUAL
								&& m.getUnitBitmailmentFee() != null) {
							money = money.add(m.getUnitBitmailmentFee().multiply(sub));
						}
						a.setPersonSocial(money);
					}
					if (!isPerson && m.getUnitSocialSum() != null) {
						money = money.add(m.getUnitSocialSum());
						if (sub.compareTo(SalaryConstants.B_ZERO) != SalaryConstants.EQUAL
								&& m.getUnitBitmailmentFee() != null) {
							money = money.subtract(m.getUnitBitmailmentFee().multiply(sub));
						}
						a.setUnitSocial(money);
					}
					socialList.add(m.getId());
				}
				//公积金
				if (!isSocial && (!Common.isNotNull(m.getSalaryFundFlag()) || CommonConstants.ZERO_STRING.equals(m.getSalaryFundFlag()))
						&& (m.getPersonalFundSum() != null || m.getUnitFundSum() != null)) {
					if (isPerson && m.getPersonalFundSum() != null) {
						money = money.add(m.getPersonalFundSum());
						a.setPersonFund(money);
					}
					if (!isPerson && m.getUnitFundSum() != null) {
						money = money.add(m.getUnitFundSum());
						a.setUnitFund(money);
					}
					fundList.add(m.getId());
				}
			}
		}
		return money;
	}

	/**
	 * @param isActual            false：有应发顺推；true：有实发，倒推应发
	 * @param itemList            本次报账金额
	 * @param itemHistoryList     历史报账金额
	 * @param specialDeductionSum 专项信息
	 * @param costReduction       减除费用
	 * @param subs                薪资扣税阶梯表list
	 * @Description: 计算薪资扣税-个税
	 * @Author: hgw
	 * @Date: 2019/10/8 18:34
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal calculation2PersonSalary(boolean isActual, List<TSalaryAccountItem> itemList
			, List<TSalaryAccountItem> itemHistoryList, BigDecimal specialDeductionSum
			, BigDecimal costReduction, List<TSalaryTaxConfig> subs, List<TSalaryTaxConfig> actualTax
			, List<TSalaryAccountItem> saiList, TSalaryAccount a) {
		//本次纳税额
		BigDecimal res = SalaryConstants.B_ZERO;
		BigDecimal sumTax = SalaryConstants.B_ZERO;

		// 实发倒推-属性：
		BigDecimal actualSalaryNow = SalaryConstants.B_ZERO;  // 本次实发
		BigDecimal actualSalary = SalaryConstants.B_ZERO;  // 实发
		BigDecimal annualBonus = SalaryConstants.B_ZERO; // -单独年终奖
		BigDecimal annualBonusTax = SalaryConstants.B_ZERO; // -单独年终奖税
		BigDecimal deduction = SalaryConstants.B_ZERO; // +个人代扣
		BigDecimal phoneSubsidy = SalaryConstants.B_ZERO; // -通讯补贴（不计税）
		BigDecimal otherDeduction = SalaryConstants.B_ZERO; // -其他扣除项，包含【累计个人社保（含代扣，含本期）+累计个人公积金（含代扣）
		// +累计年金（个人含本期）+累计个人代扣(各类个人代扣费用，含本期)+免个税个人代扣（含本期）】
		// - costReduction - specialDeductionSum
		BigDecimal relaySalaryHistory = SalaryConstants.B_ZERO; // 历史应发
		BigDecimal taxHistory = SalaryConstants.B_ZERO;  // 历史个税
		//本次
		for (TSalaryAccountItem item : itemList) {
			if (CommonConstants.ONE_STRING.equals(a.getAnnualBonusType())) {
				if (SalaryConstants.ANNUAL_BONUS_JAVA.equals(item.getJavaFiedName())) {
					annualBonus = annualBonus.add(item.getSalaryMoney());
				}
				if (SalaryConstants.ANNUAL_BONUS_TAX_JAVA.equals(item.getJavaFiedName())) {
					annualBonusTax = annualBonusTax.add(item.getSalaryMoney());
				}
			}
			if (SalaryConstants.RELAY_SALARY_JAVA.equals(item.getJavaFiedName())) {
				res = res.add(item.getSalaryMoney());
			}
			if (SalaryConstants.PDEDUCTION_JAVA.equals(item.getJavaFiedName())) {
				deduction = deduction.add(item.getSalaryMoney());
				otherDeduction = otherDeduction.add(item.getSalaryMoney());
			}
			if (SalaryConstants.PHONE_SUBSIDY_JAVA.equals(item.getJavaFiedName())) {
				phoneSubsidy = phoneSubsidy.add(item.getSalaryMoney());
			}
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalary = actualSalary.add(item.getSalaryMoney());
				actualSalaryNow = actualSalaryNow.add(item.getSalaryMoney());
			}
			if (CommonConstants.ONE_INT == item.getIsTax()) {
				res = res.subtract(item.getSalaryMoney());
			}
			otherDeduction = getOtherDeducation(otherDeduction, item);
		}
		//历史累计
		for (TSalaryAccountItem item : itemHistoryList) {
			if (CommonConstants.ONE_STRING.equals(item.getAnnualBonusType())) {
				if (SalaryConstants.ANNUAL_BONUS_JAVA.equals(item.getJavaFiedName())) {
					annualBonus = annualBonus.add(item.getSalaryMoney());
				}
				if (SalaryConstants.ANNUAL_BONUS_TAX_JAVA.equals(item.getJavaFiedName())) {
					annualBonusTax = annualBonusTax.add(item.getSalaryMoney());
				}
			}
			if (SalaryConstants.SALARY_TAX_JAVA.equals(item.getJavaFiedName())) {
				sumTax = sumTax.add(item.getSalaryMoney());
				taxHistory = taxHistory.add(item.getSalaryMoney());
			}
			if (SalaryConstants.RELAY_SALARY_JAVA.equals(item.getJavaFiedName())) {
				res = res.add(item.getSalaryMoney());
				relaySalaryHistory = relaySalaryHistory.add(item.getSalaryMoney());
			}
			if (SalaryConstants.PHONE_SUBSIDY_JAVA.equals(item.getJavaFiedName())) {
				phoneSubsidy = phoneSubsidy.add(item.getSalaryMoney());
			}
			if (SalaryConstants.PDEDUCTION_JAVA.equals(item.getJavaFiedName())) {
				deduction = deduction.add(item.getSalaryMoney());
				otherDeduction = otherDeduction.add(item.getSalaryMoney());
			}
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalary = actualSalary.add(item.getSalaryMoney());
			}
			if (CommonConstants.ONE_INT == item.getIsTax()) {
				res = res.subtract(item.getSalaryMoney());
			}
			otherDeduction = getOtherDeducation(otherDeduction, item);
		}
		if (specialDeductionSum != null) {
			res = res.subtract(specialDeductionSum);
		}
		if (costReduction != null) {
			res = res.subtract(costReduction);
		}
		if (!isActual) {
			for (TSalaryTaxConfig sub : subs) {
				if (res.compareTo(sub.getMinIncome()) > SalaryConstants.EQUAL
						&& res.compareTo(sub.getMaxIncome()) <= SalaryConstants.EQUAL) {
					//res = realDeduSalary * ((double) ((sub.getTaxRate() * 1.0) / 100)) - sumTax - sub.getQuick()
					res = res.multiply(new BigDecimal(sub.getWithholdingRate()).divide(
									SalaryConstants.B_ONEHUNDRED, SalaryConstants.PLACES, BigDecimal.ROUND_HALF_UP))
							.subtract(sumTax).subtract(sub.getQuickDeducation());// 应纳税额
					break;
				}
			}
		} else {
			// -实发倒推应发改版-2023-5-16 10:51:31-版本MVP1.5.4-王成提供的新倒推公式
			// 1 数据处理：报账明细中若存在“年终奖单独扣税”不为0的行时，在进行本公式计算时，应将年终奖金额从应发和实发中分别扣除后，再参与计算

			// 2 计算税率档（税率、速算扣除数）=(累计实发金额(去掉年终奖单独扣税的部分实发，含本期)+个人代扣(各类个人代扣费用,不包含免个税个人代扣，含本期)
			// -通讯补贴（不计税）-费用扣除标准（本期）-专项附加扣除（含本期）)

			// 税率档
			BigDecimal areaMoney = actualSalary.subtract(annualBonus).add(deduction).subtract(phoneSubsidy).add(annualBonusTax);
			if (costReduction != null) {
				areaMoney = areaMoney.subtract(costReduction);
			}
			if (specialDeductionSum != null) {
				areaMoney = areaMoney.subtract(specialDeductionSum);
			}
			// 应缴税所得额
			BigDecimal doTaxMoney = BigDecimal.ZERO;
			for (TSalaryTaxConfig sub : actualTax) {
				if (areaMoney.compareTo(sub.getMinIncome()) > SalaryConstants.EQUAL
						&& areaMoney.compareTo(sub.getMaxIncome()) <= SalaryConstants.EQUAL) {
					// 3 计算应缴税所得额（参与计税的金额）＝ （税率档位－速算扣除数）/（1—税率）
					doTaxMoney = (areaMoney.subtract(sub.getQuickDeducation())).divide(SalaryConstants.B_ONEHUNDRED
							.subtract(new BigDecimal(sub.getWithholdingRate())).divide(
							SalaryConstants.B_ONEHUNDRED, SalaryConstants.PLACES, BigDecimal.ROUND_HALF_UP)
							, SalaryConstants.PLACES, BigDecimal.ROUND_HALF_UP);
					break;
				}
			}
			// 累计个税
			BigDecimal taxAll = BigDecimal.ZERO;
			// 4 计算累计个税 =应纳税所得额×适用税率-速算扣除数
			for (TSalaryTaxConfig sub : subs) {
				if (doTaxMoney.compareTo(sub.getMinIncome()) > SalaryConstants.EQUAL
						&& doTaxMoney.compareTo(sub.getMaxIncome()) <= SalaryConstants.EQUAL) {
					taxAll = doTaxMoney.multiply(new BigDecimal(sub.getWithholdingRate()).divide(
							SalaryConstants.B_ONEHUNDRED, SalaryConstants.PLACES, BigDecimal.ROUND_HALF_UP))
							.subtract(sub.getQuickDeducation());// 应纳税额
					break;
				}
			}
			if (taxAll.compareTo(SalaryConstants.B_ZERO) < SalaryConstants.EQUAL) {
				taxAll = BigDecimal.ZERO;
			}
			if (taxAll.compareTo(taxHistory) < SalaryConstants.EQUAL) {
				taxAll = taxHistory;
			}
			// 5 计算应发=累计实发工资（含本期）+累计个税+累计个人社保（含代扣，含本期）+累计个人公积金（含代扣）
			// +累计年金（个人含本期）+累计个人代扣(各类个人代扣费用，含本期)+免个税个人代扣（含本期）-历史累计应发（不含本期）
			// 本次应发
			BigDecimal relaySalaryNow = actualSalary.add(taxAll).add(otherDeduction).subtract(relaySalaryHistory).add(annualBonusTax);
			if (relaySalaryNow.compareTo(actualSalaryNow) <= SalaryConstants.EQUAL) {
				relaySalaryNow = actualSalaryNow;
			}
			res = taxAll.subtract(taxHistory);
			// 本次个人应发合计
			TSalaryAccountItem sai = new TSalaryAccountItem();
			sai.setCnName(SalaryConstants.RELAY_SALARY);
			sai.setJavaFiedName(SalaryConstants.RELAY_SALARY_JAVA);
			sai.setIsTax(CommonConstants.ZERO_INT);
			sai.setSalaryMoney(relaySalaryNow);
			a.setRelaySalary(relaySalaryNow);
			saiList.add(sai);
		}
		if (res.compareTo(SalaryConstants.B_ZERO) < SalaryConstants.EQUAL) {
			return SalaryConstants.B_ZERO;
		}
		res = res.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		a.setSalaryTax(res);
		return res;
	}

	/**
	 * @param otherDeduction
	 * @param item
	 * @Description: 实发倒推应发，获取其他累加项
	 * @Author: hgw
	 * @Date: 2023/5/16 17:09
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal getOtherDeducation(BigDecimal otherDeduction, TSalaryAccountItem item) {
		if (SalaryConstants.WITHHOLIDING_PERSON_SOCIAL.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		if (SalaryConstants.WITHHOLIDING_PERSON_FUND.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		if (SalaryConstants.PERSONAL_SOCIAL_JAVA.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		if (SalaryConstants.PERSONAL_FUND_JAVA.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		// 企业（职业）年金
		if (SalaryConstants.ENTERPRISE_ANNUITY_JAVA.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		// 免个税个人代扣
		if (SalaryConstants.EXEMPTION_PERSION_TAX_JAVA.equals(item.getJavaFiedName())) {
			otherDeduction = otherDeduction.add(item.getSalaryMoney());
		}
		return otherDeduction;
	}


	/**
	 * @param itemList
	 * @param itemHistoryList
	 * @param saiList
	 * @Description: 计算劳务费个税、应发
	 * @Author: hgw
	 * @Date: 2022/3/3 11:30
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal calculation2Labor(List<TSalaryAccountItem> itemList
			, List<TSalaryAccountItem> itemHistoryList, List<TSalaryAccountItem> saiList) {
		// B7 = 当月实发合计
		// 税=ROUND(IF(B7<=800,0,IF(B7<=3360,(B7-800)/4,IF(B7<=21000,0.16*B7/0.84,IF(B7<=49500,(0.24*B7-2000)/0.76,(0.32*B7-7000)/0.68)))),2)
		// 本次实发
		BigDecimal actualSalarySumNow = BigDecimal.ZERO;
		// 当月实发合计
		BigDecimal actualSalarySum = BigDecimal.ZERO;
		// 历史个税合计
		BigDecimal sumTax = BigDecimal.ZERO;
		// 本次实发
		for (TSalaryAccountItem item : itemList) {
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalarySum = actualSalarySum.add(item.getSalaryMoney());
				actualSalarySumNow = actualSalarySumNow.add(item.getSalaryMoney());
			}
		}
		// 历史实发、个税
		for (TSalaryAccountItem item : itemHistoryList) {
			if (SalaryConstants.SALARY_TAX_JAVA.equals(item.getJavaFiedName())) {
				sumTax = sumTax.add(item.getSalaryMoney());
			}
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalarySum = actualSalarySum.add(item.getSalaryMoney());
			}
		}
		BigDecimal nowTax;
		// 2022-3-3 11:24:20 运营中心郭华照提供的公式：
		// ROUND(IF(B7<=800,0,IF(B7<=3360,(B7-800)/4,IF(B7<=21000,0.16*B7/0.84,IF(B7<=49500,(0.24*B7-2000)/0.76,(0.32*B7-7000)/0.68)))),2)
		if (actualSalarySum.compareTo(new BigDecimal("800")) <= 0) {
			nowTax = BigDecimal.ZERO;
		} else if (actualSalarySum.compareTo(new BigDecimal("3360")) <= 0) {
			// (B7-800)/4
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(actualSalarySum, new BigDecimal("800"))
					, new BigDecimal("4"));
		} else if (actualSalarySum.compareTo(new BigDecimal("21000")) <= 0) {
			// 0.16*B7/0.84
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.16"))
					, new BigDecimal("0.84"));
		} else if (actualSalarySum.compareTo(new BigDecimal("49500")) <= 0) {
			// (0.24*B7-2000)/0.76
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(
							BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.24")), new BigDecimal("2000"))
					, new BigDecimal("0.76"));
		} else {
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(
							BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.32")), new BigDecimal("7000"))
					, new BigDecimal("0.68"));
		}
		nowTax = nowTax.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		if (sumTax.compareTo(BigDecimal.ZERO) != 0) {
			nowTax = BigDecimalUtils.safeSubtract(nowTax, sumTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		}

		BigDecimal relaySalary = BigDecimalUtils.safeAdd(actualSalarySumNow, nowTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		// 本次个人应发合计
		TSalaryAccountItem sai = new TSalaryAccountItem();
		sai.setCnName(SalaryConstants.RELAY_SALARY);
		sai.setJavaFiedName(SalaryConstants.RELAY_SALARY_JAVA);
		sai.setIsTax(CommonConstants.ZERO_INT);
		sai.setSalaryMoney(relaySalary);
		saiList.add(sai);
		return nowTax;
	}

	/**
	 * 比较与薪资合并扣税和单独扣税的结果
	 *
	 * @return 1: 单独  0: 合并
	 * @createDate 2020-4-22 18:59:02
	 * @author hgw
	 */
	public static String checkYearFinalStyle(boolean isActual, List<TSalaryAccountItem> asList, BigDecimal sdSum
			, BigDecimal costReduction, List<TSalaryTaxConfig> personTax, List<TSalaryTaxConfig> actualTax
			, List<TSalaryAccountItem> saiList, BigDecimal annualBonus
			, List<TSalaryTaxConfig> annousTax, TSalaryAccount a) {
		BigDecimal finalSalaryWithSalary = calculation2PersonSalary(isActual, saiList, asList, sdSum
				, costReduction, personTax, actualTax, saiList, a);
		BigDecimal finalSalaryNoSalary = calculation2FinalSalary(a, annualBonus, annousTax);
		if (finalSalaryWithSalary.compareTo(finalSalaryNoSalary) > SalaryConstants.EQUAL) {
			return "1";
		}
		return "0";
	}

	/**
	 * @param salaryFormId 工资表id
	 * @Description: 获取结算单
	 * @Author: hgw
	 * @Date: 2019/9/9 17:49
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	@Override
	public R<TSalaryDetailVo> getBill(String salaryFormId) {
		//工资主表
		TSalaryStandard salary = tSalaryStandardService.getById(salaryFormId);
		TSalaryDetailVo salaryDetailVo = new TSalaryDetailVo();
		if (salary != null) {
			List<TSalaryAtta> attaList = null;
			if (salary.getType() == null || salary.getType() != CommonConstants.ONE_INT) {
				//报账表
				TSalaryAccountSearchVo salaryAccount = new TSalaryAccountSearchVo();
				salaryAccount.setSalaryFormId(salaryFormId);
				salaryAccount.setSalaryMonthStart(salary.getSalaryMonth());
				List<TSalaryAccount> salaryAccountList = tSalaryAccountService.getAccountListBySalaryId(salaryAccount);
				//报账表明细
				if (salaryAccountList != null && salaryAccountList.size() > CommonConstants.ZERO_INT) {
					TSalaryAccountItem item;
					List<TSalaryAccountItem> itemList;
					for (TSalaryAccount a : salaryAccountList) {
						item = new TSalaryAccountItem();
						item.setSalaryAccountId(a.getId());
						item.setSalaryMonth(salary.getSalaryMonth());
						itemList = tSalaryAccountItemService.getTSalaryAccountItemNoPage(item);
						a.setSaiList(itemList);
					}
				}
				salaryDetailVo.setSalaryAccountList(salaryAccountList);
				attaList = tSalaryAttaService.getAttaListHaveSrc(salary.getId(), 230);

				List<TSalaryStandardIssueRes> resList = tSalaryStandardIssueResService.list(
						Wrappers.<TSalaryStandardIssueRes>query().lambda().eq(TSalaryStandardIssueRes::getSalaryId, salary.getId()));
				salaryDetailVo.setResList(resList);

				salaryDetailVo.setSalarySum(tSalaryAccountService.getAccountSumBySalaryId(salaryFormId));
			}
			salaryDetailVo.setAttaList(attaList);
			salaryDetailVo.setAuditLogList(auditLogService.list(Wrappers.<TApprovalRecord>query().lambda().eq(TApprovalRecord::getSalaryId, salary.getId())));
		}
		//结算单
		salaryDetailVo.setSalary(salary);
		return new R<>(salaryDetailVo);
	}

	/**
	 * @param savList 报账表Vo
	 * @param vo
	 * @Description: 保存并提交
	 * @Author: huyc
	 * @Date: 2022/8/16
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	public R saveLaborSubmit(TConfigSalary configSalary, List<TSalaryAccountVo> savList, SalaryUploadParamVo vo
			, TSettleDomainSelectVo dept) {
		String orderId = vo.getOrderId();
		String salaryType = vo.getSalaryType();
		String newEmpUpdateFlag = vo.getNewEmpUpdateFlag();
		if (Common.isNotNull(savList) && !savList.isEmpty()) {
			TSalaryAccountVo salaryAccountVo = savList.get(0);
			List<TSalaryAccountItem> saiList = null;  //报账明细List
			YifuUser user = SecurityUtils.getUser();
			TSalaryStandard salary;
			LocalDateTime nowTime = LocalDateTime.now();
			//工资主表
			String invoiceTitle = dept.getBusinessSubjectName();
			R<TSalaryStandard> sr = this.saveNewTSalary(configSalary, salaryAccountVo, dept, user, nowTime, invoiceTitle
					, newEmpUpdateFlag);

			if (sr == null || sr.getCode() == CommonConstants.FAIL) {
				return sr;
			} else {
				salary = sr.getData();
			}

			if (salary != null) {
				// 复制EKP订单ID 20220831 fxj
				salary.setOrderId(orderId);
				// 薪资导入、删除前加锁：
				TSalaryLock lock = salaryLockService.lambdaQuery()
						.eq(TSalaryLock::getDeptId, dept.getId())
						.eq(TSalaryLock::getDeleteFlag, CommonConstants.ZERO_INT)
						.last("limit 1").one();
				if (lock != null && Common.isNotNull(lock.getId())) {
					return R.failed("当前结算主体已被用户锁定，请稍等！超过10分钟还没释放，请联系管理员！当前时间：" + nowTime);
				} else {
					lock = new TSalaryLock();
					lock.setCreateTime(nowTime);
					lock.setDeleteFlag(CommonConstants.ZERO_INT);
					lock.setDeptId(dept.getId());
					lock.setDeptName(dept.getDepartName());
					lock.setSettleMonth(salaryAccountVo.getSettlementMonth());
					lock.setType(CommonConstants.ZERO_INT);
					salaryLockService.save(lock);
					TSalaryLock lockUpdate;
					try {
						// 薪资核心导入代码
						if (CommonConstants.THREE_STRING.equals(salaryType)) {
							return this.doLaborCoreSalary(savList, saiList, dept, salary, user);
						} else {
							return this.doRemuCoreSalary(savList, saiList, dept, salary, user);
						}
					} catch (Exception e) {
						lockUpdate = new TSalaryLock();
						lockUpdate.setId(lock.getId());
						lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
						salaryLockService.updateById(lockUpdate);
						throw new RuntimeException(e.getMessage() == null ? "薪资导入失败！" : e.getMessage());
					} finally {
						lockUpdate = new TSalaryLock();
						lockUpdate.setId(lock.getId());
						lockUpdate.setDeleteFlag(CommonConstants.ONE_INT);
						if (Common.isNotNull(salary.getId())) {
							lockUpdate.setSalaryId(salary.getId());
							lockUpdate.setSettleMoney(salary.getSettlementAmount());
						}
						salaryLockService.updateById(lockUpdate);
					}
				}
			} else {
				return R.failed("新建工资主表失败");
			}
		}
		return R.failed("提交的数据不可为空");
	}

	/**
	 * @Description: 劳务费导入
	 * @Author: huyc
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	public R doLaborCoreSalary(List<TSalaryAccountVo> savList, List<TSalaryAccountItem> saiList,
							   TSettleDomainSelectVo dept, TSalaryStandard salary, YifuUser user) {
		List<TSalaryAccount> aList = new ArrayList<>();
		TSalaryAccount a;//定库：
		BigDecimal relaySalarySum = BigDecimal.ZERO;  //工资应发
		int size = savList.size();
		// 自有员工人数
		int ownNum = 0;
		// 自有员工应发金额
		BigDecimal ownMoney = BigDecimal.ZERO;

		// 劳务费、稿酬是否含有发薪false：否；true：是
		boolean haveSalaryFlag = false;
		// 是否重复金额false：否；true：是
		boolean repeatFlag = false;

		TSalaryAccountItem sai;
		for (int i = CommonConstants.ZERO_INT; i < size; i++) {
			a = new TSalaryAccount();
			try {
				SalaryAccountUtil.reflectionAttr(savList.get(i), a);
				a.setSalaryMonth(DateUtil.getThisMonth());
				if (!haveSalaryFlag && a.getHaveSalaryFlag() != null && a.getHaveSalaryFlag() == CommonConstants.ONE_INT) {
					haveSalaryFlag = true;
				}
				if (!repeatFlag && a.getIsRepeat() != null && a.getIsRepeat() == CommonConstants.ONE_INT) {
					repeatFlag = true;
				}

				if (savList.get(i).getSaiList() != null && !savList.get(i).getSaiList().isEmpty()) {
					saiList = new ArrayList<>();
					for (int j = 0; j < savList.get(i).getSaiList().size(); j++) {
						sai = new TSalaryAccountItem();
						SalaryAccountUtil.reflectionAttr(savList.get(i).getSaiList().get(j), sai);
						saiList.add(sai);
					}
				}

				// 实发劳务费，按月累计扣税
				this.saveNewItems(saiList, SalaryConstants.SALARY_TAX,
						SalaryConstants.SALARY_TAX_JAVA,
						calculationLabor(saiList, saiList, a), CommonConstants.ZERO_INT);

				// 自有员工以及自有员工应发金额
				if (Common.isNotNull(a.getOwnFlag()) && a.getOwnFlag() == 1) {
					ownNum++;
					ownMoney = ownMoney.add(a.getRelaySalaryUnit());
				}

				a.setSaiList(saiList);
				aList.add(a);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		salary.setOwnNums(ownNum);
		salary.setOwnMoney(ownMoney);

		for (TSalaryAccount account : aList) {
			relaySalarySum = relaySalarySum.add(account.getRelaySalaryUnit());
		}

		TSalaryDetailVo salaryDetailVo = new TSalaryDetailVo();
		salaryDetailVo.setSalaryAccountList(aList);
		salary.setSettlementAmount(relaySalarySum);
		salary.setHaveSalaryFlag(CommonConstants.ZERO_INT);
		salary.setHaveSpecialFlag(CommonConstants.ZERO_INT);
		salary.setIsRepeat(CommonConstants.ZERO_INT);
		salary.setStatus(SalaryConstants.AUDIT_STATUS[0]);
		salary.setSalaryMonth(DateUtil.getThisMonth());
		if (haveSalaryFlag || ownNum > 0 || repeatFlag) {
			if (haveSalaryFlag) {
				salary.setHaveSalaryFlag(CommonConstants.ONE_INT);
			}
			if (repeatFlag) {
				salary.setIsRepeat(CommonConstants.ONE_INT);
			}
		}
		if (Common.isEmpty(salary.getApplyNo())) {
			salary.setApplyNo(this.getCode());
		}
		//保存工资表
		tSalaryStandardService.save(salary);
		TApprovalRecord tApprovalRecord = new TApprovalRecord();
		tApprovalRecord.setApprovalResult(CommonConstants.TWO_STRING);
		tApprovalRecord.setApprovalOpinion("新建表单");
		tApprovalRecord.setSalaryId(salary.getId());
		tApprovalRecord.setNodeId("待提交");
		tApprovalRecord.setApprovalMan(user.getId());
		tApprovalRecord.setApprovalManName(user.getNickname());
		tApprovalRecord.setApprovalTime(DateUtil.getCurrentDateTime());
		auditLogService.save(tApprovalRecord);

		TPauseSalary ps;
		int  i =1;
		BigDecimal money;
		LocalDateTime nowTime = LocalDateTime.now();
		for (TSalaryAccount account : aList) {
			saiList = account.getSaiList();
			account.setSaiList(null);
			account.setOrderId(salary.getOrderId());
			account.setSalaryFormId(salary.getId());
			account.setRowIndex(i);
			i++;
			tSalaryAccountService.save(account);
			money = SalaryConstants.B_ZERO;
			for (TSalaryAccountItem item : saiList) {
				if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
					money = item.getSalaryMoney();
				}
				item.setSalaryAccountId(account.getId());
				tSalaryAccountItemService.save(item);
				// 暂停发
			}
			//暂停发
			if (SalaryConstants.SALARY_GIVE_TIME_VALUE.equals(account.getSalaryGiveTime())) {
				ps = new TPauseSalary();
				ps.setBalance(money);
				ps.setName(account.getEmpName());
				ps.setIdCard(account.getEmpIdcard());
				ps.setBankName(account.getBankName());
				ps.setBankNo(account.getBankNo());
				ps.setCreateTime(nowTime);
				ps.setCreateBy(user.getId());
				ps.setSettleDepartId(dept.getId());
				ps.setSettleDepartNo(dept.getDepartNo());
				ps.setSettleDepartName(dept.getDepartName());
				ps.setSalaryFormId(salary.getId());
				ps.setSalaryAccountId(account.getId());
				ps.setSalaryDate(account.getSalaryMonth());
				ps.setSettleDate(account.getSettlementMonth());
				ps.setType(SalaryConstants.PAUSE_TYPE[0]);
				tPauseSalaryService.save(ps);
			}
		}

		// 获取上一个工资条顺序，复制：
		tSalaryStandardSetService.copyLastSetByDeptId(salary.getId(), dept.getId(), String.valueOf(user.getId()));

		salaryDetailVo.setSalary(salary);

		return R.ok(salaryDetailVo);
	}

	/**
	 * @param itemList
	 * @param saiList
	 * @Description: 计算劳务费个税、应发
	 * @Author: hgw
	 * @Date: 2022/3/3 11:30
	 * @return: java.math.BigDecimal
	 **/
	private BigDecimal calculationLabor(List<TSalaryAccountItem> itemList,List<TSalaryAccountItem> saiList, TSalaryAccount a) {
		// B7 = 当月实发合计
		// 税=ROUND(IF(B7<=800,0,IF(B7<=3360,(B7-800)/4,IF(B7<=21000,0.16*B7/0.84,IF(B7<=49500,(0.24*B7-2000)/0.76,(0.32*B7-7000)/0.68)))),2)
		// 本次实发
		BigDecimal actualSalarySumNow = BigDecimal.ZERO;
		// 当月累计应发合计
		BigDecimal actualSalarySumT;
		// 当月实发合计
		BigDecimal actualSalarySum = BigDecimal.ZERO;
		// 个人承担部分历史个税合计
		BigDecimal sumOtherTax = BigDecimal.ZERO;
		// 历史应发合计
		BigDecimal sumSalaryTax = BigDecimal.ZERO;

		List<TSalaryAccount> list = tSalaryAccountService.list(Wrappers.<TSalaryAccount>query().lambda()
				.eq(TSalaryAccount::getEmpIdcard,a.getEmpIdcard())
				.eq(TSalaryAccount::getFormType,CommonConstants.THREE_STRING)
				.eq(TSalaryAccount::getSalaryMonth,a.getSalaryMonth())
				.eq(TSalaryAccount::getInvoiceTitle,a.getInvoiceTitle())
				.eq(TSalaryAccount::getDeleteFlag,CommonConstants.ZERO_INT));

		// 本次实发
		for (TSalaryAccountItem item : itemList) {
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalarySum = actualSalarySum.add(item.getSalaryMoney());
				actualSalarySumNow = actualSalarySumNow.add(item.getSalaryMoney());
			}
		}
		for (TSalaryAccount account: list) {
			sumOtherTax = sumOtherTax.add(BigDecimalUtils.safeAdd(account.getSalaryTax(),account.getSalaryTaxUnit()));
			sumSalaryTax = sumSalaryTax.add(account.getRelaySalaryUnit());
			actualSalarySum = actualSalarySum.add(account.getRelaySalary());
		}
		//个人承担部分税费
		BigDecimal nowTaxT;
		//个人不承担部分税费
		BigDecimal nowTaxY;
		BigDecimal relaySalary;
		BigDecimal salaryTax = BigDecimal.ZERO;
		// 1个人承担部分
		if (SalaryConstants.IS_PERSON_TAX_ARR[1].equals(a.getIsPersonTax())) {
			nowTaxT = getNowTax(actualSalarySumNow);
			if (sumSalaryTax.compareTo(BigDecimal.ZERO) != 0) {
				//计算本月应发合计
				actualSalarySumT = BigDecimalUtils.safeAdd(nowTaxT, sumSalaryTax, actualSalarySumNow).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
				//累计税费
				nowTaxY = getNowTaxNew(actualSalarySumT);
				if (sumOtherTax.compareTo(BigDecimal.ZERO) != 0) {
					nowTaxY = BigDecimalUtils.safeSubtract(false,nowTaxY, sumOtherTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
				}
				salaryTax = BigDecimalUtils.safeSubtract(false,nowTaxY, nowTaxT);
			} else {
				nowTaxY = nowTaxT;
			}
			//公司应发
			relaySalary = BigDecimalUtils.safeAdd(actualSalarySumNow, nowTaxT).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);

			a.setSalaryTax(salaryTax);
			a.setSalaryTaxUnit(nowTaxT);
			a.setActualSalary(BigDecimalUtils.safeSubtract(false,actualSalarySumNow, salaryTax));
		} else if (SalaryConstants.IS_PERSON_TAX_ARR[0].equals(a.getIsPersonTax())) {
			// 0公司承担全部
			nowTaxY = getNowTax(actualSalarySum);
			a.setActualSalary(actualSalarySumNow);
			if (sumOtherTax.compareTo(BigDecimal.ZERO) != 0) {
				//历史应发税费
				nowTaxY = BigDecimalUtils.safeSubtract(false,nowTaxY, sumOtherTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
			}
			a.setSalaryTaxUnit(nowTaxY);
			relaySalary = BigDecimalUtils.safeAdd(actualSalarySumNow, nowTaxY).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		} else {
			// 2个人承担全部
			//个人承担全部税费，实发要变为应发，推算出实发、个税
			nowTaxY = getNowTaxNew(BigDecimalUtils.safeAdd(actualSalarySumNow, sumSalaryTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP));
			if (sumOtherTax.compareTo(BigDecimal.ZERO) != 0) {
				//历史应发税费
				nowTaxY = BigDecimalUtils.safeSubtract(false,nowTaxY, sumOtherTax).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
			}
			//公司应发和个人实收
			relaySalary = actualSalarySumNow;
			a.setActualSalary(BigDecimalUtils.safeSubtract(false,actualSalarySumNow, nowTaxY).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP));
			a.setSalaryTax(nowTaxY);
		}
		a.setRelaySalaryUnit(relaySalary);
		a.setRelaySalary(actualSalarySumNow);
		// 本次个人应发合计
		TSalaryAccountItem sai = new TSalaryAccountItem();
		sai.setCnName(SalaryConstants.RELAY_SALARY);
		sai.setJavaFiedName(SalaryConstants.RELAY_SALARY_JAVA);
		sai.setIsTax(CommonConstants.ZERO_INT);
		sai.setSalaryMoney(relaySalary);
		saiList.add(sai);
		return nowTaxY;
	}

	public static BigDecimal getNowTax(BigDecimal actualSalarySum) {
		BigDecimal nowTax;
		// 2022-3-3 11:24:20 运营中心郭华照提供的公式：
		// ROUND(IF(B7<=800,0,IF(B7<=3360,(B7-800)/4,IF(B7<=21000,0.16*B7/0.84,IF(B7<=49500,(0.24*B7-2000)/0.76,(0.32*B7-7000)/0.68)))),2)
		if (actualSalarySum.compareTo(new BigDecimal("800")) <= 0) {
			nowTax = BigDecimal.ZERO;
		} else if (actualSalarySum.compareTo(new BigDecimal("3360")) <= 0) {
			// (B7-800)/4
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(actualSalarySum, new BigDecimal("800"))
					, new BigDecimal("4"));
		} else if (actualSalarySum.compareTo(new BigDecimal("21000")) <= 0) {
			// 0.16*B7/0.84
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.16"))
					, new BigDecimal("0.84"));
		} else if (actualSalarySum.compareTo(new BigDecimal("49500")) <= 0) {
			// (0.24*B7-2000)/0.76
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(
							BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.24")), new BigDecimal("2000"))
					, new BigDecimal("0.76"));
		} else {
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(
							BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.32")), new BigDecimal("7000"))
					, new BigDecimal("0.68"));
		}
		nowTax = nowTax.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		return nowTax;
	}

	public static BigDecimal getNowTaxNew(BigDecimal actualSalarySum) {
		BigDecimal nowTax;
		if (actualSalarySum.compareTo(new BigDecimal("800")) <= 0) {
			nowTax = BigDecimal.ZERO;
		} else if (actualSalarySum.compareTo(new BigDecimal("4000")) < 0) {
			// (B7-800)/4
			nowTax = BigDecimalUtils.safeDivide(BigDecimalUtils.safeSubtract(actualSalarySum, new BigDecimal("800"))
					, new BigDecimal("5"));
		} else if (actualSalarySum.compareTo(new BigDecimal("25000")) <= 0) {
			// 0.16*B7/0.84
			nowTax = BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.16"));
		} else if (actualSalarySum.compareTo(new BigDecimal("62500")) <= 0) {
			// (0.24*B7-2000)/0.76
			nowTax = BigDecimalUtils.safeSubtract(BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.24"))
					, new BigDecimal("2000"));
		} else {
			nowTax = BigDecimalUtils.safeSubtract(BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.32"))
					, new BigDecimal("7000"));
		}
		nowTax = nowTax.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		return nowTax;
	}

	/**
	 * @Description: 稿酬导入
	 * @Author: huyc
	 * @return: com.yifu.cloud.v1.common.core.util.R
	 **/
	public R doRemuCoreSalary(List<TSalaryAccountVo> savList, List<TSalaryAccountItem> saiList,
							  TSettleDomainSelectVo dept, TSalaryStandard salary, YifuUser user) {
		List<TSalaryAccount> aList = new ArrayList<>();
		TSalaryAccount a;//定库：
		BigDecimal relaySalarySum = BigDecimal.ZERO;  //工资应发
		int size = savList.size();
		// 自有员工人数
		int ownNum = 0;
		// 自有员工应发金额
		BigDecimal ownMoney = BigDecimal.ZERO;
		// 劳务费、稿酬是否含有发薪false：否；true：是
		boolean haveSalaryFlag = false;
		// 是否重复金额false：否；true：是
		boolean repeatFlag = false;

		List<String> idCardList = new ArrayList<>();
		for (TSalaryAccountVo vo : savList) {
			if (Common.isNotNull(vo.getEmpIdcard())) {
				idCardList.add(vo.getEmpIdcard());
			}
		}
		TSalaryAccountItem sai;
		for (int i = CommonConstants.ZERO_INT; i < size; i++) {
			a = new TSalaryAccount();
			// 本次实发
			BigDecimal actualSalarySumNow = BigDecimal.ZERO;
			// 当月实发合计
			BigDecimal actualSalarySum = BigDecimal.ZERO;
			try {
				SalaryAccountUtil.reflectionAttr(savList.get(i), a);
				a.setSalaryMonth(DateUtil.getThisMonth());
				if (!haveSalaryFlag && a.getHaveSalaryFlag() != null && a.getHaveSalaryFlag() == CommonConstants.ONE_INT) {
					haveSalaryFlag = true;
				}
				if (!repeatFlag && a.getIsRepeat() != null && a.getIsRepeat() == CommonConstants.ONE_INT) {
					repeatFlag = true;
				}

				if (savList.get(i).getSaiList() != null && !savList.get(i).getSaiList().isEmpty()) {
					saiList = new ArrayList<>();
					for (int j = 0; j < savList.get(i).getSaiList().size(); j++) {
						sai = new TSalaryAccountItem();
						SalaryAccountUtil.reflectionAttr(savList.get(i).getSaiList().get(j), sai);
						//个人实发合计
						if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(sai.getJavaFiedName())) {
							actualSalarySum = actualSalarySum.add(sai.getSalaryMoney());
							actualSalarySumNow = actualSalarySumNow.add(sai.getSalaryMoney());
						}
						saiList.add(sai);
					}
				}

				// 实发稿酬，按月累计扣税
				this.saveNewItems(saiList, SalaryConstants.SALARY_TAX,
						SalaryConstants.SALARY_TAX_JAVA,
						calculationRemu(saiList, saiList, a), CommonConstants.ZERO_INT);

				// 自有员工以及自有员工应发金额
				if (Common.isNotNull(a.getOwnFlag()) && a.getOwnFlag() == 1) {
					ownNum++;
					ownMoney = ownMoney.add(a.getRelaySalary());
				}
				a.setSaiList(saiList);
				aList.add(a);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		salary.setOwnNums(ownNum);
		salary.setOwnMoney(ownMoney);

		for (TSalaryAccount account : aList) {
			relaySalarySum = relaySalarySum.add(account.getRelaySalary());
		}

		TSalaryDetailVo salaryDetailVo = new TSalaryDetailVo();
		salaryDetailVo.setSalaryAccountList(aList);
		salary.setSettlementAmount(relaySalarySum);
		salary.setHaveSalaryFlag(CommonConstants.ZERO_INT);
		salary.setHaveSpecialFlag(CommonConstants.ZERO_INT);
		salary.setSalaryMonth(DateUtil.getThisMonth());
		salary.setIsRepeat(CommonConstants.ZERO_INT);
		salary.setStatus(SalaryConstants.AUDIT_STATUS[0]);
		if (haveSalaryFlag || ownNum > 0 || repeatFlag) {
			if (haveSalaryFlag) {
				salary.setHaveSalaryFlag(CommonConstants.ONE_INT);
			}
			if (repeatFlag) {
				salary.setIsRepeat(CommonConstants.ONE_INT);
			}
		}
		if (Common.isEmpty(salary.getApplyNo())) {
			salary.setApplyNo(this.getCode());
		}
		//保存工资表
		tSalaryStandardService.save(salary);
		TApprovalRecord tApprovalRecord = new TApprovalRecord();
		tApprovalRecord.setApprovalResult(CommonConstants.TWO_STRING);
		tApprovalRecord.setApprovalOpinion("新建表单");
		tApprovalRecord.setSalaryId(salary.getId());
		tApprovalRecord.setNodeId("待提交");
		tApprovalRecord.setApprovalMan(user.getId());
		tApprovalRecord.setApprovalManName(user.getNickname());
		tApprovalRecord.setApprovalTime(DateUtil.getCurrentDateTime());
		auditLogService.save(tApprovalRecord);

		int  i =1;
		for (TSalaryAccount account : aList) {
			saiList = account.getSaiList();
			account.setSaiList(null);
			account.setOrderId(salary.getOrderId());
			account.setSalaryFormId(salary.getId());
			account.setRowIndex(i);
			tSalaryAccountService.save(account);
			i++;
			for (TSalaryAccountItem item : saiList) {
				item.setSalaryAccountId(account.getId());
				tSalaryAccountItemService.save(item);
			}
		}

		// 获取上一个工资条顺序，复制：
		tSalaryStandardSetService.copyLastSetByDeptId(salary.getId(), dept.getId(), String.valueOf(user.getId()));

		salaryDetailVo.setSalary(salary);

		return R.ok(salaryDetailVo);
	}

	/**
	 * @param itemList
	 * @param saiList
	 * @Description: 计算劳务费个税、应发
	 * @Author: hgw
	 * @Date: 2022/3/3 11:30
	 * @return: java.math.BigDecimal
	 **/
	private static BigDecimal calculationRemu(List<TSalaryAccountItem> itemList, List<TSalaryAccountItem> saiList,
											  TSalaryAccount a) {
		// 本次实发
		BigDecimal actualSalarySumNow = BigDecimal.ZERO;
		// 本次实发
		for (TSalaryAccountItem item : itemList) {
			if (SalaryConstants.ACTUAL_SALARY_SUM_JAVA.equals(item.getJavaFiedName())) {
				actualSalarySumNow = actualSalarySumNow.add(item.getSalaryMoney());
			}
		}
		//个人税费
		BigDecimal nowTaxT = getNowTaxRemu(actualSalarySumNow);
		BigDecimal relaySalary;
		relaySalary = BigDecimalUtils.safeSubtract(actualSalarySumNow, nowTaxT).setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		a.setSalaryTax(nowTaxT);
		a.setActualSalary(relaySalary);
		a.setRelaySalaryUnit(actualSalarySumNow);
		a.setRelaySalary(actualSalarySumNow);
		// 本次个人应发合计
		TSalaryAccountItem sai = new TSalaryAccountItem();
		sai.setCnName(SalaryConstants.RELAY_SALARY);
		sai.setJavaFiedName(SalaryConstants.RELAY_SALARY_JAVA);
		sai.setIsTax(CommonConstants.ZERO_INT);
		sai.setSalaryMoney(actualSalarySumNow);
		saiList.add(sai);
		return nowTaxT;
	}

	public static BigDecimal getNowTaxRemu(BigDecimal actualSalarySum) {
		BigDecimal nowTax;
		if (actualSalarySum.compareTo(new BigDecimal("800")) <= 0) {
			nowTax = BigDecimal.ZERO;
		} else if (actualSalarySum.compareTo(new BigDecimal("4000")) <= 0) {
			//(x-800)*0.14
			nowTax = BigDecimalUtils.safeMultiply(BigDecimalUtils.safeSubtract(actualSalarySum, new BigDecimal("800"))
					, new BigDecimal("0.14"));
		} else {
			//x*0.16*0.7
			nowTax = BigDecimalUtils.safeMultiply(actualSalarySum, new BigDecimal("0.112"));
		}
		nowTax = nowTax.setScale(SalaryConstants.PLACES, RoundingMode.HALF_UP);
		return nowTax;
	}

	public synchronized String getCode() {
		String nowDay = DateUtil.getThisDay();
		int nowNums;
		String empCode = null;
		Cache cache = cacheManager.getCache(CacheConstants.EVERYDAY_SALARY_FORM_CODE);
		if (cache != null) {
			try {
				Object nowNumObj = cache.get(nowDay);
				if (Common.isNotNull(nowNumObj)) {
					SimpleValueWrapper value = (SimpleValueWrapper) nowNumObj;
					nowNums = (Integer) value.get() + 1;
				} else {
					empCode = baseMapper.getMaxSalaryCode();
					nowNums = Integer.parseInt(empCode) + 1;
				}
			} catch (NumberFormatException e) {
				log.error("获取人员合同当日最大编码时出错：" + empCode);
				nowNums = 1;
			}
			cache.put(nowDay, nowNums);
		} else {
			empCode = baseMapper.getMaxSalaryCode();
			nowNums = Integer.parseInt(empCode) + 1;
		}
		return "XC" + nowDay + this.getFourNum(String.valueOf(nowNums));
	}

	private String getFourNum(String nowNums) {
		if (nowNums.length() >= 4) {
			return nowNums.substring(0, 4);
		}
		String[] zeroArr = {"0", "00", "000"};
		int num = 3 - nowNums.length();
		return zeroArr[num] + nowNums;
	}

}

