package org.sky.scientific.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.sky.core.log.exception.ServiceException;
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.utils.DateUtil;
import org.sky.core.tool.utils.Func;
import org.sky.scientific.mapper.ArchiveAttachMapper;
import org.sky.scientific.mapper.DownloadTaskMapper;
import org.sky.scientific.mapper.SettingMapper;
import org.sky.scientific.pojo.dto.*;
import org.sky.scientific.pojo.entity.*;
import org.sky.scientific.pojo.vo.*;
import org.sky.scientific.service.*;
import org.sky.scientific.utils.ZipDir;
import org.sky.scientific.utils.ZipDownloadUtils;
import org.sky.scientific.utils.ZipFileRef;
import org.sky.system.cache.DictCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.Deflater;

@Service
public class ArchiveServiceImpl implements IArchiveService {

	private static final Logger log = LoggerFactory.getLogger(ArchiveServiceImpl.class);
	@Value("${archive.dir}")
	private String archiveDir;

	@Resource
	private ArchiveAttachMapper attachMapper;
	@Resource
	private SettingMapper settingMapper;
	@Resource
	private IXmFinanceService xmFinanceService;
	@Resource
	private IEnterpriseInfoService enterpriseInfoService;
	@Resource
	private IXmCostDetailsService xmCostDetailsService;
	@Resource
	private IXmTechnicianHoursService xmTechnicianHoursService;
	@Resource
	private ITechnicianService technicianService;
	@Resource
	private IXmGoodsService xmGoodsService;
	@Resource
	private IXmLeaseService xmLeaseService;
	@Resource
	private IXmAssetHoursService hoursService;
	@Resource
	private IXmFixedAssetService xmFixedAssetService;
	@Resource
	private IXmIntangibleAssetService xmIntangibleAssetService;
	@Resource
	private IXmService xmService;
	@Resource
	private IYsRyrgfyService ysRyrgfyService;
	@Resource
	private IYsZjtrfyService ysZjtrfyService;
	@Resource
	private IYsZjfyycqdtfyService ysZjfyycqdtfyService;
	@Resource
	private IYsWxzctxfyService ysWxzctxfyService;
	@Resource
	private IYsSjfyService ysSjfyService;
	@Resource
	private IYsZbtsysyfyService ysZbtsysyfyService;
	@Resource
	private IYsWtwbyjkffyService ysWtwbyjkffyService;
	@Resource
	private IYsQtfyService ysQtfyService;
	@Resource
	private IXmJdxbgService xmJdxbgService;
	@Resource
	private IXmBgrzService xmBgrzService;
	@Resource
	private IXmJtbService xmJtbService;
	@Resource
	private ICgQtService cgQtService;
	@Resource
	private IXmWwxmService xmWwxmService;
	@Resource
	private ICgJsbzService jsbzService;
	@Resource
	private ICgKylwService kylwService;
	@Resource
	private ICgZlService zlService;
	@Resource
	private ICgRjzzqService rjzzqService;
	@Resource
	private ICgQtService qtService;
	@Resource
	private DownloadTaskMapper downloadTaskMapper;
	@Resource
	private ISalaryService salaryService;
	@Resource
	private IAttendanceService attendanceService;
	@Resource
	private IXmDirectCostService xmDirectCostService;
	@Resource
	private IXmCqdtfyService xmCqdtfyService;
	@Resource
	private IXmDesignCostService xmDesignCostService;
	@Resource
	private IXmOtherCostService xmOtherCostService;
	@Resource
	private IXmWwxmCostService wwxmCostService;

	@Override
	public ArchiveAttachEntity fjbczl(String year) {
		if (Func.isNull(year)) {
			throw new ServiceException("参数year不能为空");
		}
		if (year.length() != 4) {
			throw new ServiceException("参数year为年份，如2025");
		}

		ArchiveAttachEntity attach = attachMapper.selectOne(Wrappers.<ArchiveAttachEntity>lambdaQuery().eq(ArchiveAttachEntity::getYearAndMonth, year));
		if (Func.isNull(attach)) {
			attach = new ArchiveAttachEntity();
		}

		return attach;
	}

