123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- package com.fjhx.sale.flow;
- import cn.hutool.core.bean.BeanUtil;
- 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.common.utils.Assert;
- 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.dto.ContractProductDto;
- import com.fjhx.sale.entity.contract.po.Contract;
- import com.fjhx.sale.entity.contract.po.ContractProduct;
- import com.fjhx.sale.entity.contract.po.ContractProductBom;
- import com.fjhx.sale.entity.contract.po.ContractProject;
- import com.fjhx.sale.service.contract.ContractProductBomService;
- import com.fjhx.sale.service.contract.ContractProductService;
- import com.fjhx.sale.service.contract.ContractProjectService;
- import com.fjhx.sale.service.contract.ContractService;
- import com.fjhx.tenant.utils.DeptUstil;
- 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.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;
- @Autowired
- private ContractProductBomService contractProductBomService;
- @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<ContractProductDto> contractProductList = contract.getContractProductList();
- // 赋值待处理数量
- if (CollectionUtils.isNotEmpty(contractProductList)) {
- contractProductList.forEach(item -> item.setExpendQuantity(item.getQuantity()));
- }
- //将code赋值给流程引擎
- submitData.put("code", contract.getCode());
- 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) {
- //赋值归属部门,归属公司信息
- Long deptId = contract.getDeptId();
- Assert.notEmpty(deptId, "归属部门id不能为空!");
- Long companyId = DeptUstil.getCompanyIdByDeptId(deptId);
- contract.setCompanyId(companyId);
- // 赋值城市省份信息
- 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());
- contractService.saveOrUpdate(contract);
- // 保存合同产品
- List<ContractProductDto> contractProductListDto = contract.getContractProductList();
- contractProductListDto = ObjectUtil.isEmpty(contractProductListDto) ? new ArrayList<>() : contractProductListDto;
- for (ContractProductDto cp : contractProductListDto) {
- //对新数据创建id
- cp.setId(ObjectUtil.isEmpty(cp.getId()) ? IdWorker.getId() : cp.getId());
- //赋值合同Id
- cp.setContractId(contract.getId());
- //保存设计稿图
- ObsFileUtil.editFile(cp.getFileList(), cp.getId());
- //保存生产源文件
- String prodFilePath = cp.getProdFilePath();
- if (ObjectUtil.isNotEmpty(prodFilePath) && prodFilePath.startsWith("/temp")) {
- String targetFolderPath = String.format("/contractProduct/%s", cp.getId());
- com.alibaba.fastjson2.JSONObject prodFile = ftpFileService.moveFolder(prodFilePath, targetFolderPath);
- cp.setProdFilePath(prodFile.getString("path"));
- }
- //赋值产品BOM信息
- List<ContractProductBom> contractProductBomList = cp.getContractProductBomList();
- for (ContractProductBom contractProductBom : contractProductBomList) {
- contractProductBom.setContractProductId(cp.getId());
- contractProductBom.setProductId(cp.getProductId());
- }
- contractProductBomService.editLinked(contractProductBomList, ContractProductBom::getContractProductId, cp.getId());
- }
- List<ContractProduct> contractProductList1 = BeanUtil.copyToList(contractProductListDto, ContractProduct.class);
- contractProductService.editLinked(contractProductList1, ContractProduct::getContractId, contract.getId());
- // 保存收费项目
- List<ContractProject> 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<ContractProduct> contractProductList = contractProductService.list(q -> q.eq(ContractProduct::getContractId, contract.getId()));
- List<Long> productIds = contractProductList.stream().map(ContractProduct::getProductId).collect(Collectors.toList());
- //获取产品列表
- Map<Long, ProductInfo> productInfoMap = productInfoService.mapKEntity(ProductInfo::getId, q -> q.in(ProductInfo::getId, productIds));
- //获取物料信息
- Map<Long, List<ProductBomDetail>> productBomMap = productBomDetailService.mapKGroup(ProductBomDetail::getProductId, q -> q.in(ProductBomDetail::getProductId, productIds));
- //待采购列表
- List<SubscribeDetail> subscribeDetailList = new ArrayList<>();
- for (ContractProduct contractProduct : contractProductList) {
- Long productId = contractProduct.getProductId();
- ProductInfo productInfo = productInfoMap.get(productId);
- //获取物料列表,以及原材料
- List<ProductBomDetail> productBomDetails = productBomMap.get(productId);
- if (ObjectUtil.isNotEmpty(productBomDetails)) {
- List<Long> materialIds = productBomDetails.stream().map(ProductBomDetail::getMaterialId).collect(Collectors.toList());
- Map<Long, ProductInfo> materialMap = productInfoService.mapKEntity(ProductInfo::getId, q -> q.in(ProductInfo::getId, materialIds));
- //获取合同归属归属的物料可用库存
- Map<Long, BigDecimal> 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);
- }
- }
|