/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.security.trans.projectBudgetManagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Preconditions;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.security.common.Constant;
import org.security.common.config.CommonProperties;
import org.security.common.util.DataFormatUtil;
import org.security.ht.entity.basic.Device;
import org.security.trans.basic.service.IDepartmentService;
import org.security.trans.basic.service.IDeviceService;
import org.security.trans.common.service.IFileService;
import org.security.trans.outsourcing.service.IOutCompanyService;
import org.security.trans.projectBudgetManagement.dto.ProjectDTO;
import org.security.trans.projectBudgetManagement.dto.ProjectOverReviewDTO;
import org.security.trans.projectBudgetManagement.entity.*;
import org.security.trans.projectBudgetManagement.service.*;
import org.security.trans.projectBudgetManagement.vo.*;
import org.security.trans.projectBudgetManagement.mapper.ProjectMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.security.trans.settings.entity.DeviceCategorySettings;
import org.security.trans.settings.service.IDeviceCategorySettingsService;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目管理-项目管理信息主表 服务实现类
 *
 * @author BladeX
 * @since 2022-08-05
 */
@Service
@Slf4j
@AllArgsConstructor
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

	private final IProjectPayPlanService projectPayPlanService;
	private final IFileService fileService;
	private final IProjectEstablishmentService projectEstablishmentService;
	private final IProjectPurchaseService projectPurchaseService;
	private final IProjectContractService projectContractService;
	private final IProjectImplementationService projectImplementationService;
	private final IProjectCheckService projectCheckService;
	private final IProjectOverHistoryService projectOverHistoryService;
	private final CommonProperties commonProperties;
	private final IDepartmentService departmentService;
	private final IOutCompanyService outCompanyService;
	private final IBudgetItemService budgetItemService;
	private final IDeviceCategorySettingsService deviceCategorySettingsService;
	private final IDeviceService deviceService;

	@Override
	public IPage<ProjectVO> selectProjectPage(IPage<ProjectVO> page, ProjectDTO projectDTO) {
		log.info("==============获取项目列表数据开始==============");
		List<ProjectVO> vos = baseMapper.selectProjectPage(page, projectDTO);
		//判断该登录用户是否具有项目结项同意或驳回权限
		if (Func.isNotEmpty(vos)) {
			vos.forEach(item -> {
				//获取上级机构安全员用户id
				List<String> aimUserIds = baseMapper.getSecurityUserIds(item.getDeptId(), commonProperties.getProjectRoleName());
				if (aimUserIds.contains(String.valueOf(AuthUtil.getUser().getUserId())) && Constant.PROJECT_NODE_OVER.equals(item.getProjectStatus())) {
					item.setOperateStatus(Constant.PROJECT_OVER_ONE);
				} else {
					item.setOperateStatus(Constant.PROJECT_OVER_TWO);
				}
			});
		}
		log.info("==============获取项目列表数据结束==============");
		return page.setRecords(vos);
	}

	@Override
	public ProjectVO getData(String id) {
		log.info("==============获取项目主体信息及项目付款计划数据开始==============");
		Project project = this.getById(id);
		//获取付款计划
		List<ProjectPayPlan> payPlanList = projectPayPlanService.list(new QueryWrapper<ProjectPayPlan>().lambda().eq(ProjectPayPlan::getProjectLinkId, id));
		List<ProjectPayPlanVO> payPlanVOList = Func.copy(payPlanList, ProjectPayPlanVO.class);
		if (Func.isNotEmpty(payPlanVOList)) {
			payPlanVOList.forEach(item -> {
				item.setPlanAmt(null == item.getPlanAmt() ? BigDecimal.ZERO : item.getPlanAmt().setScale(2, BigDecimal.ROUND_HALF_UP));
				item.setActualAmt(null == item.getActualAmt() ? BigDecimal.ZERO : item.getActualAmt().setScale(2, BigDecimal.ROUND_HALF_UP));
				//获取相关发票附件
				item.setRelevantAttachments(fileService.getAttachments(item.getId(), item.getInvoice()));
			});
		}
		ProjectVO vo = Func.copy(project, ProjectVO.class);
		Preconditions.checkArgument(Func.isNotEmpty(vo), "没有相关的项目信息");
		vo.setPayPlanList(payPlanVOList);
		log.info("==============获取项目主体信息及项目付款计划数据结束==============");
		return vo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean saveData(ProjectDTO projectDTO) {
		log.info("==============保存项目相关信息数据开始==============");
		String projectNode;
		Project project = Func.copy(projectDTO, Project.class);
		Preconditions.checkArgument(Func.isNotEmpty(project), "项目相关信息为空");
		project.setBudgetLinkName(baseMapper.getBudget(project.getBudgetLinkCode()));
		project.setDeptId(AuthUtil.getDeptId());
		project.setDeptName(departmentService.getById(AuthUtil.getDeptId()).getDeptName());
		//项目开始节点/项目原始节点
		projectNode = Func.isNotEmpty(project.getProjectStatus()) ? project.getProjectStatus() : Constant.PROJECT_NODE_START;
		//项目主体信息入库
		this.saveOrUpdate(project);
		//付款计划入库
		if (Func.isNotEmpty(projectDTO.getPayPlanList())) {
			savePayPlan(projectDTO, project);
		}
		//项目立项信息入库
		if (Func.isNotEmpty(projectDTO.getProjectEstablishment())) {
			projectNode = Integer.parseInt(project.getProjectStatus()) > Integer.parseInt(Constant.PROJECT_NODE_ESTABLISHMENT) ? project.getProjectStatus() : Constant.PROJECT_NODE_ESTABLISHMENT;
			saveProjectEstablishment(projectDTO, project);
		}
		//项目采购信息入库
		if (Func.isNotEmpty(projectDTO.getProjectPurchase())) {
			projectNode = Integer.parseInt(project.getProjectStatus()) > Integer.parseInt(Constant.PROJECT_NODE_PURCHASE) ? project.getProjectStatus() : Constant.PROJECT_NODE_PURCHASE;
			saveProjectPurchase(projectDTO, project);
		}
		//项目合同信息入库
		if (Func.isNotEmpty(projectDTO.getProjectContract())) {
			projectNode = Integer.parseInt(project.getProjectStatus()) > Integer.parseInt(Constant.PROJECT_NODE_CONTRACT) ? project.getProjectStatus() : Constant.PROJECT_NODE_CONTRACT;
			saveContract(projectDTO, project);
		}
		//项目实施信息入库
		if (Func.isNotEmpty(projectDTO.getProjectImplementation())) {
			projectNode = Integer.parseInt(project.getProjectStatus()) > Integer.parseInt(Constant.PROJECT_NODE_IMPLEMENTATION) ? project.getProjectStatus() : Constant.PROJECT_NODE_IMPLEMENTATION;
			saveImplementating(projectDTO, project);
		}
		//项目验收信息入库
		if (Func.isNotEmpty(projectDTO.getProjectCheck())) {
			projectNode = Integer.parseInt(project.getProjectStatus()) > Integer.parseInt(Constant.PROJECT_NODE_CHECK) ? project.getProjectStatus() : Constant.PROJECT_NODE_CHECK;
			saveProjectCheck(projectDTO, project);
		}
		project.setProjectStatus(projectNode);
		this.updateById(project);
		log.info("==============保存项目相关信息数据结束==============");
		return true;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeData(List<Long> toLongList) {
		log.info("==============删除项目相关信息数据开始==============");
		List<String> list = new ArrayList<>();
		toLongList.forEach(item -> {
			//删除付款计划及相关附件
			removePayPlan(list, item);
			//删除项目立项相关信息
			removeProjectEstablishment(list, item);
			//删除项目采购信息
			removeProjectPurchase(list, item);
			//删除项目合同信息
			removeProjectContract(list, item);
			//删除项目实施信息
			removeProjectImplementation(list, item);
			//删除项目验收信息
			removeProjectCheck(list, item);
		});
		//删除所有相关附件
		fileService.removeFileData(list);
		//删除项目主体信息
		boolean b = this.removeByIds(toLongList);
		log.info("==============删除项目相关信息数据结束==============");
		return b;
	}

	/**
	 * 删除项目验收信息
	 */
	private void removeProjectCheck(List<String> list, Long item) {
		ProjectCheck projectCheck = projectCheckService.getOne(new QueryWrapper<ProjectCheck>().lambda().eq(ProjectCheck::getProjectLinkId, item));
		if (Func.isNotEmpty(projectCheck)) {
			list.add(projectCheck.getId());
			projectCheckService.removeById(projectCheck.getId());
		}
	}

	/**
	 * 删除项目实施信息
	 */
	private void removeProjectImplementation(List<String> list, Long item) {
		ProjectImplementation projectImplementation = projectImplementationService.getOne(new QueryWrapper<ProjectImplementation>().lambda().eq(ProjectImplementation::getProjectLinkId, item));
		if (Func.isNotEmpty(projectImplementation)) {
			list.add(projectImplementation.getId());
			projectImplementationService.removeById(projectImplementation.getId());
		}
	}

	/**
	 * 删除项目合同信息
	 */
	private void removeProjectContract(List<String> list, Long item) {
		List<ProjectContract> projectContractList = projectContractService.list(new QueryWrapper<ProjectContract>().lambda().eq(ProjectContract::getProjectLinkId, item));
		if (Func.isNotEmpty(projectContractList)) {
			List<String> projectContract = new ArrayList<>();
			projectContractList.forEach(item3 -> {
				projectContract.add(item3.getId());
			});
			list.addAll(projectContract);
			projectContractService.removeByIds(projectContract);
		}
	}

	/**
	 * 删除项目采购信息
	 */
	private void removeProjectPurchase(List<String> list, Long item) {
		ProjectPurchase projectPurchase = projectPurchaseService.getOne(new QueryWrapper<ProjectPurchase>().lambda().eq(ProjectPurchase::getProjectLinkId, item));
		if (Func.isNotEmpty(projectPurchase)) {
			list.add(projectPurchase.getId());
			projectPurchaseService.removeById(projectPurchase.getId());
		}
	}

	/**
	 * 删除项目立项相关信息
	 */
	private void removeProjectEstablishment(List<String> list, Long item) {
		ProjectEstablishment projectEstablishment = projectEstablishmentService.getOne(new QueryWrapper<ProjectEstablishment>().lambda().eq(ProjectEstablishment::getProjectLinkId, item));
		if (Func.isNotEmpty(projectEstablishment)) {
			list.add(projectEstablishment.getId());
			projectEstablishmentService.removeById(projectEstablishment.getId());
		}
	}

	/**
	 * 删除付款计划及相关附件
	 */
	private void removePayPlan(List<String> list, Long item) {
		List<ProjectPayPlan> ProjectPayPlanList = projectPayPlanService.list(new QueryWrapper<ProjectPayPlan>().lambda().eq(ProjectPayPlan::getProjectLinkId, item));
		if (Func.isNotEmpty(ProjectPayPlanList)) {
			List<String> payPlan = new ArrayList<>();
			ProjectPayPlanList.forEach(item2 -> {
				payPlan.add(item2.getId());
			});
			list.addAll(payPlan);
			projectPayPlanService.removeByIds(payPlan);
		}
	}

	@Override
	public List<ProjectVO> getParentProject() {
		log.info("==============获取相关父级项目相关信息数据开始==============");
		List<Project> list = this.list(new QueryWrapper<Project>().lambda().eq(Project::getDeptId, AuthUtil.getDeptId()));
		List<ProjectVO> vos = Func.copy(list, ProjectVO.class);
		log.info("==============获取相关父级项目相关信息数据结束==============");
		return vos;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean projectOver(String id) {
		Project project = this.getById(id);
		project.setProjectStatus(Constant.PROJECT_NODE_OVER);
		//将项目节点变更为结项
		this.updateById(project);
		//新增一条项目结项流水记录
		ProjectOverHistory projectOverHistory = setProjectOverHistory(id, Constant.PROJECT_OVER, null);
		return projectOverHistoryService.save(projectOverHistory);
	}

	/**
	 * 设置结项操作流水记录
	 */
	private ProjectOverHistory setProjectOverHistory(String id, Integer aimStatus, String remark) {
		ProjectOverHistory projectOverHistory = new ProjectOverHistory();
		projectOverHistory.setOperationStatus(aimStatus);
		projectOverHistory.setProjectLinkId(id);
		projectOverHistory.setRemark(remark);
		projectOverHistory.setOperationUser(String.valueOf(AuthUtil.getUser().getUserId()));
		return projectOverHistory;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean projectOverReview(ProjectOverReviewDTO projectOverReviewDTO) {
		Project project = this.getById(projectOverReviewDTO.getId());
		//审阅-结项驳回，项目记录状态变为待结项状态
		if (Constant.PROJECT_OVER_REJECT.equals(projectOverReviewDTO.getReviewStatus())) {
			project.setProjectStatus(Constant.PROJECT_NODE_CHECK);
			this.updateById(project);
		}
		//审阅-同意结项，项目记录状态变为审阅通过状态
		if (Constant.PROJECT_OVER_AGREE.equals(projectOverReviewDTO.getReviewStatus())) {
			project.setProjectStatus(Constant.PROJECT_NODE_REVIEW);
			this.updateById(project);
		}
		//保存操作记录
		ProjectOverHistory projectOverHistory = setProjectOverHistory(projectOverReviewDTO.getId(), projectOverReviewDTO.getReviewStatus(), projectOverReviewDTO.getRemark());
		return projectOverHistoryService.save(projectOverHistory);
	}

	@Override
	public List<RemindDataVO> getRemindData() throws ParseException {
		ArrayList<RemindDataVO> vos = new ArrayList<>();
		//获取当前登录人机构的安全员用户id
		List<String> list = baseMapper.getAimUserIds(AuthUtil.getDeptId());
		if (Func.isNotEmpty(list) && list.contains(String.valueOf(AuthUtil.getUser().getUserId()))) {
			Date date = DataFormatUtil.getLocalDate();
			//获取设备维保提醒信息
			getDeviceRemindData(vos, date);
			//获取项目付款计划提醒
			getProjectPayPlanRemindData(vos, date);
			//合同到期提醒
			getProjectContractRemindData(vos, date);

		}
		return vos;
	}

	@Override
	public ProjectPayPlanVO getProjectPayPlanData(String id) {
		ProjectPayPlan projectPayPlan = projectPayPlanService.getById(id);
		ProjectPayPlanVO projectPayPlanVO = Func.copy(projectPayPlan, ProjectPayPlanVO.class);
		projectPayPlanVO.setProjectName(this.getById(projectPayPlan.getProjectLinkId()).getProjectName());
		projectPayPlanVO.setRelevantAttachments(fileService.getAttachments(projectPayPlan.getId(), projectPayPlan.getInvoice()));
		return projectPayPlanVO;
	}

	@Override
	public ProjectContractVO getProjectContractData(String id) {
		ProjectContract projectContract = projectContractService.getById(id);
		ProjectContractVO projectContractVO = Func.copy(projectContract, ProjectContractVO.class);
		projectContractVO.setProjectName(this.getById(projectContract.getProjectLinkId()).getProjectName());
		projectContractVO.setContractAttachments(fileService.getAttachments(projectContract.getId(), projectContract.getOriginalContract()));
		projectContractVO.setSupplementAttachments(fileService.getAttachments(projectContract.getId(), projectContract.getSupplementMaterials()));
		projectContractVO.setLegalAttachments(fileService.getAttachments(projectContract.getId(), projectContract.getAfterLegalDevice()));
		projectContractVO.setOtherAttachments(fileService.getAttachments(projectContract.getId(), projectContract.getOtherMaterials()));
		return projectContractVO;
	}

	/*
	 * 合同到期提醒
	 */
	private void getProjectContractRemindData(ArrayList<RemindDataVO> vos, Date date) {
		log.info("--------------------获取项目合同到期提醒开始--------------------");
		//获取合同到期提醒提前天数
		DictDataVO concatDeadlineRemind = baseMapper.getDictData(commonProperties.getConcatDeadlineRemindKeyName());
		if (Func.isNotEmpty(concatDeadlineRemind)) {
			log.info("合同到期提醒提前天数[{}]",concatDeadlineRemind.getDictValue());
			Date startDate = getRemindStartDate(date, Integer.valueOf(concatDeadlineRemind.getDictValue()));
			List<ProjectContract> projectContractList = projectContractService.list(new QueryWrapper<ProjectContract>().lambda()
				.eq(ProjectContract::getDeptId, AuthUtil.getDeptId())
				.le(Func.isNotEmpty(startDate), ProjectContract::getContractEndTime, startDate)
				.ge(Func.isNotEmpty(date), ProjectContract::getContractEndTime, date));
			log.info("即将到期的项目合同[{}]",projectContractList);
			if (Func.isNotEmpty(projectContractList)) {
				projectContractList.forEach(contract -> {
					RemindDataVO vo = new RemindDataVO();
					vo.setId(contract.getId());
					vo.setType("contract");
					vo.setTypeName("项目合同到期提醒");
					vo.setTitle(this.getById(contract.getProjectLinkId()).getProjectName());
					vo.setDeadline(contract.getContractEndTime());
					vo.setDeptName(departmentService.getById(contract.getDeptId()).getDeptName());
					vos.add(vo);
				});
			}
		}
		log.info("--------------------获取项目合同到期提醒结束--------------------");
	}

	/**
	 * 获取项目付款计划提醒
	 */
	private void getProjectPayPlanRemindData(ArrayList<RemindDataVO> vos, Date date) {
		log.info("--------------------获取项目付款计划提醒开始--------------------");
		//获取付款计划提醒提前天数
		DictDataVO payPlanRemind = baseMapper.getDictData(commonProperties.getPayPlanRemindKeyName());
		if (Func.isNotEmpty(payPlanRemind)) {
			log.info("付款计划提醒提前天数[{}]",payPlanRemind.getDictValue());
			Date startDate = getRemindStartDate(date, Integer.valueOf(payPlanRemind.getDictValue()));
			List<ProjectPayPlan> projectPayPlanList = projectPayPlanService.list(new QueryWrapper<ProjectPayPlan>().lambda()
				.eq(ProjectPayPlan::getDeptId, AuthUtil.getDeptId())
				.isNotNull(ProjectPayPlan::getPlanAmt)
				.le(Func.isNotEmpty(startDate), ProjectPayPlan::getPlanTime, startDate)
				.ge(Func.isNotEmpty(date), ProjectPayPlan::getPlanTime, date));
			log.info("即将到期的项目付款计划[{}]",projectPayPlanList);
			if (Func.isNotEmpty(projectPayPlanList)) {
				List<ProjectPayPlan> collect = projectPayPlanList.stream().filter(item -> Func.isNotEmpty(item.getActualAmt()) && (item.getActualAmt().compareTo(item.getPlanAmt()) < 0)).collect(Collectors.toList());
				collect.forEach(payPlan -> {
					RemindDataVO vo = new RemindDataVO();
					vo.setId(payPlan.getId());
					vo.setType("payPlan");
					vo.setTypeName("项目付款计划提醒");
					vo.setTitle(this.getById(payPlan.getProjectLinkId()).getProjectName());
					vo.setDeadline(payPlan.getPlanTime());
					vo.setDeptName(departmentService.getById(payPlan.getDeptId()).getDeptName());
					vos.add(vo);
				});
			}
		}
		log.info("--------------------获取项目付款计划提醒结束--------------------");
	}

	/**
	 * 获取设备维保提醒信息
	 */
	private void getDeviceRemindData(ArrayList<RemindDataVO> vos, Date date) {
		log.info("--------------------获取设备维保提醒信息开始--------------------");
		//获取设备类型提醒提前天数
		List<DeviceCategorySettings> deviceCategoryList = deviceCategorySettingsService.list(new QueryWrapper<DeviceCategorySettings>().lambda()
			.eq(DeviceCategorySettings::getDelFlag, Constant.DELETE_FLAG_0)
			.isNotNull(DeviceCategorySettings::getRemindDay));
		if (Func.isNotEmpty(deviceCategoryList)) {
			List<Device> deviceTotalList = new ArrayList<>();
			deviceCategoryList.forEach(item -> {
				log.info("设备类型[{}]的设备，维保提醒提前天数是[{}]天",item.getName(),item.getRemindDay());
				//根据设备类型获取具体设备信息
				Date startDate = getRemindStartDate(date, item.getRemindDay());
				List<Device> deviceList = deviceService.list(new QueryWrapper<Device>().lambda()
					.eq(Func.isNotEmpty(item.getId()), Device::getTypeId, item.getId())
					.eq(Device::getDepId, AuthUtil.getDeptId())
					.eq(Device::getUsageState, Constant.DEVICE_STATE_USE)
					.le(Func.isNotEmpty(startDate), Device::getMaintenanceDate, startDate)
					.ge(Func.isNotEmpty(date), Device::getMaintenanceDate, date));
				log.info("相关类型的设备信息为[{}]",deviceList);
				deviceTotalList.addAll(deviceList);
			});
			if (Func.isNotEmpty(deviceTotalList)) {
				deviceTotalList.forEach(device -> {
					RemindDataVO vo = new RemindDataVO();
					vo.setId(device.getId());
					vo.setType("device");
					vo.setTypeName("设备维保到期提醒");
					vo.setTitle(device.getName());
					vo.setDeadline(device.getMaintenanceDate());
					vo.setDeptName(departmentService.getById(device.getDepId()).getDeptName());
					vos.add(vo);
				});
			}
		}
		log.info("--------------------获取设备维保提醒信息结束--------------------");
	}

	/**
	 * 获取提醒开始日期
	 */
	private Date getRemindStartDate(Date date, int day) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, day);
		return calendar.getTime();
	}

	/**
	 * 项目验收信息入库
	 */
	private void saveProjectCheck(ProjectDTO projectDTO, Project project) {
		log.info("==============项目验收信息入库开始==============");
		ProjectCheck projectCheck = Func.copy(projectDTO.getProjectCheck(), ProjectCheck.class);
		Preconditions.checkArgument(Func.isNotEmpty(projectCheck), "项目验收信息为空");
		projectCheck.setProjectLinkId(project.getId());
		projectCheckService.saveOrUpdate(projectCheck);
		//保存相关附件
		fileService.saveAttachments(projectDTO.getProjectCheck().getCheckAttachments(), projectCheck.getId());
		log.info("==============项目验收信息入库结束==============");
	}

	/**
	 * 项目实施信息入库
	 */
	private void saveImplementating(ProjectDTO projectDTO, Project project) {
		log.info("==============项目实施信息入库开始==============");
		ProjectImplementation projectImplementation = Func.copy(projectDTO.getProjectImplementation(), ProjectImplementation.class);
		Preconditions.checkArgument(Func.isNotEmpty(projectImplementation), "项目实施信息为空");
		projectImplementation.setProjectLinkId(project.getId());
		projectImplementationService.saveOrUpdate(projectImplementation);
		//保存相关附件
		//项目实施文件
		fileService.saveAttachments(projectDTO.getProjectImplementation().getImplementationAttachments(), projectImplementation.getId());
		//工程变更单
		fileService.saveAttachments(projectDTO.getProjectImplementation().getEngineeringAttachments(), projectImplementation.getId());
		//设备合格资料
		fileService.saveAttachments(projectDTO.getProjectImplementation().getDeviceAttachments(), projectImplementation.getId());
		//项目实施其他材料
		fileService.saveAttachments(projectDTO.getProjectImplementation().getOtherAttachments(), projectImplementation.getId());
		log.info("==============项目实施信息入库结束==============");
	}

	/**
	 * 项目合同信息入库
	 */
	private void saveContract(ProjectDTO projectDTO, Project project) {
		log.info("==============项目合同信息入库开始==============");
		Preconditions.checkArgument(Func.isNotEmpty(projectDTO.getProjectContract()), "项目合同信息为空");
		projectDTO.getProjectContract().forEach(item -> {
			ProjectContract projectContract = Func.copy(item, ProjectContract.class);
			projectContract.setDeptId(AuthUtil.getDeptId());
			projectContract.setProjectLinkId(project.getId());
			projectContract.setOutCompanyName(Func.isNotEmpty(item.getOutCompany()) ? outCompanyService.getById(item.getOutCompany()).getOutCompanyName() : null);
			projectContractService.saveOrUpdate(projectContract);
			//保存相关附件
			//保存合同原件
			fileService.saveAttachments(item.getContractAttachments(), projectContract.getId());
			//保存补充材料
			fileService.saveAttachments(item.getSupplementAttachments(), projectContract.getId());
			//保存法审后意见
			fileService.saveAttachments(item.getLegalAttachments(), projectContract.getId());
			//保存项目合同其他材料
			fileService.saveAttachments(item.getOtherAttachments(), projectContract.getId());
		});
		log.info("==============项目合同信息入库结束==============");
	}

	/**
	 * 付款计划入库
	 */
	private void savePayPlan(ProjectDTO projectDTO, Project project) {
		log.info("==============付款计划入库开始==============");
		projectDTO.getPayPlanList().forEach(item -> {
			ProjectPayPlan projectPayPlan = Func.copy(item, ProjectPayPlan.class);
			projectPayPlan.setDeptId(AuthUtil.getDeptId());
			Preconditions.checkArgument(Func.isNotEmpty(projectPayPlan), "付款计划信息为空");
			projectPayPlan.setProjectLinkId(project.getId());
			projectPayPlanService.saveOrUpdate(projectPayPlan);
			//保存发票相关附件
			fileService.saveAttachments(item.getInvoiceAttachments(), projectPayPlan.getId());
		});
		log.info("==============付款计划入库结束==============");
	}

	/**
	 * 项目采购信息入库
	 */
	private void saveProjectPurchase(ProjectDTO projectDTO, Project project) {
		log.info("==============项目采购信息入库开始==============");
		ProjectPurchase projectPurchase = Func.copy(projectDTO.getProjectPurchase(), ProjectPurchase.class);
		Preconditions.checkArgument(Func.isNotEmpty(projectPurchase), "项目采购信息为空");
		projectPurchase.setProjectLinkId(project.getId());
		projectPurchaseService.saveOrUpdate(projectPurchase);
		//保存相关附件
		//公开招标材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getPublicBiddingAttachments(), projectPurchase.getId());
		//邀请招标材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getInviteBiddingAttachments(), projectPurchase.getId());
		//询价采购材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getInquiryAttachments(), projectPurchase.getId());
		//单一来源采购材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getSingleSourceAttachments(), projectPurchase.getId());
		//竞争性谈判材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getCompetitiveAttachments(), projectPurchase.getId());
		//项目采购其他材料
		fileService.saveAttachments(projectDTO.getProjectPurchase().getOtherAttachments(), projectPurchase.getId());
		log.info("==============项目采购信息入库结束==============");
	}

	/**
	 * 项目立项信息入库
	 */
	private void saveProjectEstablishment(ProjectDTO projectDTO, Project project) {
		log.info("==============项目立项信息入库开始==============");
		ProjectEstablishment projectEstablishment = Func.copy(projectDTO.getProjectEstablishment(), ProjectEstablishment.class);
		Preconditions.checkArgument(Func.isNotEmpty(projectEstablishment), "项目立项信息为空");
		projectEstablishment.setProjectLinkId(project.getId());
		projectEstablishmentService.saveOrUpdate(projectEstablishment);
		//保存相关附件信息
		//项目立项图纸
		fileService.saveAttachments(projectDTO.getProjectEstablishment().getDrawAttachments(), projectEstablishment.getId());
		//项目立项造价材料
		fileService.saveAttachments(projectDTO.getProjectEstablishment().getCostAttachments(), projectEstablishment.getId());
		//项目立项材料
		fileService.saveAttachments(projectDTO.getProjectEstablishment().getMaterialAttachments(), projectEstablishment.getId());
		//项目财审材料
		fileService.saveAttachments(projectDTO.getProjectEstablishment().getFinancialAttachments(), projectEstablishment.getId());
		//项目立项其他材料
		fileService.saveAttachments(projectDTO.getProjectEstablishment().getOtherAttachments(), projectEstablishment.getId());
		log.info("==============项目立项信息入库结束==============");
	}

}
