
package org.sky.scientific.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.sky.core.excel.util.ExcelUtil;
import org.sky.core.log.exception.ServiceException;
import org.sky.core.mp.base.BaseServiceImpl;
import org.sky.core.mp.support.Condition;
import org.sky.core.mp.support.Query;
import org.sky.core.secure.utils.SecureUtil;
import org.sky.core.tool.api.R;
import org.sky.core.tool.utils.*;
import org.sky.scientific.excel.XmCostDetailsExcel;
import org.sky.scientific.mapper.DeductionCostQtMapper;
import org.sky.scientific.mapper.SubjectEnterpriseMapper;
import org.sky.scientific.mapper.XmCostDetailsMapper;
import org.sky.scientific.mapper.XmMapper;
import org.sky.scientific.pojo.dto.XmCostDetailsDTO;
import org.sky.scientific.pojo.entity.DeductionCostQt;
import org.sky.scientific.pojo.entity.SubjectEnterprise;
import org.sky.scientific.pojo.entity.XmCostDetailsEntity;
import org.sky.scientific.pojo.vo.*;
import org.sky.scientific.service.IXmCostDetailsService;
import org.sky.scientific.service.IXmService;
import org.sky.system.feign.ISysClient;
import org.sky.system.pojo.entity.Tenant;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 研发费用支出明细账 服务实现类
 *
 * @author Kd
 * @since 2025-07-30
 */
@Service
@AllArgsConstructor
public class XmCostDetailsServiceImpl extends BaseServiceImpl<XmCostDetailsMapper, XmCostDetailsEntity> implements IXmCostDetailsService {

	private final XmMapper xmMapper;
	private final SubjectEnterpriseMapper subjectEnterpriseMapper;
	private final DeductionCostQtMapper qtMapper;
	private final ISysClient sysClient;
	private final IXmService xmService;

	@Override
	public IPage<XmCostDetailsEntity> selectXmCostDetailsPage(IPage<XmCostDetailsEntity> page, XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		List<XmCostDetailsEntity> list = null;
		if (dto.getYearAndMonth().length() == 6) {
			list = baseMapper.selectPageByYearAndMonth(page, dto);
		} else if (dto.getYearAndMonth().length() == 4) {
			list = baseMapper.selectPageByYear(page, dto);
		} else {
			throw new ServiceException("参数yearAndMonth格式错误，yyyyMM或yyyy");
		}
		return page.setRecords(list);
	}

	@Override
	public boolean submit(XmCostDetailsEntity xmCostDetails) {
		boolean result = false;
		//日期，必须为当月日期
		String judged = DateUtil.judgeDate(xmCostDetails.getRecordDate(), xmCostDetails.getYearAndMonth());
		if (judged != null) {
			throw new ServiceException(judged);
		}
		if (Func.isNull(xmCostDetails.getXmId())) {
			throw new ServiceException("参数xmId不能为空");
		}
		xmService.judgeXmIsOver(xmCostDetails.getXmId(), true);

		if (Func.isEmpty(xmCostDetails.getId())) {
			//新增
			result = this.save(xmCostDetails);
		} else {
			//修改
			result = this.updateById(xmCostDetails);
		}
		return result;
	}

	@Override
	@Transactional
	public boolean physicalDeleteByIds(List<Long> ids) {
		for (Long id : ids) {
			XmCostDetailsEntity entity = baseMapper.selectById(id);
			if (Func.notNull(entity)) {
				xmService.judgeXmIsOver(entity.getXmId(), true);
			}
		}
		return baseMapper.physicalDeleteByIds(ids) > 0;
	}

	@Override
	public boolean importXmCostDetails(MultipartFile file, String yearAndMonth) {
		if (StringUtil.isBlank(yearAndMonth)) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		List<XmCostDetailsExcel> data = ExcelUtil.read(file, 0, 5, XmCostDetailsExcel.class);
		if (CollectionUtil.isEmpty(data)) {
			throw new ServiceException("未能从模板中读取数据，请检查模板格式是否正确");
		}
		List<XmCostDetailsEntity> insertList = new ArrayList<>();

		for (XmCostDetailsExcel excel : data) {
			XmCostDetailsEntity entity = Objects.requireNonNull(BeanUtil.copyProperties(excel, XmCostDetailsEntity.class));

			//日期，必须时当月日期
			String judged = DateUtil.judgeDate(excel.getRecordDate(), yearAndMonth);
			if (judged != null) {
				throw new ServiceException(judged);
			}

			if (Func.isBlank(excel.getXmbh())) {
				throw new ServiceException("序号[" + excel.getSerialNumber() + "]的研发项目编号不能为空");
			}
			if (Func.isBlank(excel.getESubjectCode())) {
				throw new ServiceException("序号[" + excel.getSerialNumber() + "]的企业科目代码不能为空");
			}
			if (Func.isBlank(excel.getESubjectName())) {
				throw new ServiceException("序号[" + excel.getSerialNumber() + "]的企业科目名称不能为空");
			}

			//根据项目名称或编号查询xmId
			Long xmId = xmMapper.getXmIdByXmmcOrXmbh(null, null, excel.getXmbh());
			if (xmId == null) {
				throw new ServiceException("研发项目编号[" + excel.getXmbh() + "]不存在，请检查模板数据");
			}
			xmService.judgeXmIsOver(xmId, true);

			entity.setXmId(xmId);

			//根据企业科目代码查询id
			SubjectEnterprise dbSubject = subjectEnterpriseMapper.selectOne(Wrappers.<SubjectEnterprise>lambdaQuery().eq(SubjectEnterprise::getCode, excel.getESubjectCode()));
			if (Func.isNull(dbSubject)) {
				throw new ServiceException("序号[" + excel.getSerialNumber() + "]的企业科目代码不存在");
			}
			entity.setESubjectId(dbSubject.getId());
			entity.setESubjectCode(dbSubject.getCode());
			entity.setESubjectName(dbSubject.getCode());
			entity.setYearAndMonth(yearAndMonth);
			insertList.add(entity);

			if (insertList.size() % 20 == 0) {
				if (this.saveBatch(insertList)) {
					insertList.clear();
				}
			}
		}

		if (Func.isNotEmpty(insertList)) {
			this.saveBatch(insertList);
		}
		return true;
	}