	@Override
	public boolean fjbczlUpdate(ArchiveAttachEntity attach) {
		if (Func.isNull(attach.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		if (attach.getYearAndMonth().length() != 4) {
			throw new ServiceException("参数yearAndMonth为年份，如2025");
		}
		LambdaQueryWrapper<ArchiveAttachEntity> eq = Wrappers.<ArchiveAttachEntity>lambdaQuery().eq(ArchiveAttachEntity::getYearAndMonth, attach.getYearAndMonth());
		ArchiveAttachEntity one = attachMapper.selectOne(eq);
		if (Func.isNull(one)) {
			attach.setTenantId(SecureUtil.getTenantId());
			return attachMapper.insert(attach) == 1;
		} else {
			attach.setId(one.getId());
			return attachMapper.updateById(attach) == 1;
		}
	}

	public void configZipDir(ZipDir dir, String content) {
		if (Func.notNull(content)) {
			List<JSONObject> files = JSON.parseArray(content, JSONObject.class);
			List<ZipFileRef> fileRefs = new ArrayList<>();
			for (JSONObject file : files) {
				fileRefs.add(new ZipFileRef(file.getString("label"), null, file.getString("value")));
			}
			dir.setFileRefs(fileRefs);
		}
	}

	@Override
	public void downloadFjbczlZipFiles(HttpServletRequest request, HttpServletResponse response, String year) {
		List<ZipDir> data = new ArrayList<>();

		ArchiveAttachEntity attach = fjbczl(year);

		ZipDir d = new ZipDir();
		d.setDirName("高新项目技术鉴定资料");
		configZipDir(d, attach.getD1());
		data.add(d);

		d = new ZipDir();
		d.setDirName("加计扣除项目技术鉴定资料");
		configZipDir(d, attach.getD2());
		data.add(d);

		d = new ZipDir();
		d.setDirName("高新技术企业认定资料");
		configZipDir(d, attach.getD3());
		data.add(d);

		d = new ZipDir();
		d.setDirName("研发立项决议文件");
		configZipDir(d, attach.getD13());
		data.add(d);

		d = new ZipDir();
		d.setDirName("年度主要产品(服务)发挥核心支持作用的技术属于《国家重点支持的高新技术领域》规定范围的说明");
		configZipDir(d, attach.getD4());
		data.add(d);

		d = new ZipDir();
		d.setDirName("高新技术产品(服务)及对应收入资料");
		configZipDir(d, attach.getD5());
		data.add(d);

		d = new ZipDir();
		d.setDirName("年度职工和科技人员情况说明");
		configZipDir(d, attach.getD6());
		data.add(d);

		d = new ZipDir();
		d.setDirName("当年和前两个会计年度研发费用总额及占同期销售收入比例的说明");
		configZipDir(d, attach.getD7());
		data.add(d);

		d = new ZipDir();
		d.setDirName("研发管理制度");
		configZipDir(d, attach.getD8());
		data.add(d);

		d = new ZipDir();
		d.setDirName("研发费用结构明细表");
		configZipDir(d, attach.getD9());
		data.add(d);

		d = new ZipDir();
		d.setDirName("加计扣除情况说明");
		configZipDir(d, attach.getD10());
		data.add(d);

		d = new ZipDir();
		d.setDirName("其他高新备查资料");
		configZipDir(d, attach.getD11());
		data.add(d);

		d = new ZipDir();
		d.setDirName("其他加计扣除备查资料");
		configZipDir(d, attach.getD12());
		data.add(d);

		try (BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(bos)) {
			String fileName = year + "年附件补充" + ".zip";
			ZipDownloadUtils.setResponse(request, response, fileName);
			// 快速压缩
			zipOut.setLevel(Deflater.BEST_SPEED);
			for (ZipDir group : data) {
				String dir = ZipDownloadUtils.safeName(group.getDirName()) + "/";
				if (Func.isEmpty(group.getFileRefs())) {
					ZipDownloadUtils.writeEmptyDirToZip(zipOut, dir);
				} else {
					for (ZipFileRef fileRef : group.getFileRefs()) {
						if (fileRef.getLocalPath() != null && !fileRef.getLocalPath().isEmpty()) {
							ZipDownloadUtils.writeLocalFileToZip(zipOut, fileRef.getLocalPath(), dir + ZipDownloadUtils.safeName(fileRef.getName()));
						} else if (fileRef.getHttpUrl() != null && !fileRef.getHttpUrl().isEmpty()) {
							ZipDownloadUtils.writeHttpFileToZip(zipOut, fileRef.getHttpUrl(), dir + ZipDownloadUtils.safeName(fileRef.getName()));
						}
					}
				}
			}
			zipOut.finish();
			zipOut.flush();
			response.flushBuffer();
		} catch (Exception e) {
			throw new RuntimeException("打包下载失败", e);
		}
	}

	@Override
	public void downloadCenterZipFiles(DownloadTask task) {
		String year = task.getYearAndMonth();
		if (Func.isBlank(year)) {
			throw new ServiceException("参数year不能为空");
		}
		String dir;
		List<Integer> types = null;
		if (task.getType() == 0) {
			dir = "全部档案资料";
			types = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
		} else if (task.getType() == 1) {
			dir = "高新备查资料";
			types = Arrays.asList(1, 2, 4, 5, 7, 9, 11, 14, 21, 22, 23, 25, 27);
		} else {
			dir = "加计扣除备查资料";
			types = Arrays.asList(3, 4, 6, 8, 10, 13, 16, 19, 20, 26, 28);
		}
		Date date = new Date();

		ArchiveAttachEntity archiveAttach = attachMapper.selectOne(Wrappers.<ArchiveAttachEntity>lambdaQuery().eq(ArchiveAttachEntity::getYearAndMonth, year));
		if (archiveAttach == null) {
			archiveAttach = new ArchiveAttachEntity();
		}
//		Path basePath = Paths.get(archiveDir, UUID.randomUUID().toString(), SecureUtil.getTenantId(), year, dir);
		Path basePath = Paths.get(archiveDir, UUID.randomUUID().toString());
		if (FileUtil.exist(basePath.toString())) {
			FileUtil.del(basePath.toString());
		}
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		List<CompletableFuture<Void>> futureList = new ArrayList<>();

		ArchiveAttachEntity finalArchiveAttach = archiveAttach;
		List<Integer> finalTypes = types;
		futureList.add(CompletableFuture.runAsync(() -> {
			RequestContextHolder.setRequestAttributes(requestAttributes);
			if (finalTypes.contains(1)) {
				//1 高新技术企业资格证书：基础资源管理-企业基本信息-高企证书上传（按年度）。未上传则为空
				generateD1(Paths.get(basePath.toString(), "1.高新技术企业资格证书"), year);
			}
			if (finalTypes.contains(2)) {
				//2 高新技术企业认定资料：附件补充
				Path path2 = FileUtil.mkdir(Paths.get(basePath.toString(), "2.高新技术企业认定资料"));
				this.downloadAttachFiles(path2, Collections.singletonList(finalArchiveAttach.getD3()));
			}
			if (finalTypes.contains(3)) {
				//3 加计扣除情况说明：附件补充
				Path path3 = FileUtil.mkdir(Paths.get(basePath.toString(), "3.加计扣除情况说明"));
				this.downloadAttachFiles(path3, Collections.singletonList(finalArchiveAttach.getD10()));
			}
			if (finalTypes.contains(4)) {
				//4 研发立项决议文件：附件补充
				Path path4 = FileUtil.mkdir(Paths.get(basePath.toString(), "4.研发立项决议文件"));
				this.downloadAttachFiles(path4, Collections.singletonList(finalArchiveAttach.getD13()));
			}
			if (finalTypes.contains(5)) {
				//5 高新研发项目汇总表：对外报表-高新口径研发费用报表-高新-研发项目清单表
				generateD5(Paths.get(basePath.toString(), "5.高新研发项目汇总表"), year, 3);
			}
			if (finalTypes.contains(6)) {
				//6 加计扣除研发项目汇总表：对外报表-加计扣除口径研发费用报表-加计扣除-研发项目清单表
				generateD5(Paths.get(basePath.toString(), "6.加计扣除研发项目汇总表"), year, 2);
			}
		}));

		if (types.contains(7)) {
			Path path7 = FileUtil.mkdir(Paths.get(basePath.toString(), "7.高新研发项目全套技术资料"));
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			dto.setType(3);
			List<XmFinanceEntity> list = xmFinanceService.selectXmFinanceList(dto);
			AtomicInteger iii = new AtomicInteger(1);
			for (XmFinanceEntity xm : list) {
				futureList.add(CompletableFuture.runAsync(() -> {
					RequestContextHolder.setRequestAttributes(requestAttributes);
					generateD7(path7, iii.getAndIncrement(), xm);
				}));
			}
		}
		if (types.contains(8)) {
			Path path8 = FileUtil.mkdir(Paths.get(basePath.toString(), "8.加计扣除研发项目全套技术资料"));
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			dto.setType(2);
			List<XmFinanceEntity> list = xmFinanceService.selectXmFinanceList(dto);
			AtomicInteger jjj = new AtomicInteger(1);
			for (XmFinanceEntity xm : list) {
				futureList.add(CompletableFuture.runAsync(() -> {
					RequestContextHolder.setRequestAttributes(requestAttributes);
					generateD7(path8, jjj.getAndIncrement(), xm);
				}));
			}
		}

		futureList.add(CompletableFuture.runAsync(() -> {
			RequestContextHolder.setRequestAttributes(requestAttributes);
			if (finalTypes.contains(9)) {
				//9 高新研发人员与科技人员资料：改成高新科技人员资料：即科技人员管理-年高新科技人员汇总表资料表，选出：对外报表-高新口径研发费用报表-高新-研发项目清单中项目人员汇总
				generateD9(Paths.get(basePath.toString(), "9.高新科技人员资料"), year, finalArchiveAttach.getD6());
			}
			if (finalTypes.contains(10)) {
				//10 加计扣除研发人员与科技人员资料：改成加计扣除项目科研人员资料：即科技人员管理-项目人员汇总表，选出：对外报表-加计扣除口径研发费用报表-加计扣除-研发项目清单中项目人员汇总
				generateD10(Paths.get(basePath.toString(), "10.加计扣除项目科研人员资料"), year);
			}
		}));

		futureList.add(CompletableFuture.runAsync(() -> {
			RequestContextHolder.setRequestAttributes(requestAttributes);
			if (finalTypes.contains(11)) {
				//11 全部知识产权资料（汇总表、附件）：当年度所有科研成果列表导出，及所有附件资料的下载
				generateD11(Paths.get(basePath.toString(), "11.全部知识产权资料"), 0, year);
			}
			if (finalTypes.contains(12)) {
				//12 高新项目知识产权资料（汇总表、附件）：对外报表-高新口径研发费用报表-高新-研发项目清单中的科研成果列表及所有附件资料的下载
				generateD11(Paths.get(basePath.toString(), "12.高新项目知识产权资料"), 2, year);
			}
			if (finalTypes.contains(13)) {
				//13 加计扣除项目知识产权资料（汇总表、附件）：对外报表-加计扣除口径研发费用报表-加计扣除-研发项目清单中的科研成果列表及所有附件资料的下载
				generateD11(Paths.get(basePath.toString(), "13.加计扣除项目知识产权资料"), 3, year);
			}

		}));

		futureList.add(CompletableFuture.runAsync(() -> {
			RequestContextHolder.setRequestAttributes(requestAttributes);
			if (finalTypes.contains(14)) {
				//14 会计口径研发费用辅助账：对外报表-会计加计扣除口径研发费用报表-会计-研发支出辅助账
				generateD14(Paths.get(basePath.toString(), "14.会计口径研发费用辅助账"), year);
			}
			if (finalTypes.contains(15)) {
				//15 高新口径研发费用辅助账：对外报表-高新口径研发费用报表-高新-研发支出辅助账
				generateD15(Paths.get(basePath.toString(), "15.高新口径研发费用辅助账"), year, finalArchiveAttach.getD9());
			}
			if (finalTypes.contains(16)) {
				//16 加计扣除口径研发费用辅助账：对外报表-加计扣除口径研发费用报表-加计扣除-研发支出辅助账
				generateD16(Paths.get(basePath.toString(), "16.加计扣除口径研发费用辅助账"), year);
			}
		}));
		if (finalTypes.contains(17)) {
			//17.会计口径研发费用附件凭证资料及相关说明：对外报表-会计加计扣除口径研发费用报表-会计-研发项目（见列表详细）
			Path path17 = FileUtil.mkdir(Paths.get(basePath.toString(), "17.会计口径研发费用附件支撑资料及相关说明"));
			try {
				XmFinanceEntity dto2 = new XmFinanceEntity();
				dto2.setYearAndMonth(year);
				dto2.setType(1);
				generateD17(path17, xmFinanceService.selectXmFinanceList(dto2), year, futureList);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		if (finalTypes.contains(18)) {
			//18.高新研发费用附件凭证资料及相关说明：对外报表-高新口径研发费用报表-高新-研发项目（见列表详细）
			Path path18 = FileUtil.mkdir(Paths.get(basePath.toString(), "18.高新研发费用附件支持资料及相关说明"));
			try {
				XmFinanceEntity dto2 = new XmFinanceEntity();
				dto2.setYearAndMonth(year);
				dto2.setType(3);
				generateD17(path18, xmFinanceService.selectXmFinanceList(dto2), year, futureList);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		if (finalTypes.contains(19)) {
			//19.加计扣除研发费用附件凭证资料及相关说明：对外报表-加计扣除口径研发费用报表-加计扣除-研发项目（见列表详细）
			Path path19 = FileUtil.mkdir(Paths.get(basePath.toString(), "19.加计扣除研发费用附件支撑资料及相关说明"));
			try {
				XmFinanceEntity dto2 = new XmFinanceEntity();
				dto2.setYearAndMonth(year);
				dto2.setType(2);
				generateD17(path19, xmFinanceService.selectXmFinanceList(dto2), year, futureList);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		if (finalTypes.contains(20)) {
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				//20.A107012研发费用加计扣除优惠明细表：A107012导出表
				generateD20(Paths.get(basePath.toString(), "20.A107012研发费用加计扣除优惠明细表"), year);
			}));
		}
		futureList.add(CompletableFuture.runAsync(() -> {
			RequestContextHolder.setRequestAttributes(requestAttributes);
			if (finalTypes.contains(21)) {
				//21.当年和前两个会计年度研发费用总额及占同期销售收入比例的说明：附件补充
				Path path21 = FileUtil.mkdir(Paths.get(basePath.toString(), "21.当年和前两个会计年度研发费用总额及占同期销售收入比例的说明"));
				this.downloadAttachFiles(path21, Collections.singletonList(finalArchiveAttach.getD7()));
			}
			if (finalTypes.contains(22)) {
				//22.年度主要产品(服务)发挥核心支持作用的技术属于《国家重点支持的高新技术领域》规定范围的说明：附件补充
				Path path22 = FileUtil.mkdir(Paths.get(basePath.toString(), "22.年度主要产品(服务)发挥核心支持作用的技术属于《国家重点支持的高新技术领域》规定范围的说明"));
				this.downloadAttachFiles(path22, Collections.singletonList(finalArchiveAttach.getD4()));
			}
			if (finalTypes.contains(23)) {
				//23.高新技术产品(服务)及对应收入资料：附件补充
				Path path23 = FileUtil.mkdir(Paths.get(basePath.toString(), "23.高新技术产品(服务)及对应收入资料"));
				this.downloadAttachFiles(path23, Collections.singletonList(finalArchiveAttach.getD5()));
			}
			if (finalTypes.contains(24)) {
				//24.研发管理制度：附件补充
				Path path24 = FileUtil.mkdir(Paths.get(basePath.toString(), "24.研发管理制度"));
				this.downloadAttachFiles(path24, Collections.singletonList(finalArchiveAttach.getD8()));
			}
			if (finalTypes.contains(25)) {
				//25.高新项目技术鉴定资料：附件补充
				Path path25 = FileUtil.mkdir(Paths.get(basePath.toString(), "25.高新项目技术鉴定资料"));
				this.downloadAttachFiles(path25, Collections.singletonList(finalArchiveAttach.getD1()));
			}
			if (finalTypes.contains(26)) {
				//26.加计扣除项目技术鉴定资料：附件补充
				Path path26 = FileUtil.mkdir(Paths.get(basePath.toString(), "26.加计扣除项目技术鉴定资料"));
				this.downloadAttachFiles(path26, Collections.singletonList(finalArchiveAttach.getD2()));
			}
			if (finalTypes.contains(27)) {
				//27.其他高新备查资料：附件补充
				Path path27 = FileUtil.mkdir(Paths.get(basePath.toString(), "27.其他高新备查资料"));
				this.downloadAttachFiles(path27, Collections.singletonList(finalArchiveAttach.getD11()));
			}
			if (finalTypes.contains(28)) {
				//28.其他加计扣除备查资料：附件补充
				Path path28 = FileUtil.mkdir(Paths.get(basePath.toString(), "28.其他加计扣除备查资料"));
				this.downloadAttachFiles(path28, Collections.singletonList(finalArchiveAttach.getD12()));
			}
		}));
		CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
		log.info("一键导出耗时：{}", (new Date().getTime() - date.getTime()) / 1000 + "秒");


		Path zipPath = Paths.get(archiveDir,year+"年" + dir + ".zip");
		try {
			ZipUtil.zip(basePath.toString(), zipPath.toString());
		} catch (IORuntimeException e) {
			log.error("创建zip文件失败，{}", e.getLocalizedMessage());
		}


		//设置任务状态为 已完成
			task.setStatus(2);
			task.setDoneTime(new Date());
 			task.setZipUrl(zipPath.toString());
		task.setFileSize(FileUtil.size(FileUtil.file(zipPath.toString())));
		downloadTaskMapper.updateById(task);
	}

	private void generateD17(Path path, List<XmFinanceEntity> list, String year, List<CompletableFuture<Void>> futureList) {
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		for (XmFinanceEntity xm : list) {
			Long xmId = xm.getXmId();

			//创建项目文件夹
			Path xmmcPath = FileUtil.mkdir(FileUtil.mkdir(Paths.get(path.toString(), xm.getXmmc())));

			//1.人员人工费用
			Path path17_1 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "1.人员人工费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				//1-1.每月研发人员工资
				generateD17_1_1(path17_1, year, xmId);
			}));

			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				//1-2.每月研发人员出勤
				generateD17_1_2(path17_1, year, xmId);
			}));

			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				//1-3.每月研发工时打卡
				generateD17_1_3(path17_1, year, xmId);
			}));

			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				//1-4.人工费用分配表
				generateD17_1_4(path17_1, year, xmId);
			}));

			//2.直接投入费用
			Path path17_2 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "2.直接投入费用"));

			//2-1.研发材料燃料动力费用
			Path path17_2_1 = FileUtil.mkdir(Paths.get(path17_2.toString(), "1.研发材料燃料动力费用"));
			//2-1-1.每月领料燃料动力明细
			Path path17_2_1_1 = FileUtil.mkdir(Paths.get(path17_2_1.toString(), "1.每月领料燃料动力明细"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				////2-1-1.每月领料燃料动力明细
				generateD17_2_1_1(path17_2_1_1, year, xmId);
			}));

			//2-1-2.研发领料单
			Path path17_2_1_2 = FileUtil.mkdir(Paths.get(path17_2_1.toString(), "2.研发领料单"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generateD17_2_1_2(year, path17_2_1_2, xm.getXmId(), "材料");
			}));

			//2-1-3.研发燃料耗用单
			Path path17_2_1_3 = FileUtil.mkdir(Paths.get(path17_2_1.toString(), "3.研发燃料耗用单"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generateD17_2_1_2(year, path17_2_1_3, xmId, "燃料");
			}));

			//2-1-4.研发动力耗用单
			Path path17_2_1_4 = FileUtil.mkdir(Paths.get(path17_2_1.toString(), "4.研发动力耗用单"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generateD17_2_1_2(year, path17_2_1_4, xmId, "动力");
			}));

			//2-2.研发固定资产租赁费用
			Path path17_2_2 = FileUtil.mkdir(Paths.get(path17_2.toString(), "2.研发固定资产租赁费用"));
			//2-2-1.每月租赁资产费用明细
			Path path17_2_2_1 = FileUtil.mkdir(Paths.get(path17_2_2.toString(), "1.每月租赁资产费用明细"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generateD17_2_2_1(path17_2_2_1, year, xmId);
			}));

			//2-2-2.研发租赁费用分配表
			Path path17_2_2_2 = FileUtil.mkdir(Paths.get(path17_2_2.toString(), "2.研发租赁费用分配表"));

			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_2_2_2(year, path17_2_2_2, xmId);
			}));

			//2-3.每月直接投入费用
			Path path17_2_3 = FileUtil.mkdir(Paths.get(path17_2.toString(), "3.每月直接投入费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_2_3(path17_2_3, year, xmId);
			}));

			//3.折旧费用与长期待摊费用
			Path path17_3 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "3.折旧费用与长期待摊费用"));
			//3-1.每月仪器设备工时打卡
			Path path17_3_1 = FileUtil.mkdir(Paths.get(path17_3.toString(), "1.每月仪器设备工时打卡"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_3_1(path17_3_1, year, xmId);
			}));

			//3-2.仪器设备折旧费用分配表
			Path path17_3_2 = FileUtil.mkdir(Paths.get(path17_3.toString(), "2.仪器设备折旧费用分配表"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_3_2(path17_3_2, year, xmId);
			}));

			//3-3.在用建筑物折旧费用分配表
			Path path17_3_3 = FileUtil.mkdir(Paths.get(path17_3.toString(), "3.在用建筑物折旧费用分配表"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_3_3(path17_3_3, year, xmId);
			}));

			//3-4.长期待摊费用分配表
			Path path17_3_4 = FileUtil.mkdir(Paths.get(path17_3.toString(), "4.长期待摊费用分配表"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_3_4(path17_3_4, year, xmId);
			}));

			//4.无形资产摊销费用
			Path path17_4 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "4.无形资产摊销费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_4(path17_4, year, xmId);
			}));

			//5和6.设计费用、装备调试费用与试验费用
			Path path17_5 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "5和6.设计费用、装备调试费用与试验费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_5(path17_5, year, xmId);
			}));

			//7.其他费用
			Path path17_7 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "7.其他费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_7(path17_7, year, xmId);
			}));

			//8.委托外部研究开发费用
			Path path17_8 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "8.委托外部研究开发费用"));
			futureList.add(CompletableFuture.runAsync(() -> {
				RequestContextHolder.setRequestAttributes(requestAttributes);
				generate17_8(path17_8, year, xmId);
			}));
		}
	}

	@SneakyThrows
	private void generate17_8(Path path, String year, Long xmId) {
		XmWwxmCostQuery wwxmCost = new XmWwxmCostQuery();
		wwxmCost.setXmId(xmId);
		wwxmCost.setYearAndMonth(year);
		List<XmWwxmCostVO> wwxmCostList = wwxmCostService.selectPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), wwxmCost).getRecords();
		if (Func.isNotEmpty(wwxmCostList)) {
			wwxmCostService.export(new FileOutputStream(path + "/" + year + "年委托外部研究开发费用（全年）.xlsx"), wwxmCostList, wwxmCost.getYearAndMonth());
		}
	}

	@SneakyThrows
	private void generate17_7(Path path, String year, Long xmId) {
		XmOtherCostQuery otherCost = new XmOtherCostQuery();
		otherCost.setXmId(xmId);
		otherCost.setYearAndMonth(year);
		List<XmOtherCostEntity> otherCostList = xmOtherCostService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), otherCost).getRecords();
		if (Func.isNotEmpty(otherCostList)) {
			xmOtherCostService.exportXmOtherCost(new FileOutputStream(path + "/" + year + "年其他费用（全年）.xlsx"), otherCostList, otherCost.getYearAndMonth());
		}
	}

	@SneakyThrows
	private void generate17_5(Path path, String year, Long xmId) {
		XmDesignCostQuery designCost = new XmDesignCostQuery();
		designCost.setXmId(xmId);
		designCost.setYearAndMonth(year);
		List<XmDesignCostVO> designCostList = xmDesignCostService.selectXmDesignCostPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), designCost).getRecords();
		if (Func.isNotEmpty(designCostList)) {
			xmDesignCostService.exportXmDesignCost(new FileOutputStream(path + "/" + year + "年5和6.设计费用、装备调试费用与试验费用（全年）.xlsx"), designCostList, designCost.getYearAndMonth());
		}
	}

	@SneakyThrows
	private void generate17_4(Path path, String year, Long xmId) {
		XmAssetQueryParam wxzctxCost = new XmAssetQueryParam();
		wxzctxCost.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			wxzctxCost.setYearAndMonth(year + month);
			List<XmIntangibleAssetCostVo> wxzctxfyList = xmIntangibleAssetService.keyanwuxingzichantanxiaofeiyongfenpeibiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), wxzctxCost).getRecords();
			if (Func.isNotEmpty(wxzctxfyList)) {
				xmIntangibleAssetService.exportKeyanwuxingzichanfenpeibiao(new FileOutputStream(path + "/" + year + "年" + month + "月无形资产摊销费用分配表.xlsx"), wxzctxfyList, wxzctxCost.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_3_4(Path path, String year, Long xmId) {
		XmCqdtfyDTO xmCqdtfyDTO = new XmCqdtfyDTO();
		xmCqdtfyDTO.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			xmCqdtfyDTO.setYearAndMonth(year + month);
			List<XmCqdtfyVO> cqdtCostList = xmCqdtfyService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmCqdtfyDTO).getRecords();
			if (Func.isNotEmpty(cqdtCostList)) {
				xmCqdtfyService.exportXmCqdtfy(new FileOutputStream(path + "/" + year + "年" + month + "月长期待摊费用分配表.xlsx"), cqdtCostList, xmCqdtfyDTO.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_3_3(Path path, String year, Long xmId) {
		XmAssetQueryParam jzwCost = new XmAssetQueryParam();
		jzwCost.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			jzwCost.setYearAndMonth(year + month);
			List<XmFixedAssetCostVo> jzwList = xmFixedAssetService.keyanfangwujianzhuwuzhejiufeiyongfenpeibiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), jzwCost).getRecords();
			if (Func.isNotEmpty(jzwList)) {
				xmFixedAssetService.exportKeyanfangwujianzhuwuzhejiufeiyongfenpeibiao(new FileOutputStream(path + "/" + year + "年" + month + "月在用建筑物折旧费用分配表.xlsx"), jzwList, jzwCost.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_3_2(Path path, String year, Long xmId) {
		XmAssetQueryParam yqsbCost = new XmAssetQueryParam();
		yqsbCost.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			yqsbCost.setYearAndMonth(year + month);
			List<XmFixedAssetCostVo> yiqishebeiCostList = xmFixedAssetService.keyanyiqishebeizhejiufeiyongfenpeibiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), yqsbCost).getRecords();
			if (Func.isNotEmpty(yiqishebeiCostList)) {
				xmFixedAssetService.exportKeyanyiqishebeizhejiufeiyongfenpeibiao(new FileOutputStream(path + "/" + year + "年" + month + "月仪器设备折旧费用分配表.xlsx"), yiqishebeiCostList, yqsbCost.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_3_1(Path path, String year, Long xmId) {
		XmAssetHoursDto assetHoursDto = new XmAssetHoursDto();
		assetHoursDto.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			assetHoursDto.setYearAndMonth(year + month);
			List<XmAssetHoursVO> assetHoursList = hoursService.selectXmAssetHoursPage(assetHoursDto, Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE))).getRecords();
			if (Func.isNotEmpty(assetHoursList)) {
				hoursService.exportXmAssetHours(new FileOutputStream(path + "/" + year + "年" + month + "月仪器设备工时打卡.xlsx"), assetHoursList, assetHoursDto.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_2_3(Path path, String year, Long xmId) {
		XmDirectCostEntity xmDirectCost = new XmDirectCostEntity();
		xmDirectCost.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			xmDirectCost.setYearAndMonth(year + month);
			List<XmDirectCostEntity> xmDirectCostEntities = xmDirectCostService.selectXmDirectCostPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmDirectCost).getRecords();
			if (Func.isNotEmpty(xmDirectCostEntities)) {
				xmDirectCostService.exportXmDirectCost(new FileOutputStream(path + "/" + year + "年" + month + "月直接投入费用.xlsx"), xmDirectCostEntities);
			}
		}
	}

	private void generateD7(Path path, Integer index, XmFinanceEntity xm) {
		Long xmId = xm.getXmId();
		//创建项目文件夹
		Path xmmcPath = FileUtil.mkdir(Paths.get(path.toString(), index + "." + xm.getXmmc()));
		//1.项目立项
		generateD7_1(xmmcPath, xm);
		//2.研发预算编制
		Path path7_2 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "2.研发预算编制"));
		generateD7_2(path7_2, xmId);
		//2-1.人员人工费用
		generateD7_2_1(path7_2, xmId);
		//2-2.直接投入费用
		generateD7_2_2(path7_2, xmId);
		//2-3.折旧费用与长期待摊费用
		generateD7_2_3(path7_2, xmId);
		//2-4.无形资产摊销费用
		generateD7_2_4(path7_2, xmId);
		//2-5.设计费用
		generateD7_2_5(path7_2, xmId);
		//2-6.装备调试费用与实验费用
		generateD7_2_6(path7_2, xmId);
		//2-7.委托外研究开发费
		generateD7_2_7(path7_2, xmId);
		//2-8.其他费用
		generateD7_2_8(path7_2, xmId);
		//3.项目实施
		Path path7_3 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "3.项目实施"));
		generateD7_3(path7_3, xmId);
		//4.项目变更
		Path path7_4 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "4.项目变更"));
		generateD7_4(path7_4, xm);
		//5.项目结题
		Path path7_5 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "5.项目结题"));
		generateD7_5(path7_5, xm);
		//6.项目成果
		Path path7_6 = FileUtil.mkdir(Paths.get(xmmcPath.toString(), "6.项目成果"));
		generateD7_6(path7_6, xm);
		//7.委外项目
		generateD7_7(FileUtil.mkdir(Paths.get(xmmcPath.toString(), "7.委外项目")), xm);
	}

	private boolean generateD14(Path path, String year) {
		try {
			FileUtil.mkdir(path);
			String yearAndMonth = year + "12";
			XmCostDetailsDTO dto = new XmCostDetailsDTO();
			dto.setYearAndMonth(yearAndMonth);
			List<FinanceCostSummary> summaryList = xmCostDetailsService.financeCostSummary(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), dto).getRecords();
			if (Func.isNotEmpty(summaryList)) {
				xmCostDetailsService.exportFinanceCostSummary(new FileOutputStream(path + "/会计口径研发费用辅助账汇总表（12月）.xlsx"), summaryList, dto.getYearAndMonth());
			}
			List<FinanceCostDetailVO> detailList = xmCostDetailsService.financeCostDetail(dto);
			for (FinanceCostDetailVO vo : detailList) {
				dto.setXmId(vo.getXmId());
				xmCostDetailsService.exportFinanceCostDetail(new FileOutputStream(path + "/" + vo.getXmmc() + "-会计口径研发费用辅助账（12月）.xlsx"), vo, dto.getYearAndMonth());
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private boolean generateD15(Path path, String year, String attchD9) {
		try {
			FileUtil.mkdir(path);
			String yearAndMonth = year + "12";
			XmCostDetailsDTO dto = new XmCostDetailsDTO();
			dto.setYearAndMonth(yearAndMonth);
			//高新口径研发费用辅助账汇总表（12月）.xlsx
			List<HighTechCostSummary> summaryList = xmCostDetailsService.highTechCostSummary(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), dto).getRecords();
			if (Func.isNotEmpty(summaryList)) {
				xmCostDetailsService.exportHighTechCostSummary(new FileOutputStream(path + "/高新口径研发费用辅助账汇总表（12月）.xlsx"), summaryList, dto.getYearAndMonth());
			}
			//高新口径研发费用辅助账（12月）.xlsx
			List<HighTechCostDetailVO> detailList = xmCostDetailsService.highTechCostDetail(dto);
			for (HighTechCostDetailVO vo : detailList) {
				dto.setXmId(vo.getXmId());
				xmCostDetailsService.exportHighTechCostDetail(new FileOutputStream(path + "/" + vo.getXmmc() + "-高新口径研发费用辅助账（12月）.xlsx"), vo, dto.getYearAndMonth());
			}
			//下载研发费用结构明细表
			this.downloadAttachFiles(path, Collections.singletonList(attchD9));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private boolean generateD16(Path path, String year) {
		try {
			FileUtil.mkdir(path);
			String yearAndMonth = year + "12";
			XmCostDetailsDTO dto = new XmCostDetailsDTO();
			dto.setYearAndMonth(yearAndMonth);
			//加计扣除口径研发费用辅助账汇总表（12月）.xlsx
			DeductionCostSummary summary = xmCostDetailsService.deductionCostSummary(dto);
			xmCostDetailsService.exportDeductionCostSummary(new FileOutputStream(path + "/加计扣除口径研发费用辅助账汇总表（12月）.xlsx"), summary, dto.getYearAndMonth());

			//加计扣除口径研发费用辅助账（12月）.xlsx
			//1.费用化，2.资本化
			dto.setType(1);
			List<DeductionCostDetailVO> fyhList = xmCostDetailsService.deductionCostDetail(dto);
			for (DeductionCostDetailVO vo : fyhList) {
				dto.setXmId(vo.getXmId());
				xmCostDetailsService.exportDeductionCostDetail(new FileOutputStream(path + "/" + vo.getXmmc() + "-费用化-加计扣除口径研发费用辅助账（12月）.xlsx"), vo, dto.getYearAndMonth());
			}
			dto.setType(2);
			List<DeductionCostDetailVO> zbhList = xmCostDetailsService.deductionCostDetail(dto);
			for (DeductionCostDetailVO vo : zbhList) {
				dto.setXmId(vo.getXmId());
				xmCostDetailsService.exportDeductionCostDetail(new FileOutputStream(path + "/" + vo.getXmmc() + "-资本化-加计扣除口径研发费用辅助账（12月）.xlsx"), vo, dto.getYearAndMonth());
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private boolean generateD1(Path path, String year) {
		try {
			FileUtil.mkdir(path);
			SettingEntity one = settingMapper.selectOne(Wrappers.<SettingEntity>lambdaQuery().eq(SettingEntity::getYearAndMonth, year).eq(SettingEntity::getTenantId, SecureUtil.getTenantId()));
			if (Func.notNull(one) && Func.isNotBlank(one.getHighTechUrl())) {
				String[] urlList = one.getHighTechUrl().split(",");
				int i = 1;
				for (String s : urlList) {
					HttpUtil.downloadFile(s, path + "/高新技术企业资格证书_" + i + s.substring(s.lastIndexOf(".")));
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private boolean generateD5(Path path, String year, Integer type) {
		try {
			FileUtil.mkdir(path);
			FileOutputStream out = new FileOutputStream(path + "/" + (type == 3 ? "高新研发项目汇总表.xlsx" : "加计扣除研发项目汇总表.xlsx"));
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			dto.setType(type);
			xmFinanceService.exportFinance(out, dto);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private void downloadAttachFiles(Path dest, List<String> attachList) {
		Map<String, Integer> attachMap = new ConcurrentHashMap<>();
		for (String attach : attachList) {
			if (Func.isBlank(attach)) {
				continue;
			}
			List<JSONObject> tmp = JSON.parseArray(attach, JSONObject.class);
			for (JSONObject k : tmp) {
				String label = k.getString("label");
				String value = k.getString("value");
				if (attachMap.containsKey(label)) {
					String ext = FileUtil.extName(label);
					String prefix = FileUtil.getPrefix(label);
					attachMap.put(label, attachMap.get(label) + 1);
					label = prefix + "(" + attachMap.get(label) + ")" + "." + ext;
				} else {
					attachMap.put(label, 0);
				}
				HttpUtil.downloadFile(value, dest + "/" + label);
			}
		}
	}

	@SneakyThrows
	private void generateD7_1(Path path, XmFinanceEntity xm) {
		//1.项目立项
		Path path1 = FileUtil.mkdir(Paths.get(path.toString(), "1.项目立项"));
		FileOutputStream os = new FileOutputStream(path1 + "/" + xm.getXmmc() + "项目立项表.doc");
		xmService.exportApprovalInfo(os, xm.getXmId());
		//下载立项表中上传的附件
		this.downloadAttachFiles(path1, Arrays.asList(xm.getLxpw(), xm.getLxbg(), xm.getQtzl()));
	}

	@SneakyThrows
	private void generateD7_2(Path path, Long xmId) {
		//2.研发预算编制
		xmService.exportYszb(new FileOutputStream(path + "/" + "0.研发项目经费预算表.xlsx"), xmId);
	}

	@SneakyThrows
	private void generateD7_2_1(Path path, Long xmId) {
		//2-1.人员人工费用
		YsRyrgfyVO ysRyrgfyVO = new YsRyrgfyVO();
		ysRyrgfyVO.setXmId(xmId);
		ysRyrgfyService.exportYsRyrgfy(new FileOutputStream(path + "/" + "1.人员人工费用.xlsx"), ysRyrgfyVO);
	}

	@SneakyThrows
	private void generateD7_2_2(Path path, Long xmId) {
		//2-2.直接投入费用
		YsZjtrfyVO ysZjtrfyVO = new YsZjtrfyVO();
		ysZjtrfyVO.setXmId(xmId);
		ysZjtrfyService.exportYsZjtrfy(new FileOutputStream(path + "/" + "2.直接投入费用.xlsx"), ysZjtrfyVO);
	}

	@SneakyThrows
	private void generateD7_2_3(Path path, Long xmId) {
		//2-3.折旧费用与长期待摊费用
		YsZjfyycqdtfyVO ysZjfyycqdtfyVO = new YsZjfyycqdtfyVO();
		ysZjfyycqdtfyVO.setXmId(xmId);
		ysZjfyycqdtfyService.exportYsZjfyycqdtfy(new FileOutputStream(path + "/" + "3.折旧费用与长期待摊费用.xlsx"), ysZjfyycqdtfyVO);
	}

	@SneakyThrows
	private void generateD7_2_4(Path path, Long xmId) {
		//2-4.无形资产摊销费用
		YsWxzctxfyVO ysWxzctxfyVO = new YsWxzctxfyVO();
		ysWxzctxfyVO.setXmId(xmId);
		ysWxzctxfyService.exportYsWxzctxfy(new FileOutputStream(path + "/" + "4.无形资产摊销费用.xlsx"), ysWxzctxfyVO);
	}

	@SneakyThrows
	private void generateD7_2_5(Path path, Long xmId) {
		//2-5.设计费用
		YsSjfyVO ysSjfyVO = new YsSjfyVO();
		ysSjfyVO.setXmId(xmId);
		ysSjfyService.exportYsSjfy(new FileOutputStream(path + "/" + "5.设计费用.xlsx"), ysSjfyVO);
	}

	@SneakyThrows
	private void generateD7_2_6(Path path, Long xmId) {
		//2-6.装备调试费用与实验费用
		YsZbtsysyfyVO ysZbtsysyfyVO = new YsZbtsysyfyVO();
		ysZbtsysyfyVO.setXmId(xmId);
		ysZbtsysyfyService.exportYsZbtsysyfy(new FileOutputStream(path + "/" + "6.装备调试费用与实验费用.xlsx"), ysZbtsysyfyVO);
	}

	@SneakyThrows
	private void generateD7_2_7(Path path, Long xmId) {
		//2-7.委托外研究开发费
		YsWtwbyjkffyVO ysWtwbyjkffyVO = new YsWtwbyjkffyVO();
		ysWtwbyjkffyVO.setXmId(xmId);
		ysWtwbyjkffyService.exportYsWtwbyjkffy(new FileOutputStream(path + "/" + "7.委托外研究开发费.xlsx"), ysWtwbyjkffyVO);
	}

	@SneakyThrows
	private void generateD7_2_8(Path path, Long xmId) {
		//2-8.其他费用
		YsQtfyVO ysQtfyVO = new YsQtfyVO();
		ysQtfyVO.setXmId(xmId);
		ysQtfyService.exportYsQtfy(new FileOutputStream(path + "/" + "8.其他费用.xlsx"), ysQtfyVO);
	}

	@SneakyThrows
	private void generateD7_3(Path path, Long xmId) {
		//3.项目实施
		XmJdxbgEntity xmJdxbgEntity = new XmJdxbgEntity();
		xmJdxbgEntity.setXmId(xmId);
		List<XmJdxbgVO> xmJdxbgVOList = xmJdxbgService.selectByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmJdxbgEntity).getRecords();

		Map<String, Integer> fileNameMap = new ConcurrentHashMap<>();
		List<String> attachList = new ArrayList<>();
		for (XmJdxbgVO vo : xmJdxbgVOList) {
			XmEntity xmEntity = vo.getXmEntity();
			String fileName = xmEntity.getXmmc() + "-" + DictCache.getValue("项目实施-阶段性报告-附件类型", vo.getType()) + ".doc";
			if (fileNameMap.containsKey(fileName)) {
				fileNameMap.put(fileName, fileNameMap.get(fileName) + 1);
				fileName = xmEntity.getXmmc() + "-" + DictCache.getValue("项目实施-阶段性报告-附件类型", vo.getType()) + "(" + fileNameMap.get(fileName) + ").doc";
			} else {
				fileNameMap.put(fileName, 0);
			}
			FileOutputStream outputStream = new FileOutputStream(path + "/" + fileName);
			xmJdxbgService.exportXmJdxbgDoc(outputStream, vo);

			//将所有附件放到容器中
			attachList.add(vo.getAttachment());
		}
		//下载附件
		this.downloadAttachFiles(path, attachList);
	}

	@SneakyThrows
	private void generateD7_4(Path path, XmFinanceEntity xm) {
		//4.项目变更
		XmBgrzEntity xmBgrzEntity = new XmBgrzEntity();
		xmBgrzEntity.setXmId(xm.getXmId());
		List<XmBgrzVO> xmBgrzVOList = xmBgrzService.selectBgrzPage(xmBgrzEntity, Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE))).getRecords();
		List<String> attachList = new ArrayList<>();
		Map<String, Integer> fileNameMap = new ConcurrentHashMap<>();
		for (XmBgrzVO vo : xmBgrzVOList) {
			String fileName = xm.getXmmc() + "-" + vo.getZdmcStr() + "变更" + DateUtil.format(vo.getBgsxsj(), DateUtil.PATTERN_YYYYMMDD) + ".doc";
			if (fileNameMap.containsKey(fileName)) {
				fileNameMap.put(fileName, fileNameMap.get(fileName) + 1);
				fileName = xm.getXmmc() + "-" + vo.getZdmcStr() + "变更" + DateUtil.format(vo.getBgsxsj(), DateUtil.PATTERN_YYYYMMDD) + "(" + fileNameMap.get(fileName) + ").doc";
			} else {
				fileNameMap.put(fileName, 0);
			}
			xmBgrzService.exportXmBgrzDoc(new FileOutputStream(path + "/" + fileName), vo);

			attachList.add(vo.getAttachment());
		}
		this.downloadAttachFiles(path, attachList);
	}

	@SneakyThrows
	private void generateD7_5(Path path, XmFinanceEntity xm) {
		//5.项目结题
		XmJtbDTO xmJtbDTO = new XmJtbDTO();
		xmJtbDTO.setXmId(xm.getXmId());
		XmJtbVO xmJtbVO = xmJtbService.selectByCondition(xmJtbDTO);
		if (xmJtbVO != null) {
			xmJtbService.exportXmJtbDoc(new FileOutputStream(path + "/" + xm.getXmmc() + "-项目结题表.doc"), xmJtbVO);
			this.downloadAttachFiles(path, Arrays.asList(xmJtbVO.getYsbg(), xmJtbVO.getJsbg(), xmJtbVO.getCgbg(), xmJtbVO.getXybg(), xmJtbVO.getYspw()));
		}
	}

	@SneakyThrows
	private void generateD7_7(Path path, XmFinanceEntity xm) {
		//7.委外项目
		XmWwxmDTO xmWwxmDTO = new XmWwxmDTO();
		xmWwxmDTO.setXmId(xm.getXmId());
		xmWwxmDTO.setYearAndMonth(xm.getYearAndMonth());
		List<XmWwxmVO> wwxmVOList = xmWwxmService.selectPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmWwxmDTO).getRecords();
		if (Func.isNotEmpty(wwxmVOList)) {
			wwxmVOList.forEach(vo -> {
				vo.setXmmc(xm.getXmmc());
				vo.setXmbh(xm.getXmbh());
			});
			xmWwxmService.exportWwxm(new FileOutputStream(path + "/" + xm.getXmmc() + "-委外项目.xlsx"), wwxmVOList);
			//下载附件
			List<String> attachList = new ArrayList<>();
			for (XmWwxmVO vo : wwxmVOList) {
				attachList.addAll(Arrays.asList(vo.getJshtxy(), vo.getWwfyfp(), vo.getJshtdjzm(), vo.getStfjfcg(), vo.getQtzl()));
			}
			this.downloadAttachFiles(path, attachList);
		}
	}

	@SneakyThrows
	private void generateD7_6(Path path, XmFinanceEntity xm) {
		//6.项目成果
		List<XmCGSummary> xmCGSummaryList = cgQtService.xmCgSummary(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xm.getXmId()).getRecords();
		if (Func.isNotEmpty(xmCGSummaryList)) {
			cgQtService.exportXmCgSummary(new FileOutputStream(path + "/" + xm.getXmmc() + "-项目成果.xlsx"), xmCGSummaryList);
			List<String> attachList = new ArrayList<>();
			for (XmCGSummary xmCGSummary : xmCGSummaryList) {
				attachList.add(xmCGSummary.getAttachment());
			}
			//下载附件
			this.downloadAttachFiles(path, attachList);
		}
	}

	private boolean generateD9(Path path, String year, String attchD6) {
		try {
			FileUtil.mkdir(path);
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			//2:高科技人员资料
			dto.setType(2);
			List<XmFinanceEntity> list = xmFinanceService.selectXmFinanceList(dto);
			List<Long> xmIdList = list.stream().map(XmFinanceEntity::getXmId).toList();
			if (Func.isNotEmpty(xmIdList)) {
				TechnicianDTO param = new TechnicianDTO();
				param.setYearAndMonth(year);
				param.setXmIdList(xmIdList);
				List<TechnicianVO> ndgxkjryhzbList = technicianService.niandugaokejirenyuanhuizongbiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), param).getRecords();
				if (Func.isNotEmpty(ndgxkjryhzbList)) {
					technicianService.exportNdgkjryhzb(new FileOutputStream(path + "/" + "科技人员管理-年度高新科技人员汇总.xlsx"), ndgxkjryhzbList, year);
				}

				XmTechnicianEntity xmTechnicianEntity = new XmTechnicianEntity();
				xmTechnicianEntity.setYearAndMonth(year);
				xmTechnicianEntity.setXmIdList(xmIdList);
				List<XmTechnicianSummary> xmcyryList = technicianService.xiangmucanyanrenyuanhuizongbiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmTechnicianEntity).getRecords();
				if (Func.isNotEmpty(xmcyryList)) {
					technicianService.exportXmcyryhzb(new FileOutputStream(path + "/" + "科技人员管理-项目人员汇总.xlsx"), xmcyryList, year);
				}
				//年度职工和科技人员情况说明.doc
				if (Func.isNotBlank(attchD6)) {
					this.downloadAttachFiles(path, Arrays.asList(attchD6));
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

	private boolean generateD10(Path path, String year) {
		try {
			FileUtil.mkdir(path);
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			//3:加计扣除人员资料
			dto.setType(3);
			List<XmFinanceEntity> list = xmFinanceService.selectXmFinanceList(dto);
			List<Long> xmIdList = list.stream().map(XmFinanceEntity::getXmId).toList();
			if (Func.isNotEmpty(xmIdList)) {
				XmTechnicianDto param = new XmTechnicianDto();
				param.setYearAndMonth(year);
				param.setXmIdList(xmIdList);
				List<XmTechnicianVO> cyryhzList = technicianService.canyanrenyuanhuamingce(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), param).getRecords();
				if (Func.isNotEmpty(cyryhzList)) {
					technicianService.exportCyryhmc(new FileOutputStream(path + "/" + "科技人员管理-参研人员汇总.xlsx"), cyryhzList, year);
				}

				XmTechnicianEntity xmTechnicianEntity = new XmTechnicianEntity();
				xmTechnicianEntity.setYearAndMonth(year);
				xmTechnicianEntity.setXmIdList(xmIdList);
				List<XmTechnicianSummary> xmcyryList = technicianService.xiangmucanyanrenyuanhuizongbiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmTechnicianEntity).getRecords();
				if (Func.isNotEmpty(xmcyryList)) {
					technicianService.exportXmcyryhzb(new FileOutputStream(path + "/" + "科技人员管理-项目人员汇总.xlsx"), xmcyryList, year);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}


	@SneakyThrows
	private boolean generateD11(Path path, Integer type, String year) {
		//type,0:全部知识产权资料,2:高新项目知识产权资料,3:加计扣除项目知识产权资料
		FileUtil.mkdir(path);

		List<Long> xmIdList = new ArrayList<>();
		if (Arrays.asList(2, 3).contains(type)) {
			XmFinanceEntity dto = new XmFinanceEntity();
			dto.setYearAndMonth(year);
			dto.setType(type);
			List<XmFinanceEntity> list = xmFinanceService.selectXmFinanceList(dto);
			xmIdList = list.stream().map(XmFinanceEntity::getXmId).toList();
			if (Func.isEmpty(xmIdList)) {
				return true;
			}
		}
		CgZlEntity cgZlEntity = new CgZlEntity();
		cgZlEntity.setXmIdList(xmIdList);
		List<CgZlEntity> cgzlList = zlService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), cgZlEntity).getRecords();
		if (Func.isNotEmpty(cgzlList)) {
			zlService.exportZl(new FileOutputStream(path + "/" + "1.专利.xlsx"), cgzlList);
			List<String> attachList = new ArrayList<>();
			for (CgZlEntity tmp : cgzlList) {
				attachList.add(tmp.getAttachment());
			}
			this.downloadAttachFiles(Paths.get(path.toString(), "1.专利附件"), attachList);
		}

		CgRjzzqDTO cgRjzzq = new CgRjzzqDTO();
		cgRjzzq.setXmIdList(xmIdList);
		List<CgRjzzqEntity> cgRjzzqEntityList = rjzzqService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), cgRjzzq).getRecords();
		if (Func.isNotEmpty(cgRjzzqEntityList)) {
			rjzzqService.export(new FileOutputStream(path + "/" + "2.软件著件权.xlsx"), cgRjzzqEntityList);
			List<String> attachList = new ArrayList<>();
			for (CgRjzzqEntity tmp : cgRjzzqEntityList) {
				attachList.add(tmp.getAttachment());
			}
			this.downloadAttachFiles(Paths.get(path.toString(), "2.软件著作权附件"), attachList);
		}

		CgJsbzEntity cgJsbz = new CgJsbzEntity();
		cgJsbz.setXmIdList(xmIdList);
		List<CgJsbzEntity> cgJsbzEntityList = jsbzService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), cgJsbz).getRecords();
		if (Func.isNotEmpty(cgJsbzEntityList)) {
			jsbzService.export(new FileOutputStream(path + "/" + "3.技术标准.xlsx"), cgJsbzEntityList);
			List<String> attachList = new ArrayList<>();
			for (CgJsbzEntity tmp : cgJsbzEntityList) {
				attachList.add(tmp.getAttachment());
			}
			this.downloadAttachFiles(Paths.get(path.toString(), "3.技术标准附件"), attachList);
		}

		CgKylwEntity cgKylw = new CgKylwEntity();
		cgKylw.setXmIdList(xmIdList);
		List<CgKylwEntity> cgKylwEntityList = kylwService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), cgKylw).getRecords();
		if (Func.isNotEmpty(cgKylwEntityList)) {
			kylwService.export(new FileOutputStream(path + "/" + "4.科研论文.xlsx"), cgKylwEntityList);
			List<String> attachList = new ArrayList<>();
			for (CgKylwEntity tmp : cgKylwEntityList) {
				attachList.add(tmp.getAttachment());
			}
			this.downloadAttachFiles(Paths.get(path.toString(), "4.科研论文附件"), attachList);
		}

		CgQtDTO cgQtDTO = new CgQtDTO();
		cgQtDTO.setXmIdList(xmIdList);
		List<CgQtEntity> cgQtEntityList = qtService.selectPageByCondition(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), cgQtDTO).getRecords();
		if (Func.isNotEmpty(cgQtEntityList)) {
			cgQtService.export(new FileOutputStream(path + "/" + "5.其他成果.xlsx"), cgQtEntityList);
			List<String> attachList = new ArrayList<>();
			for (CgKylwEntity tmp : cgKylwEntityList) {
				attachList.add(tmp.getAttachment());
			}
			this.downloadAttachFiles(Paths.get(path.toString(), "5.其他成果附件"), attachList);
		}

		return true;
	}

	@SneakyThrows
	private void generateD17_1_1(Path path, String year, Long xmId) {
		//1-1.每月研发人员工资
		Path path1_1 = FileUtil.mkdir(Paths.get(path.toString(), "1.每月研发人员工资"));
		SalaryDTO salaryDTO = new SalaryDTO();
		salaryDTO.setXmId(xmId);
		String month = null;
		for (int i = 1; i <= 12; i++) {
			month = (i < 10 ? "0" + i : i + "");
			String yearAndMonth = year + month;
			salaryDTO.setYearAndMonth(yearAndMonth);
			//查询项目参研人员的工资数据
			List<SalaryVO> salaryList = salaryService.selectSalaryPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), salaryDTO).getRecords();
			if (Func.isNotEmpty(salaryList)) {
				salaryService.exportSalary(new FileOutputStream(path1_1 + "/" + year + "年" + month + "月研发人员工资.xlsx"), salaryList, salaryDTO.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generateD17_1_2(Path path, String year, Long xmId) {
		//1-2.每月研发人员出勤
		Path path1_2 = FileUtil.mkdir(Paths.get(path.toString(), "2.每月研发人员出勤"));
		AttendanceDto attendanceDto = new AttendanceDto();
		attendanceDto.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			attendanceDto.setYearAndMonth(year + month);
			List<AttendanceVO> attendanceList = attendanceService.selectAttendancePage(attendanceDto, Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE))).getRecords();
			if (Func.isNotEmpty(attendanceList)) {
				attendanceService.exportAttendance(new FileOutputStream(path1_2 + "/" + year + "年" + month + "月研发人员出勤.xlsx"), attendanceList, attendanceDto.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generateD17_1_3(Path path, String year, Long xmId) {
		//1-3.每月研发工时打卡
		Path path1_3 = FileUtil.mkdir(Paths.get(path.toString(), "3.每月研发工时打卡"));
		XmTechnicianHoursVO xmtechnicianHoursVO = new XmTechnicianHoursVO();
		xmtechnicianHoursVO.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			xmtechnicianHoursVO.setYearAndMonth(year + month);
			List<XmTechnicianHoursVO> xmTechnicianHoursVOList = xmTechnicianHoursService.selectPage(xmtechnicianHoursVO, Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE))).getRecords();
			if (Func.isNotEmpty(xmTechnicianHoursVOList)) {
				xmTechnicianHoursService.export(new FileOutputStream(path1_3 + "/" + year + "年" + month + "月研发工时打卡.xlsx"), xmTechnicianHoursVOList, xmtechnicianHoursVO.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generateD17_1_4(Path path, String year, Long xmId) {
		//1-4.人工费用分配表
		Path path1_4 = FileUtil.mkdir(Paths.get(path.toString(), "4.人工费用分配表"));
		XmTechnicianDto xmTechnicianDto = new XmTechnicianDto();
		xmTechnicianDto.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			xmTechnicianDto.setYearAndMonth(year + month);
			List<XmTechnicianSalaryVO> rgfyList = technicianService.meiyueyanfarengongfeiyongfeifenpeibiao(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmTechnicianDto).getRecords();
			if (Func.isNotEmpty(rgfyList)) {
				technicianService.exportMeiyueyanfarengongfeiyongfeifenpeibiao(new FileOutputStream(path1_4 + "/" + year + "年" + month + "月人工费用分配表.xlsx"), rgfyList, xmTechnicianDto.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generateD17_2_1_1(Path path, String year, Long xmId) {
		//2-1-1.每月领料燃料动力明细
		XmGoodsDTO dto = new XmGoodsDTO();
		dto.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			dto.setYearAndMonth(year + month);
			List<XmGoodsVO> list = xmGoodsService.selectXmGoodsPage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), dto).getRecords();
			if (Func.isNotEmpty(list)) {
				xmGoodsService.exportXmGoods(new FileOutputStream(path + "/" + year + "年" + month + "月领料燃料动力明细.xlsx"), list, dto.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generateD17_2_2_1(Path path, String year, Long xmId) {
		//2-2-1.每月租赁资产费用明细
		XmLeaseEntity xmLease = new XmLeaseEntity();
		xmLease.setXmId(xmId);
		for (int i = 1; i <= 12; i++) {
			String month = (i < 10 ? "0" + i : i + "");
			xmLease.setYearAndMonth(year + month);
			List<XmLeaseEntity> leaseList = xmLeaseService.selectXmLeasePage(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), xmLease).getRecords();
			if (Func.isNotEmpty(leaseList)) {
				xmLeaseService.exportXmLease(new FileOutputStream(path + "/" + year + "年" + month + "月租赁资产费用明细.xlsx"), leaseList, xmLease.getYearAndMonth());
			}
		}
	}

	@SneakyThrows
	private void generate17_2_2_2(String year, Path path, Long xmId) {
		for (int i = 1; i <= 12; i++) {
			String yearAndMonth = year + (i < 10 ? "0" + i : i);
			XmLeaseEntity param = new XmLeaseEntity();
			param.setYearAndMonth(yearAndMonth);
			param.setXmId(xmId);
			List<JSONObject> leaseList = xmLeaseService.yanfazulinzichanfeiyongfenpeibiao(param);
			if (Func.isEmpty(leaseList)) {
				continue;
			}
			for (JSONObject o : leaseList) {
				for (String key : o.keySet()) {
					String[] arr = key.split(":");
					String useDate = arr[1];
					FileOutputStream fos = new FileOutputStream(path + "/" + useDate + "研发租赁资产费用分配表.xlsx");
					param.setLeaseDate(DateUtil.parse(useDate, DateUtil.PATTERN_DATE));
					xmLeaseService.exportYanfazulinzichanfeiyongfenpeibiao(fos, param);
				}
			}
		}
	}

	@SneakyThrows
	private void generateD17_2_1_2(String year, Path path, Long xmId, String type) {
		String fileName = type.equals("材料") ? "领料单.xlsx" : (type.equals("动力") ? "研发动力耗用单" : "研发燃料耗用单") + ".xlsx";
		for (int i = 1; i <= 12; i++) {
			String yearAndMonth = year + (i < 10 ? "0" + i : i);
			XmGoodsDTO param = new XmGoodsDTO();
			param.setType(type);
			param.setYearAndMonth(yearAndMonth);
			param.setXmId(xmId);
			List<JSONObject> cailiaoList = xmGoodsService.yanfalingliaodan(param);
			if (Func.isEmpty(cailiaoList)) {
				continue;
			}
			for (JSONObject o : cailiaoList) {
				for (String key : o.keySet()) {
					String[] arr = key.split(":");
					String useDate = arr[1];
					FileOutputStream fos = new FileOutputStream(path + "/" + useDate + fileName);
					param = new XmGoodsDTO();
					param.setYearAndMonth(yearAndMonth);
					param.setType(type);
					param.setXmId(xmId);
					param.setUseDate(DateUtil.parse(useDate, DateUtil.PATTERN_DATE));
					xmGoodsService.exportYanfalingliaodan(fos, param);
				}
			}
		}
	}

	private boolean generateD20(Path path, String year) {
		//A107012研发费用加计扣除优惠明细表
		try {
			FileUtil.mkdir(path);
			try (FileOutputStream out = new FileOutputStream(Paths.get(path.toString(), "A107012研发费用加计扣除优惠明细表.xlsx").toString())) {
				enterpriseInfoService.exportYffyjjkcyhmxbA107012(out, year);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}

}
