diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/EbomApi.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/EbomApi.java index 2bb41d9e..4b6b47cb 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/EbomApi.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/EbomApi.java @@ -37,6 +37,7 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -165,6 +166,19 @@ public class EbomApi extends BaseApi { return ResultVO.success(errorMsgVOS); } + @PostMapping("convertToPBomForFormalEBom") + @ApiOperation("EBom正式版转PBom") + @LogRecord(success = "转PBom:物料编码:{{#CToPbom.materialNo}} 版本:{{#CToPbom.currentVersion}},操作结果:{{#_ret}}", + bizNo = "{{#paramDto.bomRowIds.toString()}}", type = "转PBom") + public ResultVO> convertToPBomForFormalEBom(@RequestBody EBomToPBomParamDTO paramDto) throws ExecutionException, InterruptedException { + VUtils.isTure(CollUtil.isEmpty(paramDto.getBomRowIds())).throwMessage("请选择要转换的物料"); + VUtils.isTure(CollUtil.isEmpty(paramDto.getFacCodes())).throwMessage("请选择要转换的工厂"); + VUtils.isTure(Objects.isNull(paramDto.getConvertMode())).throwMessage("转换模式不能为空"); + bomNewEbomParentService.convertToPBomForFormalEBom(paramDto); + + return ResultVO.success(Collections.emptyList()); + } + @PostMapping("upgradeChanges") @ApiOperation("发起变更") @LogRecord(success = "发起变更:物料编码:{{#bom.materialNo}} 版本:{{#bom.currentVersion}},操作结果:{{#_ret}}", diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/BomNewEbomParentService.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/BomNewEbomParentService.java index fbd5d6d9..dd92a0d8 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/BomNewEbomParentService.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/BomNewEbomParentService.java @@ -540,6 +540,25 @@ public class BomNewEbomParentService extends ServiceImpl getFormalBomTree(Long rowId) throws ExecutionException, InterruptedException { + List bomDetail = this.getBaseMapper().getParentChild(rowId); + EBomFormalDetailTask detailTask = new EBomFormalDetailTask(bomDetail); + ForkJoinTask> submit = bomDetailPool.submit(detailTask); + + List result = submit.join(); + return result; + + } + + /** * 获取整个BOM树 * @@ -936,6 +955,51 @@ public class BomNewEbomParentService extends ServiceImpl parents = this.getBaseMapper().selectBatchIds(paramDto.getBomRowIds()); + + parents.forEach(p -> { + if (p.getMaterialNo().startsWith("31")) { + List errors = new ArrayList<>(); + if (ebomChildService.lambdaQuery().eq(BomNewEbomChildEntity::getParentRowId, p.getRowId()) + .eq(BomNewEbomChildEntity::getVirtualPartType, VirtualPackageTypeEnum.UN_VIRTUAL_PACKAGE.getValue()) + .exists()) { + errors.add(p.getMaterialNo() + "下还有未生成发货包的物料"); + } + VUtils.isTure(CollUtil.isNotEmpty(errors)).throwMessage(StrUtil.join("
", errors)); + } + }); + for (Long bomRowId : paramDto.getBomRowIds()) { + BomNewEbomParentVO parent = Convert.convert(BomNewEbomParentVO.class, this.getById(bomRowId)); + VUtils.isTure(Objects.isNull(parent)).throwMessage("Bom版本不存在:" + bomRowId.toString()); + LogRecordContext.putVariable("CToPbom", parent); + List bomTree = getFormalBomTree(bomRowId); + VUtils.isTure(CollUtil.isEmpty(bomTree)).throwMessage("该BOM不存在下级,无需转换:" + bomRowId.toString()); + parent.setBomRowId(parent.getRowId()); + parent.setChildBomRowId(parent.getRowId()); + parent.setParentRowId(0L); + bomTree.add(parent); + EBomToPbomBase eBomToPBom =parent.getMaterialNo().startsWith("31")? new EBomToPBomForFormal31(parent, bomTree, paramDto.getFacCodes(), 0L,EnumUtils.getValueEnum(ConvertToPBomModelEnum.class,paramDto.getConvertMode())):new EBomToPBomForFormal(parent, bomTree, paramDto.getFacCodes(), 0L,EnumUtils.getValueEnum(ConvertToPBomModelEnum.class,paramDto.getConvertMode())); + eBomToPBom.convert(); + + if (CollUtil.isNotEmpty(eBomToPBom.getPBomParentResult())) { + pBomParentService.saveOrUpdateBatch(eBomToPBom.getPBomParentResult()); + + } + if (CollUtil.isNotEmpty(eBomToPBom.getPBomChildResult())) { + pBomChildService.saveOrUpdateBatch(eBomToPBom.getPBomChildResult()); + } + } + } + public List importToSAP(Long rootBomRowId) { BomNewEbomParentEntity root = this.getById(rootBomRowId); VUtils.isTure(Objects.isNull(root)).throwMessage("数据不存在"); diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomFormalDetailTask.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomFormalDetailTask.java new file mode 100644 index 00000000..bfcb74a2 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomFormalDetailTask.java @@ -0,0 +1,122 @@ +package com.nflg.product.bomnew.service.domain.EBom; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.nflg.product.bomnew.constant.EBomStatusEnum; +import com.nflg.product.bomnew.pojo.entity.BomNewEbomParentEntity; +import com.nflg.product.bomnew.pojo.vo.BomNewEbomParentVO; +import com.nflg.product.bomnew.service.BomNewEbomParentService; +import com.nflg.product.bomnew.util.ListCommonUtil; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.RecursiveTask; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author 大米 + * @descreption EBOM 正式版BOM树 + * @date 2023/7/8 9:18 + */ +public class EBomFormalDetailTask extends RecursiveTask> { + + private List bomDetail; + + + + @Getter + @Setter + public static int levelNum=1; + + List result = new ArrayList<>(); + + + + + public EBomFormalDetailTask(List inBomDetail) { + bomDetail = inBomDetail; + + + } + + /** + * 处理BOM明细中未选择Bom版本的明细;使用最新版 + */ + public void handlerChildBomVersionDetail() { + List materialNos = bomDetail.stream().filter(u -> StrUtil.isNotBlank(u.getMaterialNo()) ).map(BomNewEbomParentVO::getMaterialNo).collect(Collectors.toList()); + + if (CollUtil.isNotEmpty(materialNos)) { + + List childBomlist = SpringUtil.getBean(BomNewEbomParentService.class).lambdaQuery().in(BomNewEbomParentEntity::getMaterialNo, materialNos) + .eq(BomNewEbomParentEntity::getStatus, EBomStatusEnum.PUBLISHED.getValue()).list(); + Map stringBomNewOriginalParentEntityMap = childBomlist.parallelStream() + .collect(Collectors.toMap( + BomNewEbomParentEntity::getMaterialNo, // key: DrawingNo + Function.identity(), + BinaryOperator.maxBy(Comparator.comparing(BomNewEbomParentEntity::getCurrentVersion)) + )); +// Map stringBomNewOriginalParentEntityMap = ListCommonUtil.listToMap(childBomlist, BomNewEbomParentEntity::getMaterialNo); + for (BomNewEbomParentVO detailVO : bomDetail) { + if (stringBomNewOriginalParentEntityMap.containsKey(detailVO.getMaterialNo())) { + BomNewEbomParentEntity ebomParentEntity = stringBomNewOriginalParentEntityMap.get(detailVO.getMaterialNo()); + detailVO.setChildBomRowId(ebomParentEntity.getRowId()); + detailVO.setBomRowId(ebomParentEntity.getRowId()); + detailVO.setSourceRowId(ebomParentEntity.getSourceRowId()); + detailVO.setCurrentVersion(ebomParentEntity.getCurrentVersion()); + detailVO.setDeviseUserCode(ebomParentEntity.getDeviseUserCode()); + detailVO.setDeptName(ebomParentEntity.getDeptName()); + detailVO.setDeviseName(ebomParentEntity.getDeviseName()); + detailVO.setBomExist(ebomParentEntity.getBomExist()); + detailVO.setStatus(ebomParentEntity.getStatus()); + detailVO.setBatchNo(ebomParentEntity.getBatchNo()); + } + } + + + } + + + } + + /** + * 递归调用零部件BOM + * + * @return + */ + @Override + protected List compute() { + + handlerChildBomVersionDetail(); + // 最新 BOM 版本 + + result.addAll(bomDetail); + + if (CollUtil.isNotEmpty(bomDetail)) { + levelNumAdd(); + List childBowIds = bomDetail.stream().filter(u-> u.getChildBomRowId()!=null && u.getChildBomRowId() > 0).map(u->u.getChildBomRowId()).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(childBowIds)) { + List bom = SpringUtil.getBean(BomNewEbomParentService.class).getBaseMapper().getParentChildBatch(childBowIds); + + EBomFormalDetailTask task = new EBomFormalDetailTask(bom); + task.fork(); + bomDetail.addAll(task.join()); + return bomDetail; + } + + } + return result; + + + } + + public synchronized void levelNumAdd(){ + levelNum++; + } +} diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal.java new file mode 100644 index 00000000..bd6c56e3 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal.java @@ -0,0 +1,104 @@ +package com.nflg.product.bomnew.service.domain.EBom; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.enums.BooleanEnum; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.nflg.product.bomnew.constant.ConvertToPBomModelEnum; +import com.nflg.product.bomnew.constant.PBomStatusEnum; +import com.nflg.product.bomnew.pojo.entity.BomNewPbomChildEntity; +import com.nflg.product.bomnew.pojo.entity.BomNewPbomParentEntity; +import com.nflg.product.bomnew.pojo.vo.BomNewEbomParentVO; +import com.nflg.product.bomnew.util.ListCommonUtil; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 正式版 Ebom 转Pbom + */ +@NoArgsConstructor +public class EBomToPBomForFormal extends EBomToPbomBase { + + + + + public EBomToPBomForFormal(BomNewEbomParentVO inParent, List inAllBomDetail, List inFacCodes, Long parentRowId, ConvertToPBomModelEnum convertModelEnum) { + this.parent = inParent; + this.allBomDetail = inAllBomDetail; + this.facCodes = inFacCodes; + this.convertMode=convertModelEnum; + generateDrawingNo(allBomDetail, parentRowId, ""); + + } + + + /** + * 31項体层 + */ + @Override + public void convert() { + + //效验数据是否OK + check(); + //bom 提层 + liftingLayer(); + List parentList = ListCommonUtil.toDistinct(result.stream().filter(u -> u.getBomRowId() > 0).collect(Collectors.toList()), BomNewEbomParentVO::getBomRowId); + List hasConvert = new ArrayList<>(); + + for (String facCode : facCodes) { + //buildPBomParent(parent, facCode); + for (BomNewEbomParentVO vo : parentList) { + String hasConvertKey = StrUtil.join("-", facCode, vo.getBomRowId()); + if (hasConvert.contains(hasConvertKey) ) { + continue; + } + hasConvert.add(hasConvertKey); + + //无需转换bom + if(BooleanEnum.TRUE.equals(vo.getNoConvertToPBomIs()) ){ + continue; + } + //构建变更明细 +// buildUpgradeChangeDetail(vo, VirtualPackageTypeEnum.DIRECT_DELIVERY_PACKAGE); +// buildUpgradeChangeDetail(vo, VirtualPackageTypeEnum.PRE_ASSEMBLY_PACKAGE); + + //子级 + List child = result.stream().filter(u -> u.getParentRowId().equals(vo.getBomRowId())).distinct().collect(Collectors.toList()); + List mergeChild = mergeChild(child); + if( compareContentIsSame(vo, mergeChild, facCode)){ + continue; + } + + BomNewPbomParentEntity parentEnt = buildPBomParent(vo, facCode,parentList); + if(Objects.isNull(parentEnt)){ + continue; + } + //子级 + if (CollUtil.isNotEmpty(child)) { + //合并子级 + for (BomNewEbomParentVO eb : mergeChild) { + BomNewPbomChildEntity childEnt = new BomNewPbomChildEntity(); + BeanUtil.copyProperties(eb, childEnt,"sourceRowId"); + childEnt.setRowId(IdWorker.getId()); + childEnt.setParentRowId(parentEnt.getRowId()); + childEnt.setFacCode(facCode); + childEnt.setSourceRowId(eb.getRowId()); + childEnt.setIdentityNo(StrUtil.join("-", parentEnt.getMaterialNo(), eb.getMaterialNo())); + this.pBomChildResult.add(childEnt); + } + + + } + } + } + } + + + + +} diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal31.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal31.java new file mode 100644 index 00000000..82aa6a92 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPBomForFormal31.java @@ -0,0 +1,134 @@ +package com.nflg.product.bomnew.service.domain.EBom; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.enums.BooleanEnum; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.nflg.product.bomnew.constant.ConvertToPBomModelEnum; +import com.nflg.product.bomnew.constant.EBomConstant; +import com.nflg.product.bomnew.pojo.entity.BomNewPbomChildEntity; +import com.nflg.product.bomnew.pojo.entity.BomNewPbomParentEntity; +import com.nflg.product.bomnew.pojo.vo.BomNewEbomParentVO; +import com.nflg.product.bomnew.util.ListCommonUtil; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 31码转PBOM + */ +@NoArgsConstructor +public class EBomToPBomForFormal31 extends EBomToPbomBase { + + + + private Map> facBomDataMp=new HashMap<>(); + + + public EBomToPBomForFormal31(BomNewEbomParentVO inParent, List inAllBomDetail, List inFacCodes, Long parentRowId, ConvertToPBomModelEnum convertModelEnum) { + this.parent = inParent; + this.allBomDetail = inAllBomDetail; + this.facCodes = inFacCodes; + this.convertMode=convertModelEnum; + generateDrawingNo(allBomDetail, parentRowId, ""); + + + } + + private void splitData(){ + this.facCodes=new ArrayList<>(); + //1020数据 + List data1020=new ArrayList<>(); + List deliveryPackage1020 = result.stream().filter(u -> u.getParentRowId().equals(parent.getRowId()) && u.getMaterialName().contains("仙桃") ).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(deliveryPackage1020)){ + facCodes.add(EBomConstant.XIAN_TAO_FACTORY_CODE_1020); + data1020.add(parent); + for (BomNewEbomParentVO data: deliveryPackage1020){ + List subVos = result.stream().filter(u -> u.getLevelNumber().compareTo(data.getLevelNumber()) >= 0 && u.getLevelNumber().compareTo(NumberUtil.add(data.getLevelNumber(), BigDecimal.valueOf(0.01))) < 0).collect(Collectors.toList()); + data1020.addAll(subVos); + } + facBomDataMp.put(EBomConstant.XIAN_TAO_FACTORY_CODE_1020,data1020); + } + + //1010 数据 + + List data1010=new ArrayList<>(); + List deliveryPackage1010 = result.stream().filter(u -> u.getParentRowId().equals(parent.getRowId()) && !u.getMaterialName().contains("仙桃")).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(deliveryPackage1010)){ + facCodes.add(EBomConstant.MAIN_FACTORY_CODE_1010); + data1010.add(parent); + for (BomNewEbomParentVO data: deliveryPackage1010){ + List subVos = result.stream().filter(u -> u.getLevelNumber().compareTo(data.getLevelNumber()) >= 0 && u.getLevelNumber().compareTo(NumberUtil.add(data.getLevelNumber(), BigDecimal.valueOf(0.01))) < 0).collect(Collectors.toList()); + data1010.addAll(subVos); + } + facBomDataMp.put(EBomConstant.MAIN_FACTORY_CODE_1010,data1010); + } + + } + + /** + * 31項体层 + */ + @Override + public void convert() { + + //效验数据是否OK + check(); + //bom 提层 + liftingLayer(); + result.forEach(u->u.setLevelNo("")); + generateDrawingNo(result, parent.getRowId(), "1"); + splitData(); + List hasConvert = new ArrayList<>(); + + for (String facCode : facCodes) { + List parentList = ListCommonUtil.toDistinct(facBomDataMp.get(facCode).stream().filter(u -> u.getBomRowId() > 0) + .sorted(Comparator.comparing(BomNewEbomParentVO::getLevelNumber)) + .collect(Collectors.toList()), BomNewEbomParentVO::getBomRowId); + for (BomNewEbomParentVO vo : parentList) { + String hasConvertKey = StrUtil.join("-", facCode, vo.getBomRowId()); + if (hasConvert.contains(hasConvertKey)) { + continue; + } + hasConvert.add(hasConvertKey); + //无需转换bom + if(BooleanEnum.TRUE.equals(vo.getNoConvertToPBomIs()) ){ + continue; + } + //构建变更明细 +// buildUpgradeChangeDetail(vo, VirtualPackageTypeEnum.DIRECT_DELIVERY_PACKAGE); +// buildUpgradeChangeDetail(vo, VirtualPackageTypeEnum.PRE_ASSEMBLY_PACKAGE); + + //子级 + List child = facBomDataMp.get(facCode).stream().filter(u -> u.getParentRowId().equals(vo.getBomRowId())).distinct().collect(Collectors.toList()); + List mergeChild = mergeChild(child); + if( compareContentIsSame(vo, mergeChild, facCode)){ + continue; + } + BomNewPbomParentEntity parentEnt = buildPBomParent(vo, facCode,parentList); + if(Objects.isNull(parentEnt)){ + continue; + } + //子级 + if (CollUtil.isNotEmpty(child)) { + //合并子级 + for (BomNewEbomParentVO eb : mergeChild) { + BomNewPbomChildEntity childEnt = new BomNewPbomChildEntity(); + BeanUtil.copyProperties(eb, childEnt,"sourceRowId"); + childEnt.setRowId(IdWorker.getId()); + childEnt.setParentRowId(parentEnt.getRowId()); + childEnt.setFacCode(facCode); + childEnt.setIdentityNo(StrUtil.join("-", parentEnt.getMaterialNo(), eb.getMaterialNo())); + this.pBomChildResult.add(childEnt); + } + } + } + } + } + + +} diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPbomBase.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPbomBase.java index 169c7906..279ad951 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPbomBase.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/domain/EBom/EBomToPbomBase.java @@ -174,7 +174,7 @@ public abstract class EBomToPbomBase { } else { //pbom-处于正式表 String bomVersion= VersionUtil.compare(parentVo.getCurrentVersion(),oldParent.getCurrentVersion())>=0?parentVo.getCurrentVersion():VersionUtil.getNextVersion(oldParent.getCurrentVersion()); - return buildParentEntity(parentVo, facCode, oldParent,bomVersion)); + return buildParentEntity(parentVo, facCode, oldParent,bomVersion); }