	@SneakyThrows
	@Override
	public void exportXmCostDetails(HttpServletResponse response, XmCostDetailsDTO dto) {

		List<XmCostDetailsEntity> list = this.selectXmCostDetailsPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), dto).getRecords();
		AtomicInteger index = new AtomicInteger(1);
		list.forEach(temp -> {
			temp.setXh(index.getAndIncrement() + "");
			temp.setRecordDateStr(Func.notNull(temp.getRecordDate()) ? DateUtil.format(temp.getRecordDate(), DateUtil.PATTERN_DATE) : null);
			temp.setCode(temp.getESubjectCode());
			temp.setName(temp.getESubjectName());
		});

		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/研发费用管理/研发支出明细账P098.xls");
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("研发支出明细账.xls", Charsets.UTF_8));
		ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(list, fillConfig, writeSheet);
		Map<String, Object> map = new HashMap<>();
		map.put("total", list.stream().filter(Objects::nonNull).map(XmCostDetailsEntity::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
		String yearAndMonth = dto.getYearAndMonth();

		map.put("yearAndMonth", (yearAndMonth.length() == 6) ? yearAndMonth.substring(0, 4) + "年" + yearAndMonth.substring(4) + "月" : yearAndMonth + "年");
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public List<FinanceCostDetailVO> financeCostDetail(XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		dto.setTenantId(SecureUtil.getTenantId());
		List<FinanceCostDetailVO> list = baseMapper.financeCostDetail(dto);
		for (FinanceCostDetailVO tmp : list) {
			List<FinanceCostItemVO> vos = tmp.getCostList();
			for (FinanceCostItemVO vo : vos) {
				if (Arrays.asList("53010101", "53010201").contains(vo.getL3Code())) {
					//人员人工费用
					vo.setRyrg(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010102", "53010202").contains(vo.getL3Code())) {
					//直接投入费用
					vo.setZjtr(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010103", "53010203").contains(vo.getL3Code())) {
					//折旧费用与长期待摊费用
					vo.setZjfyycqdtfy(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010104", "53010204").contains(vo.getL3Code())) {
					//无形资产摊销费用
					vo.setWxzctx(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010105", "53010205").contains(vo.getL3Code())) {
					//设计费用
					vo.setSjf(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010106", "53010206").contains(vo.getL3Code())) {
					//装备调试费用与试验费用
					vo.setZbtsfyysyfy(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010107", "53010207").contains(vo.getL3Code())) {
					//委托外部研究开发费用
					vo.setWwyf(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010108", "53010208").contains(vo.getL3Code())) {
					//其他费用
					vo.setQtfy(vo.getAmount().doubleValue());
				} else {
					throw new ServiceException("费用归集出错啦");
				}
			}
		}
		return list;
	}

	@SneakyThrows
	@Override
	public void exportFinanceCostDetail(OutputStream os, FinanceCostDetailVO vo, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/会计口径-研发支出辅助明细账.xls");
		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		Map<String, Object> map = new HashMap<>();
		List<JSONObject> results = new ArrayList<>();
		AtomicInteger index = new AtomicInteger(1);

		map.put("xmbh", vo.getXmbh());
		map.put("xmmc", vo.getXmmc());

		List<FinanceCostItemVO> costList = vo.getCostList();
		for (FinanceCostItemVO item : costList) {
			JSONObject obj = new JSONObject();
			obj.put("xh", index.getAndIncrement() + "");
			obj.put("recordDateStr", Func.notNull(item.getRecordDate()) ? DateUtil.format(item.getRecordDate(), DateUtil.PATTERN_DATE) : null);
			obj.put("voucherNumber", item.getVoucherNumber());
			obj.put("digest", item.getDigest());
			obj.put("ryrg", item.getRyrg());
			obj.put("zjtr", item.getZjtr());
			obj.put("zjfyycqdtfy", item.getZjfyycqdtfy());
			obj.put("sjf", item.getSjf());
			obj.put("wxzctx", item.getWxzctx());
			obj.put("zbtsfyysyfy", item.getZbtsfyysyfy());
			obj.put("qtfy", item.getQtfy());
			obj.put("wwyf", item.getWwyf());
			obj.put("amount", item.getAmount());
			obj.put("cashbook", item.getCashbook());
			results.add(obj);
		}

		map.put("ryrgTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getRyrg).sum()));
		map.put("zjtrTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getZjtr).sum()));
		map.put("zjfyycqdtfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getZjfyycqdtfy).sum()));
		map.put("sjfTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getSjf).sum()));
		map.put("wxzctxTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getWxzctx).sum()));
		map.put("zbtsfyysyfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getZbtsfyysyfy).sum()));
		map.put("qtfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getQtfy).sum()));
		map.put("wwyfTotal", BigDecimal.valueOf(costList.stream().mapToDouble(FinanceCostItemVO::getWwyf).sum()));
		map.put("amountTotal", costList.stream().map(FinanceCostItemVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));


		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(results, fillConfig, writeSheet);
		map.put("year", yearAndMonth.substring(0, 4));
		map.put("month", yearAndMonth.substring(4));
		R<Tenant> tenant = sysClient.getTenant(SecureUtil.getTenantId());
		if (tenant.isSuccess()) {
			map.put("enterpriseName", tenant.getData().getTenantName());
		}

		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public IPage<FinanceCostSummary> financeCostSummary(IPage<FinanceCostSummary> page, XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		dto.setTenantId(SecureUtil.getTenantId());

		Query query = new Query();
		query.setCurrent((int) page.getCurrent());
		query.setSize((int) page.getSize());
		IPage<JSONObject> p1 = Condition.getPage(query);
		//设置为会计口径，1：会计口径，2：加计扣除口径，3：高新口径
		dto.setCaliber(1);
		List<JSONObject> tmpList = baseMapper.costSummary(p1, dto);
		page.setTotal(p1.getTotal()).setCurrent(p1.getCurrent()).setSize(p1.getSize());

		List<FinanceCostSummary> summaryList = JSON.parseArray(JSON.toJSONString(tmpList), FinanceCostSummary.class);
		for (FinanceCostSummary summary : summaryList) {

			List<CostItemVO> itemVOS = baseMapper.selectCostItemByCondition(dto.getYearAndMonth(), summary.getXmId());
			for (CostItemVO item : itemVOS) {
				if (Arrays.asList("53010101", "53010201").contains(item.getL3Code())) {
					//人员人工费用
					summary.setRyrgTotal(summary.getRyrgTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010102", "53010202").contains(item.getL3Code())) {
					//直接投入费用
					summary.setZjtrTotal(summary.getZjtrTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010103", "53010203").contains(item.getL3Code())) {
					//折旧费用与长期待摊费用
					summary.setZjfyycqdtfyTotal(summary.getZjfyycqdtfyTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010104", "53010204").contains(item.getL3Code())) {
					//无形资产摊销费用
					summary.setWxzctxTotal(summary.getWxzctxTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010105", "53010205").contains(item.getL3Code())) {
					//设计费用
					summary.setSjfTotal(summary.getSjfTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010106", "53010206").contains(item.getL3Code())) {
					//装备调试费用与试验费用
					summary.setZbtsfyysyfyTotal(summary.getZbtsfyysyfyTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010107", "53010207").contains(item.getL3Code())) {
					//委托外部研究开发费用
					summary.setWwyfTotal(summary.getWwyfTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010108", "53010208").contains(item.getL3Code())) {
					//其他费用
					summary.setQtfyTotal(summary.getQtfyTotal().add(item.getAmount()));
				}
			}
			summary.setTotal(summary.getRyrgTotal().add(summary.getZjtrTotal()).add(summary.getZjfyycqdtfyTotal()).add(summary.getSjfTotal()).add(summary.getWxzctxTotal()).add(summary.getZbtsfyysyfyTotal()).add(summary.getQtfyTotal()).add(summary.getWwyfTotal()));
		}
		return page.setRecords(summaryList);
	}

	@SneakyThrows
	@Override
	public void exportFinanceCostSummary(OutputStream os, List<FinanceCostSummary> list, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/会计口径-研发支出辅助账汇总表.xls");
		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();
		Map<String, Object> map = new HashMap<>();
		AtomicInteger index = new AtomicInteger(1);
		list.forEach(item -> {
			item.setXh(index.getAndIncrement() + "");
		});
		map.put("ryrgTotalSum", list.stream().map(FinanceCostSummary::getRyrgTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zjtrTotalSum", list.stream().map(FinanceCostSummary::getZjtrTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zjfyycqdtfyTotalSum", list.stream().map(FinanceCostSummary::getZjfyycqdtfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("sjfTotalSum", list.stream().map(FinanceCostSummary::getSjfTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("wxzctxTotalSum", list.stream().map(FinanceCostSummary::getWxzctxTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zbtsfyysyfyTotalSum", list.stream().map(FinanceCostSummary::getZbtsfyysyfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("qtfyTotalSum", list.stream().map(FinanceCostSummary::getQtfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("wwyfTotalSum", list.stream().map(FinanceCostSummary::getWwyfTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("totalSum", list.stream().map(FinanceCostSummary::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add));

		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(list, fillConfig, writeSheet);

		map.put("year", yearAndMonth.substring(0, 4));
		map.put("month", yearAndMonth.substring(4));

		R<Tenant> tenant = sysClient.getTenant(SecureUtil.getTenantId());
		if (tenant.isSuccess()) {
			map.put("enterpriseName", tenant.getData().getTenantName());
		}
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public List<HighTechCostDetailVO> highTechCostDetail(XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		dto.setTenantId(SecureUtil.getTenantId());
		List<HighTechCostDetailVO> list = baseMapper.highTechCostDetail(dto);
		for (HighTechCostDetailVO tmp : list) {
			List<HighTechCostItemVO> vos = tmp.getCostList();
			for (HighTechCostItemVO vo : vos) {
				if (vo.getRdSubjectEnable() == 0) {
					//四级科目 不是高新研发费用科目，费用不归集
					continue;
				}
				if (Arrays.asList("53010101", "53010201").contains(vo.getL3Code())) {
					//人员人工费用
					vo.setRyrg(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010102", "53010202").contains(vo.getL3Code())) {
					//直接投入费用
					vo.setZjtr(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010103", "53010203").contains(vo.getL3Code())) {
					//折旧费用与长期待摊费用
					vo.setZjfyycqdtfy(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010104", "53010204").contains(vo.getL3Code())) {
					//无形资产摊销费用
					vo.setWxzctx(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010105", "53010205").contains(vo.getL3Code())) {
					//设计费用
					vo.setSjf(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010106", "53010206").contains(vo.getL3Code())) {
					//装备调试费用与试验费用
					vo.setZbtsfyysyfy(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010107", "53010207").contains(vo.getL3Code())) {
					//委托外部研究开发费用
					vo.setWwyf(vo.getAmount().doubleValue());
				} else if (Arrays.asList("53010108", "53010208").contains(vo.getL3Code())) {
					//其他费用
					vo.setQtfy(vo.getAmount().doubleValue());
				} else {
					throw new ServiceException("费用归集出错啦");
				}
			}
		}
		return list;
	}

	@SneakyThrows
	@Override
	public void exportHighTechCostDetail(OutputStream os, HighTechCostDetailVO vo, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/高新口径-研发支出辅助明细账.xls");
		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		Map<String, Object> map = new HashMap<>();
		List<JSONObject> results = new ArrayList<>();
		AtomicInteger index = new AtomicInteger(1);

		map.put("xmbh", vo.getXmbh());
		map.put("xmmc", vo.getXmmc());
		List<HighTechCostItemVO> costList = vo.getCostList();
		for (HighTechCostItemVO item : costList) {
			JSONObject obj = new JSONObject();
			obj.put("xh", index.getAndIncrement() + "");
			obj.put("recordDateStr", Func.notNull(item.getRecordDate()) ? DateUtil.format(item.getRecordDate(), DateUtil.PATTERN_DATE) : null);
			obj.put("voucherNumber", item.getVoucherNumber());
			obj.put("digest", item.getDigest());
			obj.put("ryrg", item.getRyrg());
			obj.put("zjtr", item.getZjtr());
			obj.put("zjfyycqdtfy", item.getZjfyycqdtfy());
			obj.put("sjf", item.getSjf());
			obj.put("wxzctx", item.getWxzctx());
			obj.put("zbtsfyysyfy", item.getZbtsfyysyfy());
			obj.put("qtfy", item.getQtfy());
			obj.put("wwyf", item.getWwyf());
			obj.put("amount", item.getAmount());
			obj.put("cashbook", item.getCashbook());
			results.add(obj);
		}
		map.put("ryrgTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getRyrg).sum()));
		map.put("zjtrTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getZjtr).sum()));
		map.put("zjfyycqdtfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getZjfyycqdtfy).sum()));
		map.put("sjfTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getSjf).sum()));
		map.put("wxzctxTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getWxzctx).sum()));
		map.put("zbtsfyysyfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getZbtsfyysyfy).sum()));
		map.put("qtfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getQtfy).sum()));
		map.put("wwyfTotal", BigDecimal.valueOf(costList.stream().mapToDouble(HighTechCostItemVO::getWwyf).sum()));
		map.put("amountTotal", costList.stream().map(HighTechCostItemVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));

		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(results, fillConfig, writeSheet);

		map.put("year", yearAndMonth.substring(0, 4));
		map.put("month", yearAndMonth.substring(4));

		R<Tenant> tenant = sysClient.getTenant(SecureUtil.getTenantId());
		if (tenant.isSuccess()) {
			map.put("enterpriseName", tenant.getData().getTenantName());
		}
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public IPage<HighTechCostSummary> highTechCostSummary(IPage<HighTechCostSummary> page, XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		dto.setTenantId(SecureUtil.getTenantId());

		Query query = new Query();
		query.setCurrent((int) page.getCurrent());
		query.setSize((int) page.getSize());
		IPage<JSONObject> p1 = Condition.getPage(query);

		//设置为高新口径，1：会计口径，2：加计扣除口径，3：高新口径
		dto.setCaliber(3);
		List<JSONObject> tmpList = baseMapper.costSummary(p1, dto);

		page.setTotal(p1.getTotal()).setCurrent(p1.getCurrent()).setSize(p1.getSize());

		List<HighTechCostSummary> summaryList = JSON.parseArray(JSON.toJSONString(tmpList), HighTechCostSummary.class);
		for (HighTechCostSummary summary : summaryList) {

			List<CostItemVO> itemVOS = baseMapper.selectCostItemByCondition(dto.getYearAndMonth(), summary.getXmId());

			for (CostItemVO item : itemVOS) {
				if (item.getRdSubjectEnable() == 0) {
					//四级科目不是高新研发费用科目，费用不归集
					continue;
				}
				if (Arrays.asList("53010101", "53010201").contains(item.getL3Code())) {
					//1、人员人工费用
					summary.setRyrgTotal(summary.getRyrgTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010102", "53010202").contains(item.getL3Code())) {
					//2、直接投入费用
					summary.setZjtrTotal(summary.getZjtrTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010103", "53010203").contains(item.getL3Code())) {
					//3、折旧费用与长期待摊费用
					summary.setZjfyycqdtfyTotal(summary.getZjfyycqdtfyTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010104", "53010204").contains(item.getL3Code())) {
					//4、无形资产摊销费用
					summary.setWxzctxTotal(summary.getWxzctxTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010105", "53010205").contains(item.getL3Code())) {
					//5、设计费用
					summary.setSjfTotal(summary.getSjfTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010106", "53010206").contains(item.getL3Code())) {
					//6、装备调试费用与试验费用
					summary.setZbtsfyysyfyTotal(summary.getZbtsfyysyfyTotal().add(item.getAmount()));
				} else if (Arrays.asList("53010107", "53010207").contains(item.getL3Code())) {
					//委托外部研究开发费用
					summary.setWwyfTotal(summary.getWwyfTotal().add(item.getAmount()).multiply(BigDecimal.valueOf(0.8)));
				} else if (Arrays.asList("53010108", "53010208").contains(item.getL3Code())) {
					//7-1、其他费用
					summary.setQtfyTotal(summary.getQtfyTotal().add(item.getAmount()));
				}
				// 7-2、其他费用限额，1-6合计相加/0.8*0.2
				BigDecimal total = summary.getRyrgTotal().add(summary.getZjtrTotal()).add(summary.getZjfyycqdtfyTotal()).add(summary.getSjfTotal()).add(summary.getWxzctxTotal()).add(summary.getZbtsfyysyfyTotal());
				summary.setQtfyLimit(total.divide(BigDecimal.valueOf(0.8), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(0.2)));
				//7-3、调整后其他费用，7-1和7-2，谁小取谁

				summary.setQtfyAdjust((summary.getQtfyTotal().compareTo(summary.getQtfyLimit()) == -1) ? summary.getQtfyTotal() : summary.getQtfyLimit());
			}
		}
		return page.setRecords(summaryList);
	}

	@SneakyThrows
	@Override
	public void exportHighTechCostSummary(OutputStream os, List<HighTechCostSummary> list, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/高新口径-研发支出辅助账汇总表.xls");
		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();
		Map<String, Object> map = new HashMap<>();
		AtomicInteger index = new AtomicInteger(1);
		list.forEach(item -> {
			item.setXh(index.getAndIncrement() + "");
			item.setTotal(item.getRyrgTotal().add(item.getZjtrTotal()).add(item.getZjfyycqdtfyTotal()).add(item.getSjfTotal()).add(item.getWxzctxTotal()).add(item.getZbtsfyysyfyTotal()).add(item.getQtfyAdjust()).add(item.getWwyfTotal()));
		});
		map.put("ryrgTotalSum", list.stream().map(HighTechCostSummary::getRyrgTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zjtrTotalSum", list.stream().map(HighTechCostSummary::getZjtrTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zjfyycqdtfyTotalSum", list.stream().map(HighTechCostSummary::getZjfyycqdtfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("sjfTotalSum", list.stream().map(HighTechCostSummary::getSjfTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("wxzctxTotalSum", list.stream().map(HighTechCostSummary::getWxzctxTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("zbtsfyysyfyTotalSum", list.stream().map(HighTechCostSummary::getZbtsfyysyfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("qtfyTotalSum", list.stream().map(HighTechCostSummary::getQtfyTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("wwyfTotalSum", list.stream().map(HighTechCostSummary::getWwyfTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("totalSum", list.stream().map(HighTechCostSummary::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(list, fillConfig, writeSheet);
		map.put("year", yearAndMonth.substring(0, 4));
		map.put("month", yearAndMonth.substring(4));

		R<Tenant> tenant = sysClient.getTenant(SecureUtil.getTenantId());
		if (tenant.isSuccess()) {
			map.put("enterpriseName", tenant.getData().getTenantName());
		}

		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public List<DeductionCostDetailVO> deductionCostDetail(XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		if (dto.getType() == null) {
			throw new ServiceException("参数type不能为空");
		}
		if (!Arrays.asList(1, 2).contains(dto.getType())) {
			throw new ServiceException("参数type的值只能是1：费用化，2：资本化");
		}
		dto.setTenantId(SecureUtil.getTenantId());
		List<DeductionCostDetailVO> list = baseMapper.deductionCostDetail(dto);
		for (DeductionCostDetailVO tmp : list) {
			tmp.setType(dto.getType());

			tmp.setWcqk(DateUtil.now().before(tmp.getXmjssj()) ? "进行中" : "已完成");
			List<DeductionCostItemVO> vos = tmp.getCostList();
			for (DeductionCostItemVO vo : vos) {
				if (vo.getAdSubjectEnable() == 0) {
					//四级科目 不是加计扣除研发费用科目，费用不归集
 					continue;
				}
				if (dto.getType() == 1) {
					//费用化
					if (Func.equals(vo.getL3Code(), "53010101")) {
						//人员人工费用
						vo.setRyrgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010102")) {
						//直接投入费用
						vo.setZjtrfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010103")) {
						//折旧费用
						vo.setZjfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010104")) {
						//无形资产摊销
						vo.setWxzctx(vo.getAmount().doubleValue());
					} else if (Arrays.asList("5301010501", "5301010502", "5301010602", "5301010603").contains(vo.getL4Code())) {
						//新产品设计费等
						//三级科目中的“设计费用”-新产品设计费，新工艺规程制定费；和"装备调试费用与试验费用"-新药研制的临床试验费,勘探开发的现场试验费；归集到新产品设计费等
						vo.setXcpsjfd(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010108")) {
						//其他相关费用
						vo.setQtxgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL4Code(), "5301010701")) {
						//委托境内机构或个人进行研发活动所发生的费用
						vo.setWtjnjgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL4Code(), "5301010702")) {
						//委托境外机构进行研发活动所发生的费用
						vo.setWtjwjgfy(vo.getAmount().doubleValue());
					} else {
						throw new ServiceException("费用归集出错啦");
					}
				} else if (dto.getType() == 2) {
					//资本化
					if (Func.equals(vo.getL3Code(), "53010201")) {
						//人员人工费用
						vo.setRyrgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010202")) {
						//直接投入费用
						vo.setZjtrfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010203")) {
						//折旧费用
						vo.setZjfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010204")) {
						//无形资产摊销
						vo.setWxzctx(vo.getAmount().doubleValue());
					} else if (Arrays.asList("5301020501", "5301020502", "5301020602", "5301020603").contains(vo.getL4Code())) {
						//新产品设计费等
						//三级科目中的“设计费用”-新产品设计费，新工艺规程制定费；和"装备调试费用与试验费用"-新药研制的临床试验费,勘探开发的现场试验费；归集到新产品设计费等
						vo.setXcpsjfd(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL3Code(), "53010208")) {
						//其他相关费用
						vo.setQtxgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL4Code(), "5301020701")) {
						//委托境内机构或个人进行研发活动所发生的费用
						vo.setWtjnjgfy(vo.getAmount().doubleValue());
					} else if (Func.equals(vo.getL4Code(), "5301020702")) {
						//委托境外机构进行研发活动所发生的费用
						vo.setWtjwjgfy(vo.getAmount().doubleValue());
					} else {
						throw new ServiceException("费用归集出错啦");
					}
				}
				vo.setGjje(vo.getRyrgfy() + vo.getZjtrfy() + vo.getZjfy() + vo.getWxzctx() + vo.getXcpsjfd() + vo.getQtxgfy() + vo.getWtjnjgfy() + vo.getWtjwjgfy());
			}
		}
		return list;
	}

	@SneakyThrows
	@Override
	public void exportDeductionCostDetail(OutputStream os, DeductionCostDetailVO vo, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/加计扣除-研发支出辅助明细账.xls");
		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		Map<String, Object> map = new HashMap<>();
		List<JSONObject> results = new ArrayList<>();
		AtomicInteger index = new AtomicInteger(1);

		List<DeductionCostItemVO> costList = vo.getCostList();
		for (DeductionCostItemVO item : costList) {
			JSONObject obj = new JSONObject();
			obj.put("xh", index.getAndIncrement() + "");
			obj.put("recordDateStr", Func.notNull(item.getRecordDate()) ? DateUtil.format(item.getRecordDate(), DateUtil.PATTERN_DATE) : "");
			obj.put("voucherNumber", item.getVoucherNumber());
			obj.put("type", vo.getType() == 1 ? "费用化" : "资本化");
			obj.put("digest", item.getDigest());
			obj.put("amount", item.getAmount());
			obj.put("ryrgfy", item.getRyrgfy());
			obj.put("zjtrfy", item.getZjtrfy());
			obj.put("zjfy", item.getZjfy());
			obj.put("wxzctx", item.getWxzctx());
			obj.put("xcpsjfd", item.getXcpsjfd());
			obj.put("qtxgfy", item.getQtxgfy());
			obj.put("wtjnjgfy", item.getWtjnjgfy());
			obj.put("wtjwjgfy", item.getWtjwjgfy());
			obj.put("gjje", item.getRyrgfy()+item.getZjtrfy()+item.getZjfy()+item.getWxzctx()+item.getXcpsjfd()+item.getQtxgfy()+item.getWtjnjgfy()+item.getWtjwjgfy());
			results.add(obj);
		}
		map.put("type", vo.getType() == 1 ? "费用化" : "资本化");
		map.put("wcqk", vo.getWcqk());
		map.put("xmbh", vo.getXmbh());
		map.put("xmmc", vo.getXmmc());
		map.put("year", yearAndMonth.substring(0, 4));
		map.put("month", yearAndMonth.substring(4));

		map.put("ryrgfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getRyrgfy).sum()));
		map.put("zjtrfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getZjtrfy).sum()));
		map.put("zjfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getZjfy).sum()));
		map.put("wxzctxTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getWxzctx).sum()));
		map.put("xcpsjfdTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getXcpsjfd).sum()));
		map.put("qtxgfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getQtxgfy).sum()));
		map.put("wtjnjgfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getWtjnjgfy).sum()));
		map.put("wtjwjgfyTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getWtjwjgfy).sum()));
		map.put("amountTotal", costList.stream().map(DeductionCostItemVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
		map.put("gjjeTotal", BigDecimal.valueOf(costList.stream().mapToDouble(DeductionCostItemVO::getGjje).sum()));
		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(results, fillConfig, writeSheet);
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public DeductionCostSummary deductionCostSummary(XmCostDetailsDTO dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		dto.setTenantId(SecureUtil.getTenantId());
		//设置为加计扣除口径，1：会计口径，2：加计扣除口径，3：高新口径
		dto.setCaliber(2);
		List<DeductionCostDetailVO> list = baseMapper.deductionCostDetail(dto);
		DeductionCostSummary summary = new DeductionCostSummary();
		DeductionCostQt qt = qtMapper.selectOne(Wrappers.<DeductionCostQt>lambdaQuery().eq(DeductionCostQt::getYearAndMonth, dto.getYearAndMonth()));
		if (Func.notNull(qt)) {
			summary.setRyrgfy_qt(qt.getRyrgfyQt());
			summary.setZjtrfy_qt(qt.getZjtrfyQt());
			summary.setZjfy_qt(qt.getZjfyQt());
			summary.setWxzctx_qt(qt.getWxzctxQt());
			summary.setXcpsjfd_qt(qt.getXcpsjfdQt());
			summary.setQtxgfyhj_qt(qt.getQtxgfyhjQt());
			summary.setWtjnjgfy_qt(qt.getWtjnjgfyQt());
			summary.setWtjwjgfy_qt(qt.getWtjwjgfyQt());

			//先将“其中：其他事项”加入到 对应的费用化金额小计
			summary.setRyrgfy_fyh(summary.getRyrgfy_fyh().add(summary.getRyrgfy_qt()));
			summary.setZjtrfy_fyh(summary.getZjtrfy_fyh().add(summary.getZjtrfy_qt()));
			summary.setZjfy_fyh(summary.getZjfy_fyh().add(summary.getZjfy_qt()));
			summary.setWxzctx_fyh(summary.getWxzctx_fyh().add(summary.getWxzctx_qt()));
			summary.setXcpsjfd_fyh(summary.getXcpsjfd_fyh().add(summary.getXcpsjfd_qt()));
			summary.setQtxgfyhj_fyh(summary.getQtxgfyhj_fyh().add(summary.getQtxgfyhj_qt()));
			summary.setWtjnjgfy_fyh(summary.getWtjnjgfy_fyh().add(summary.getWtjnjgfy_qt()));
			summary.setWtjwjgfy_fyh(summary.getWtjwjgfy_fyh().add(summary.getWtjwjgfy_qt()));

			//其中：其他事项-前五项 小计
			summary.setTotal_qt(qt.getRyrgfyQt().add(qt.getZjtrfyQt()).add(qt.getZjfyQt()).add(qt.getWxzctxQt()).add(qt.getXcpsjfdQt()));

			summary.setTotal_fyh(summary.getTotal_fyh().add(summary.getTotal_qt()));
		}
		List<DeductionCostSummaryItem> summaryList = new ArrayList<>();
		for (DeductionCostDetailVO cost : list) {
			String wcqk = DateUtil.now().before(cost.getXmjssj()) ? "进行中" : "已完成";
			DeductionCostSummaryItem fyhSummary = new DeductionCostSummaryItem(cost.getXmId(), cost.getXmbh(), cost.getXmmc(), wcqk, 1);
			DeductionCostSummaryItem zbhSummary = new DeductionCostSummaryItem(cost.getXmId(), cost.getXmbh(), cost.getXmmc(), wcqk, 2);
			summaryList.add(fyhSummary);
			summaryList.add(zbhSummary);
			for (DeductionCostItemVO vo : cost.getCostList()) {
				if (vo.getAdSubjectEnable() == 0) {
					//四级科目 不是加计扣除研发费用科目，费用不归集
					continue;
				}
				if (Func.equals(vo.getL3Code(), "53010101")) {
					//1、人员人工费用-费用化
					fyhSummary.setRyrgTotal(fyhSummary.getRyrgTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010201")) {
					//人员人工费用-资本化
					zbhSummary.setRyrgTotal(zbhSummary.getRyrgTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010102")) {
					//2、直接投入费用费用-费用化
					fyhSummary.setZjtrTotal(fyhSummary.getZjtrTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010202")) {
					//直接投入费用-资本化
					zbhSummary.setZjtrTotal(zbhSummary.getZjtrTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010103")) {
					//3、折旧费用-费用化
					fyhSummary.setZjfyTotal(fyhSummary.getZjfyTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010203")) {
					//3、折旧费用-资本化
					zbhSummary.setZjfyTotal(zbhSummary.getZjfyTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010104")) {
					//4、无形资产摊销-费用化
					fyhSummary.setWxzctxTotal(fyhSummary.getWxzctxTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010204")) {
					//4、无形资产摊销-资本化
					zbhSummary.setWxzctxTotal(zbhSummary.getWxzctxTotal().add(vo.getAmount()));
				} else if (Arrays.asList("5301010501", "5301010502", "5301010602", "5301010603").contains(vo.getL4Code())) {
					//5、新产品设计费等-费用化
					//三级科目中的“设计费用”-新产品设计费，新工艺规程制定费；和"装备调试费用与试验费用"-新药研制的临床试验费,勘探开发的现场试验费；归集到新产品设计费等
					fyhSummary.setXcpsjfd(fyhSummary.getXcpsjfd().add(vo.getAmount()));
				} else if (Arrays.asList("5301020501", "5301020502", "5301020602", "5301020603").contains(vo.getL4Code())) {
					//5、新产品设计费等-资本化
					//三级科目中的“设计费用”-新产品设计费，新工艺规程制定费；和"装备调试费用与试验费用"-新药研制的临床试验费,勘探开发的现场试验费；归集到新产品设计费等
					zbhSummary.setXcpsjfd(zbhSummary.getXcpsjfd().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010108")) {
					//7.1、其他相关费用-费用化
					fyhSummary.setQtxgfyTotal(fyhSummary.getQtxgfyTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL3Code(), "53010208")) {
					//7.1、其他相关费用-资本化
					zbhSummary.setQtxgfyTotal(zbhSummary.getQtxgfyTotal().add(vo.getAmount()));
				} else if (Func.equals(vo.getL4Code(), "5301010701")) {
					//8.1、委托境内机构或个人进行研发活动所发生的费用-费用化
					fyhSummary.setWtjnfy(fyhSummary.getWtjnfy().add(vo.getAmount()));
				} else if (Func.equals(vo.getL4Code(), "5301020701")) {
					//8.1、委托境内机构或个人进行研发活动所发生的费用-资本化
					zbhSummary.setWtjnfy(zbhSummary.getWtjnfy().add(vo.getAmount()));
				} else if (Func.equals(vo.getL4Code(), "5301010702")) {
					//8.3、委托境外机构进行研发活动所发生的费用-费用化
					fyhSummary.setWtjwfy(fyhSummary.getWtjwfy().add(vo.getAmount()));
				} else if (Func.equals(vo.getL4Code(), "5301020702")) {
					//8.3、委托境外机构进行研发活动所发生的费用-资本化
					zbhSummary.setWtjwfy(zbhSummary.getWtjwfy().add(vo.getAmount()));
				} else {
					throw new ServiceException("费用归集出错啦");
				}
			}

			//前五项小计=1、人员人工费用+2、直接投入费用+3、折旧费用+4、无形资产摊销+5、新产品设计费等
			fyhSummary.setTotal(fyhSummary.getRyrgTotal().add(fyhSummary.getZjtrTotal()).add(fyhSummary.getZjfyTotal()).add(fyhSummary.getWxzctxTotal()).add(fyhSummary.getXcpsjfd()));
			zbhSummary.setTotal(zbhSummary.getRyrgTotal().add(zbhSummary.getZjtrTotal()).add(zbhSummary.getZjfyTotal()).add(zbhSummary.getWxzctxTotal()).add(zbhSummary.getXcpsjfd()));

			zbhSummary.setWtjnfyAdjust(zbhSummary.getWtjnfyAdjust().multiply(new BigDecimal("0.8")));
			fyhSummary.setWtjnfyAdjust(fyhSummary.getWtjnfyAdjust().multiply(new BigDecimal("0.8")));


			//资本化金额小计----------------begin
			//资本化金额小计-人员人工费用
			summary.setRyrgfy_zbh(summary.getRyrgfy_zbh().add(zbhSummary.getRyrgTotal()));
			//费用化金额小计-人员人工费用
			summary.setRyrgfy_fyh(summary.getRyrgfy_fyh().add(fyhSummary.getRyrgTotal()));
			//金额合计-人员人工费用
			summary.setRyrgfy_hjje(summary.getRyrgfy_hjje().add(summary.getRyrgfy_zbh()).add(summary.getRyrgfy_fyh()));

			//资本化金额小计-直接投入费用
			summary.setZjtrfy_zbh(summary.getZjtrfy_zbh().add(zbhSummary.getZjtrTotal()));
			//费用化金额小计-直接投入费用
			summary.setZjtrfy_fyh(summary.getZjtrfy_fyh().add(fyhSummary.getZjtrTotal()));
			//金额合计-直接投入费用
			summary.setZjtrfy_hjje(summary.getZjtrfy_hjje().add(summary.getZjtrfy_zbh()).add(summary.getZjtrfy_fyh()));

			//资本化金额小计-折旧费用
			summary.setZjfy_zbh(summary.getZjfy_zbh().add(zbhSummary.getZjfyTotal()));
			//费用化金额小计-折旧费用
			summary.setZjfy_fyh(summary.getZjfy_fyh().add(fyhSummary.getZjfyTotal()));
			//金额合计-折旧费用
			summary.setZjfy_hjje(summary.getZjfy_hjje().add(summary.getZjfy_zbh()).add(summary.getZjfy_fyh()));

			//资本化金额小计-无形资产摊销
			summary.setWxzctx_zbh(summary.getWxzctx_zbh().add(zbhSummary.getWxzctxTotal()));
			//费用化金额小计-无形资产摊销
			summary.setWxzctx_fyh(summary.getWxzctx_fyh().add(fyhSummary.getWxzctxTotal()));
			//金额合计-无形资产摊销
			summary.setWxzctx_hjje(summary.getWxzctx_hjje().add(summary.getWxzctx_zbh()).add(summary.getWxzctx_fyh()));

			//资本化金额小计-新产品设计费等
			summary.setXcpsjfd_zbh(summary.getXcpsjfd_zbh().add(zbhSummary.getXcpsjfd()));
			//费用化金额小计-新产品设计费等
			summary.setXcpsjfd_fyh(summary.getXcpsjfd_fyh().add(fyhSummary.getXcpsjfd()));
			//金额合计-新产品设计费等
			summary.setXcpsjfd_hjje(summary.getXcpsjfd_hjje().add(summary.getXcpsjfd_zbh()).add(summary.getXcpsjfd_fyh()));


			//资本化金额小计-前五项小计
			summary.setTotal_zbh(summary.getTotal_zbh().add(zbhSummary.getTotal()));
			//费用化金额小计-前五项小计
			summary.setTotal_fyh(summary.getTotal_fyh().add(fyhSummary.getTotal()));
			//金额合计-前五项 小计
			summary.setTotal_hjje(summary.getTotal_hjje().add(summary.getTotal_zbh()).add(summary.getTotal_fyh()));

			//资本化金额小计-其他相关费用合计
			summary.setQtxgfyhj_zbh(summary.getQtxgfyhj_zbh().add(zbhSummary.getQtxgfyTotal()));
			//费用化金额小计-其他相关费用合计
			summary.setQtxgfyhj_fyh(summary.getQtxgfyhj_fyh().add(fyhSummary.getQtxgfyTotal()));
			//金额合计-其他相关费用合计
			summary.setQtxgfyhj_hjje(summary.getQtxgfyhj_hjje().add(summary.getQtxgfyhj_zbh()).add(summary.getQtxgfyhj_fyh()));

			//资本化金额小计-委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_zbh(summary.getWtjnjgfy_zbh().add(zbhSummary.getWtjnfy()));
			//费用化金额小计-委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_fyh(summary.getWtjnjgfy_fyh().add(fyhSummary.getWtjnfy()));
			//金额合计-委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_hjje(summary.getWtjnjgfy_hjje().add(summary.getWtjnjgfy_zbh()).add(summary.getWtjnjgfy_fyh()));


			//资本化金额小计-允许加计扣除的委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_zbh(summary.getWtjnjgfy_zbh().add(zbhSummary.getWtjnfyAdjust()));
			//费用化金额小计-允许加计扣除的委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_fyh(summary.getWtjnjgfy_fyh().add(fyhSummary.getWtjnfyAdjust()));
			//金额合计-允许加计扣除的委托境内机构或个人进行研发活动所发生的费用
			summary.setWtjnjgfy_hjje(summary.getWtjnjgfy_hjje().add(summary.getWtjnjgfy_zbh()).add(summary.getWtjnjgfy_fyh()));

			//资本化金额小计-委托境外机构进行研发活动所发生的费用
			summary.setWtjwjgfy_zbh(summary.getWtjwjgfy_zbh().add(zbhSummary.getWtjwfy()));
			//费用化金额小计-委托境外机构进行研发活动所发生的费用
			summary.setWtjwjgfy_fyh(summary.getWtjwjgfy_fyh().add(fyhSummary.getWtjwfy()));
			//金额合计-委托境外机构进行研发活动所发生的费用
			summary.setWtjwjgfy_hjje(summary.getWtjwjgfy_hjje().add(summary.getWtjwjgfy_zbh()).add(summary.getWtjwjgfy_fyh()));

			//允许加计扣除金额合计=前五项 小计 + 经限额调整后的其他相关费用 + 允许加计扣除的委托境内机构或个人进行研发活动所发生的费用 + 经限额调整后的委托境外机构进行研发活动所发生的费用
			fyhSummary.setYxjjkcjehj(fyhSummary.getYxjjkcjehj().add(fyhSummary.getTotal()));
			zbhSummary.setYxjjkcjehj(zbhSummary.getYxjjkcjehj().add(zbhSummary.getTotal()));
		}

		summary.setTotal_hjje(summary.getTotal_zbh().add(summary.getTotal_fyh()));

		//=IF(K20*0.1/0.9<L20,K20*0.1/0.9,L20)
		BigDecimal divide = summary.getTotal_hjje().multiply(new BigDecimal("0.1")).divide(new BigDecimal("0.9"), 2, RoundingMode.HALF_UP);
		summary.setQtxgfyhj_adjust_hjje(divide.compareTo(summary.getQtxgfyhj_hjje()) < 0 ? divide : summary.getQtxgfyhj_hjje());


		//金额合计-经限额调整后的委托境外机构进行研发活动所发生的费用
		//(K20+M20+O20)*2/3
		BigDecimal d1 = summary.getTotal_hjje().add(summary.getQtxgfyhj_hjje()).add(summary.getWtjnjgfy_hjje()).multiply(new BigDecimal("2")).divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP);
		//P20*0.8
		BigDecimal d2 = summary.getWtjwjgfy_hjje().multiply(new BigDecimal("0.8"));
		summary.setWtjwjgfy_adjust_hjje(d1.compareTo(d2) < 0 ? d1 : d2);

		for (DeductionCostSummaryItem item : summaryList) {

			//=$Q$20/$P$20*P8 经限额调整后的委托境外机构进行研发活动所发生的费用
			if (BigDecimal.ZERO.compareTo(summary.getWtjwjgfy_hjje()) != 0) {
				item.setWtjwfyAdjust(summary.getWtjwjgfy_adjust_hjje().multiply(item.getWtjwfy()).divide(summary.getWtjwjgfy_hjje(), 2, RoundingMode.HALF_UP));
			}

			//=M20/L20*L9
			if (BigDecimal.ZERO.compareTo(summary.getQtxgfyhj_hjje()) != 0) {
				item.setQtxgfyAdjustTotal(summary.getQtxgfyhj_adjust_hjje().multiply(item.getQtxgfyTotal()).divide(summary.getQtxgfyhj_hjje(), 2, RoundingMode.HALF_UP));
			}

			//允许加计扣除金额合计 = 前五项 小计 + 经限额调整后的其他相关费用 + 允许加计扣除的委托境内机构或个人进行研发活动所发生的费用 + 经限额调整后的委托境外机构进行研发活动所发生的费用
			item.setYxjjkcjehj(item.getRyrgTotal().add(item.getQtxgfyAdjustTotal()).add(item.getWtjnfyAdjust()).add(item.getWtjwfyAdjust()));

			if (item.getType() == 1) {
				summary.setQtxgfyhj_adjust_fyh(summary.getQtxgfyhj_adjust_fyh().add(item.getQtxgfyAdjustTotal()));
				summary.setWtjwjgfy_adjust_fyh(summary.getWtjwjgfy_adjust_fyh().add(item.getWtjwfyAdjust()));

				summary.setYxjjkcjehj_fyh(summary.getYxjjkcjehj_fyh().add(item.getYxjjkcjehj()));

			} else if (item.getType() == 2) {
				summary.setQtxgfyhj_adjust_zbh(summary.getQtxgfyhj_adjust_zbh().add(item.getQtxgfyAdjustTotal()));
				summary.setWtjwjgfy_adjust_zbh(summary.getWtjwjgfy_adjust_zbh().add(item.getWtjwfyAdjust()));

				summary.setYxjjkcjehj_zbh(summary.getYxjjkcjehj_zbh().add(item.getYxjjkcjehj()));
			}
		}
		summary.setYxjjkcjehj_hjje(summary.getYxjjkcjehj_hjje().add(summary.getYxjjkcjehj_fyh()).add(summary.getYxjjkcjehj_zbh()));
		summary.setItemList(summaryList);
		return summary;
	}

	@SneakyThrows
	@Override
	public void exportDeductionCostSummary(OutputStream os, DeductionCostSummary summary, String yearAndMonth) {
		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/对外报表管理/加计扣除-研发支出辅助汇总表.xls");

		ExcelWriter excelWriter = EasyExcel.write(os)
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();
		AtomicInteger index = new AtomicInteger(1);
		List<DeductionCostSummaryItem> itemList = summary.getItemList();
		List<JSONObject> results = new ArrayList<>();
		itemList.forEach(item -> {
			JSONObject obj = new JSONObject();
			BeanUtil.copyProperties(item, obj);
			obj.put("xh", index.getAndIncrement() + "");
			obj.put("typeStr", item.getType() == 1 ? "费用化" : "资本化");
			results.add(obj);
		});

		Map<String, Object> map = new HashMap<>();
		BeanUtil.copyProperties(summary, map, "itemList");
		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		//设置list集合数据
		excelWriter.fill(results, fillConfig, writeSheet);
		map.put("yearAndMonth", yearAndMonth);
		R<Tenant> tenant = sysClient.getTenant(SecureUtil.getTenantId());
		if (tenant.isSuccess()) {
			Tenant data = tenant.getData();
			map.put("enterpriseName", data.getTenantName());
			map.put("uscc", data.getUscc());
		}
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public boolean updateDeductionQt(DeductionCostQt dto) {
		if (Func.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		LambdaQueryWrapper<DeductionCostQt> eq = Wrappers.<DeductionCostQt>lambdaQuery()
			.eq(DeductionCostQt::getYearAndMonth, dto.getYearAndMonth())
			.eq(DeductionCostQt::getTenantId, SecureUtil.getTenantId());
		DeductionCostQt dbQt = qtMapper.selectOne(eq);
		if (Func.isNull(dbQt)) {
			return qtMapper.insert(dto) == 1;
		} else {
			dto.setId(dbQt.getId());
			return qtMapper.updateById(dto) == 1;
		}
	}

}
