package com.fjhx.sale.flow; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.fjhx.area.utils.CustomizeAreaUtil; import com.fjhx.common.entity.InOutBo; import com.fjhx.common.enums.CodingRuleEnum; import com.fjhx.common.enums.FlowStatusEnum1; import com.fjhx.common.enums.InOutType; import com.fjhx.common.service.coding.CodingRuleService; import com.fjhx.common.service.file.FtpFileService; import com.fjhx.file.utils.ObsFileUtil; import com.fjhx.flow.core.FlowDelegate; import com.fjhx.flow.enums.FlowStatusEnum; import com.fjhx.item.entity.product.po.ProductBomDetail; import com.fjhx.item.entity.product.po.ProductInfo; import com.fjhx.item.entity.product.po.ProductStockInfo; import com.fjhx.item.enums.ProductAvailableRecordType; import com.fjhx.item.service.product.ProductBomDetailService; import com.fjhx.item.service.product.ProductInfoService; import com.fjhx.item.service.product.ProductStockInfoService; import com.fjhx.purchase.entity.subscribe.po.SubscribeDetail; import com.fjhx.purchase.service.subscribe.SubscribeDetailService; import com.fjhx.sale.entity.contract.dto.ContractDto; import com.fjhx.sale.entity.contract.po.Contract; import com.fjhx.sale.entity.contract.po.ContractProduct; import com.fjhx.sale.entity.contract.po.ContractProject; import com.fjhx.sale.service.contract.ContractProductService; import com.fjhx.sale.service.contract.ContractProjectService; import com.fjhx.sale.service.contract.ContractService; import com.ruoyi.common.annotation.LogicIgnore; import com.ruoyi.common.core.domain.BasePo; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.mybatis.holder.TenantHolder; import com.ruoyi.system.service.ISysDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * 外销合同流程 * * @Author:caozj * @DATE:2023/4/3 17:38 */ @Component //@DS(SourceConstant.SALE) public class ContractFlow extends FlowDelegate { @Autowired private CodingRuleService codingRuleService; @Autowired private ContractService contractService; @Autowired private ContractProductService contractProductService; @Autowired private ContractProjectService contractProjectService; @Autowired private FtpFileService ftpFileService; @Autowired private ProductInfoService productInfoService; @Autowired private SubscribeDetailService subscribeDetailService; @Autowired private ProductBomDetailService productBomDetailService; @Autowired private ISysDeptService deptService; @Autowired private ProductStockInfoService productStockInfoService; @Override public String getFlowKey() { return "contract_flow"; } /** * 发起流程 * * @param flowId 流程ID * @param submitData 采购付款数据 * @return 业务id */ @Override public Long start(Long flowId, JSONObject submitData) { ContractDto contract = submitData.toJavaObject(ContractDto.class); contract.setFlowId(flowId); if (StringUtils.isEmpty(contract.getCurrency())) { throw new ServiceException("币种不能为空"); } contract.setCode(codingRuleService.createCode(CodingRuleEnum.CONTRACT.getKey(), contract.getBuyCorporationId())); // 保存合同产品 List contractProductList = contract.getContractProductList(); // 赋值待处理数量 if (CollectionUtils.isNotEmpty(contractProductList)) { contractProductList.forEach(item -> item.setExpendQuantity(item.getQuantity())); } return start(contract); } /** * 结束流程 * * @param flowId 流程ID * @param businessId 业务ID * @param submitData 数据 */ @Override public void end(Long flowId, Long businessId, JSONObject submitData) { // 通过业务ID查询合同数据 Contract contract = contractService.getById(businessId); if (ObjectUtils.isEmpty(contract)) { throw new ServiceException("合同不存在"); } // 修改合同状态为审批通过 contract.setStatus(FlowStatusEnum1.PASS.getKey()); contract.setApprovedDate(new Date()); contractService.updateById(contract); //生成物料待采购数据 createMaterialWaitPurchase(contract); } public Long start(ContractDto contract) { // 赋值城市省份信息 CustomizeAreaUtil.setAreaId(contract); SysUser loginUser = SecurityUtils.getLoginUser().getUser(); contract.setUserName(loginUser.getNickName()); contract.setBuyCityId(contract.getCityId()); contract.setBuyCountryId(contract.getCountryId()); contract.setBuyProvinceId(contract.getProvinceId()); contract.setStatus(FlowStatusEnum1.UNDER_REVIEW.getKey()); //根据归属公司将数据赋值给指定公司 Long companyId = contract.getCompanyId(); TenantHolder.setIgnore(true); SysDept country = deptService.getById(companyId); TenantHolder.clear(); if (ObjectUtil.isEmpty(country)) { throw new ServiceException("归属公司不存在"); } SecurityUtils.setTenantId(country.getTenantId()); contractService.saveOrUpdate(contract); SecurityUtils.clearTenantId(); // 保存合同产品 List contractProductList = contract.getContractProductList(); contractProductList = ObjectUtil.isEmpty(contractProductList) ? new ArrayList<>() : contractProductList; for (ContractProduct c : contractProductList) { //对新数据创建id c.setId(ObjectUtil.isEmpty(c.getId()) ? IdWorker.getId() : c.getId()); //赋值合同Id c.setContractId(contract.getId()); //保存设计稿图 ObsFileUtil.editFile(c.getFileList(), c.getId()); //保存生产源文件 String prodFilePath = c.getProdFilePath(); if (ObjectUtil.isNotEmpty(prodFilePath) && prodFilePath.startsWith("/temp")) { String targetFolderPath = String.format("/contractProduct/%s", c.getId()); com.alibaba.fastjson2.JSONObject prodFile = ftpFileService.moveFolder(prodFilePath, targetFolderPath); c.setProdFilePath(prodFile.getString("path")); } } contractProductService.editLinked(contractProductList, ContractProduct::getContractId, contract.getId()); // 保存收费项目 List contractProjectList = contract.getContractProjectList(); contractProjectList = ObjectUtil.isEmpty(contractProjectList) ? new ArrayList<>() : contractProjectList; for (ContractProject c : contractProjectList) { c.setContractId(contract.getId()); } contractProjectService.editLinked(contractProjectList, ContractProject::getContractId, contract.getId()); return contract.getId(); } /** * 重新发起 * * @param flowId * @param businessId * @param flowStatus * @param submitData */ @Override @LogicIgnore public void relaunch(Long flowId, Long businessId, FlowStatusEnum flowStatus, JSONObject submitData) { //删除采购合同 ContractDto contractDto = submitData.toJavaObject(ContractDto.class); if (ObjectUtils.isEmpty(contractDto)) { throw new ServiceException("合同数据不能为空"); } start(contractDto); } /** * 驳回 * * @param flowId * @param businessId * @param flowStatus */ @Override public void reject(Long flowId, Long businessId, FlowStatusEnum flowStatus) { contractService.update(q -> q .eq(Contract::getId, businessId) .set(Contract::getStatus, 20)//20为驳回 .set(Contract::getUpdateTime, new Date()) .set(BasePo::getUpdateUser, SecurityUtils.getUserId()) ); } @Override public void cancellation(Long flowId, Long businessId, FlowStatusEnum flowStatus) { super.cancellation(flowId, businessId, flowStatus); contractService.update(q -> q .eq(Contract::getId, businessId) .set(Contract::getStatus, FlowStatusEnum1.CANCELLATION.getKey()) .set(BasePo::getUpdateTime, new Date()) .set(BasePo::getUpdateUser, SecurityUtils.getUserId()) ); } /** * 创建合同产品 物料待采购信息 */ private void createMaterialWaitPurchase(Contract contract) { //生成物料待采购数据 List contractProductList = contractProductService.list(q -> q.eq(ContractProduct::getContractId, contract.getId())); List productIds = contractProductList.stream().map(ContractProduct::getProductId).collect(Collectors.toList()); //获取产品列表 Map productInfoMap = productInfoService.mapKEntity(ProductInfo::getId, q -> q.in(ProductInfo::getId, productIds)); //获取物料信息 Map> productBomMap = productBomDetailService.mapKGroup(ProductBomDetail::getProductId, q -> q.in(ProductBomDetail::getProductId, productIds)); //待采购列表 List subscribeDetailList = new ArrayList<>(); for (ContractProduct contractProduct : contractProductList) { Long productId = contractProduct.getProductId(); ProductInfo productInfo = productInfoMap.get(productId); //获取物料列表,以及原材料 List productBomDetails = productBomMap.get(productId); if (ObjectUtil.isNotEmpty(productBomDetails)) { List materialIds = productBomDetails.stream().map(ProductBomDetail::getMaterialId).collect(Collectors.toList()); Map materialMap = productInfoService.mapKEntity(ProductInfo::getId, q -> q.in(ProductInfo::getId, materialIds)); //获取合同归属归属的物料可用库存 Map availableQuantityMap = productStockInfoService.mapKV(ProductStockInfo::getId, ProductStockInfo::getAvailableQuantity, q -> q .in(ProductStockInfo::getProductId, materialIds) .eq(ProductStockInfo::getCompanyId, contract.getCompanyId()) ); //遍历物料列表 for (ProductBomDetail productBomDetail : productBomDetails) { Long materialId = productBomDetail.getMaterialId(); ProductInfo materialInfo = materialMap.get(materialId); BigDecimal multiply = productBomDetail.getQuantity().multiply(contractProduct.getQuantity()); //获取产品安全库存 BigDecimal stockThreshold = materialInfo.getStockThreshold(); //获取可用库存 BigDecimal availableQuantity = availableQuantityMap.getOrDefault(materialId, BigDecimal.ZERO); //计数需要采购的数量(需采购量 = 安全库存 - (可用库存 - 合同量)若 需采购量<0,则按0算不采购) BigDecimal subtract = availableQuantity.subtract(multiply); BigDecimal requiredQuantity = stockThreshold.subtract(subtract); //计算可用库存 if (requiredQuantity.compareTo(BigDecimal.ZERO) < 0) { //需要采购的数量<0 可用库存 = 可用库存 - 合同量 InOutBo inOutBo = new InOutBo(); inOutBo.setProductId(materialId); inOutBo.setQuantity(multiply); productInfoService.editAvailableQuantity(Arrays.asList(inOutBo), InOutType.OUT, contractProduct.getId(), ProductAvailableRecordType.SALE_PASS, contract.getCompanyId()); } else { //需要采购的数量>=0 可用库存 = 安全库存 InOutBo inOutBo = new InOutBo(); inOutBo.setProductId(materialId); inOutBo.setQuantity(stockThreshold); productInfoService.editAvailableQuantity(Arrays.asList(inOutBo), InOutType.EQ, contractProduct.getId(), ProductAvailableRecordType.SALE_PASS, contract.getCompanyId()); } //需要采购的数量大于0生成待采购数据 if (requiredQuantity.compareTo(BigDecimal.ZERO) > 0) { SubscribeDetail subscribeDetail = new SubscribeDetail(); subscribeDetail.setProductId(materialId); subscribeDetail.setCount(requiredQuantity); subscribeDetail.setStatus(15);//待采购 subscribeDetail.setContractId(contract.getId()); subscribeDetail.setContractDetailId(contractProduct.getId()); subscribeDetail.setDataType(1); subscribeDetailList.add(subscribeDetail); } } } } //根据归属公司将数据赋值给指定公司 Long companyId = contract.getCompanyId(); SysDept company = deptService.getById(companyId); if (ObjectUtil.isEmpty(companyId)) { throw new ServiceException("归属公司不存在"); } //保存待采购明细 subscribeDetailService.saveBatch(subscribeDetailList); } }