|
|
|
|
@ -5,7 +5,10 @@ import cn.hutool.core.bean.BeanUtil;
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.convert.Convert;
|
|
|
|
|
import cn.hutool.core.convert.Converter;
|
|
|
|
|
import cn.hutool.core.lang.TypeReference;
|
|
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import cn.hutool.extra.spring.SpringUtil;
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
|
|
@ -14,30 +17,41 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
|
import com.nflg.product.base.core.conmon.util.SessionUtil;
|
|
|
|
|
import com.nflg.product.bomnew.mapper.master.MaterialMainMapper;
|
|
|
|
|
import com.nflg.product.bomnew.mapper.master.ProductionOrderItemSapMapper;
|
|
|
|
|
import com.nflg.product.bomnew.mapper.master.ProductionOrderMapper;
|
|
|
|
|
import com.nflg.product.bomnew.mapper.master.ProductionOrderSapMapper;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.dto.sap.SapReqParams;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.dto.sap.SapResult;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.dto.sap.production.ProImportSapParamDTO;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.dto.sap.production.ProT1DTO;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.entity.ProductionOrderEntity;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.entity.ProductionOrderItemEntity;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.entity.ProductionOrderItemSapEntity;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.entity.ProductionOrderSapEntity;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.query.ProductionOrderQuery;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.query.ProductionOrderSaveQuery;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.query.QueryMaterialsQuery;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.vo.BaseMaterialVO;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.vo.EbomQueryMaterialsVO;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.vo.ProductionOrderItemVO;
|
|
|
|
|
import com.nflg.product.bomnew.pojo.vo.ProductionOrderVO;
|
|
|
|
|
import com.nflg.product.bomnew.util.VUtils;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import nflg.product.common.constant.STATE;
|
|
|
|
|
import nflg.product.common.vo.ResultVO;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
|
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
|
import java.util.concurrent.Executor;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -60,7 +74,7 @@ public class ProductionOrderService extends ServiceImpl<ProductionOrderMapper, P
|
|
|
|
|
private ProductionOrderItemSapMapper productionOrderItemSapMapper;
|
|
|
|
|
|
|
|
|
|
public IPage<ProductionOrderVO> getListByPage(ProductionOrderQuery query){
|
|
|
|
|
query.setSyncStatus(0);
|
|
|
|
|
// query.setSyncStatus(0);
|
|
|
|
|
Page<ProductionOrderQuery> page = new Page<>(query.getPage(),query.getPageSize());
|
|
|
|
|
Page<ProductionOrderVO> listByPage = this.getBaseMapper().getListByPage(page, query);
|
|
|
|
|
if (CollUtil.isNotEmpty(listByPage.getRecords())) {
|
|
|
|
|
@ -158,7 +172,8 @@ public class ProductionOrderService extends ServiceImpl<ProductionOrderMapper, P
|
|
|
|
|
this.updateById(updateEntity);
|
|
|
|
|
// 计划已确认,自动提交到AP
|
|
|
|
|
if (confirmStatus == 3) {
|
|
|
|
|
syncChange2Sap(rowId);
|
|
|
|
|
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> syncChange2Sap(rowId, SessionUtil.getUserCode()));
|
|
|
|
|
task1.join();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -166,13 +181,14 @@ public class ProductionOrderService extends ServiceImpl<ProductionOrderMapper, P
|
|
|
|
|
* 生产订单变更提交到SAP
|
|
|
|
|
* @param rowId
|
|
|
|
|
*/
|
|
|
|
|
private void syncChange2Sap(Long rowId) {
|
|
|
|
|
// TODO
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void syncChange2Sap(Long rowId, String updateBy) {
|
|
|
|
|
if (doSyncChange2Sap(rowId)) {
|
|
|
|
|
ProductionOrderEntity updateEntity = new ProductionOrderEntity();
|
|
|
|
|
updateEntity.setRowId(rowId);
|
|
|
|
|
updateEntity.setEditStatus(2);
|
|
|
|
|
updateEntity.setSyncStatus(1); // 已同步
|
|
|
|
|
updateEntity.setUpdatedBy(SessionUtil.getUserCode());
|
|
|
|
|
updateEntity.setUpdatedBy(updateBy);
|
|
|
|
|
updateEntity.setUpdatedTime(LocalDateTime.now());
|
|
|
|
|
this.updateById(updateEntity);
|
|
|
|
|
ProductionOrderSapEntity updateSapEntity = new ProductionOrderSapEntity();
|
|
|
|
|
@ -180,6 +196,103 @@ public class ProductionOrderService extends ServiceImpl<ProductionOrderMapper, P
|
|
|
|
|
updateSapEntity.setSyncStatus(1); // 已同步
|
|
|
|
|
this.productionOrderSapMapper.updateById(updateSapEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean doSyncChange2Sap(Long rowId) {
|
|
|
|
|
ProductionOrderEntity order = this.getById(rowId);
|
|
|
|
|
if (ObjectUtil.isEmpty(order)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
List<ProductionOrderItemEntity> itemList = this.productionOrderItemService.lambdaQuery()
|
|
|
|
|
.eq(ProductionOrderItemEntity::getOrderRowId, rowId)
|
|
|
|
|
.list();
|
|
|
|
|
if (CollUtil.isNotEmpty(itemList)) {
|
|
|
|
|
// ProImportSapParamDTO sapParamDTO = new ProImportSapParamDTO();
|
|
|
|
|
List<ProT1DTO> proT1DTOS = new ArrayList<>();
|
|
|
|
|
// sapParamDTO.setT1(proT1DTOS);
|
|
|
|
|
// sapParamDTO.setI_AUFNR("0000" + order.getProductionOrder());
|
|
|
|
|
// SAP 原始数据
|
|
|
|
|
QueryWrapper<ProductionOrderItemSapEntity> queryWrapper = new QueryWrapper<>();
|
|
|
|
|
queryWrapper.eq("order_row_id", rowId);
|
|
|
|
|
List<ProductionOrderItemSapEntity> sapItemList = this.productionOrderItemSapMapper.selectList(queryWrapper);
|
|
|
|
|
// 格式:项目号_物料号
|
|
|
|
|
List<String> itemNoMaterialNos = itemList.stream().map(item -> item.getItemNo() + "_" + item.getMaterialNo()).collect(Collectors.toList());
|
|
|
|
|
List<String> sapItemNoMaterialNos = sapItemList.stream().map(item -> item.getPOSNR() + "_" + item.getMATNR().replaceAll("^0+", "")).collect(Collectors.toList());
|
|
|
|
|
// 假设旧版 [1,2,3,4,5] 新版 [3,4,5,6,7]
|
|
|
|
|
// 旧版和新版的交集 -> [3,4,5]
|
|
|
|
|
List<String> intersection = new ArrayList<>(sapItemNoMaterialNos);
|
|
|
|
|
intersection.retainAll(itemNoMaterialNos);
|
|
|
|
|
// 旧版相对于新版的差集 -> [1,2]
|
|
|
|
|
List<String> difference = new ArrayList<>(sapItemNoMaterialNos);
|
|
|
|
|
difference.removeAll(itemNoMaterialNos);
|
|
|
|
|
// 新版相对于旧版的差集 -> [6,7]
|
|
|
|
|
List<String> difference2 = new ArrayList<>(itemNoMaterialNos);
|
|
|
|
|
difference2.removeAll(sapItemNoMaterialNos);
|
|
|
|
|
// SAP物料操作类型有4种:0不变 1新增 2修改 3删除
|
|
|
|
|
// 两个差集认为 difference2 的物料是增加,difference 的物料是减少
|
|
|
|
|
for (String add : difference2) {
|
|
|
|
|
ProductionOrderItemEntity addItem = itemList.stream().filter(item -> add.equals(item.getItemNo() + "_" + item.getMaterialNo())).findFirst().orElse(null);
|
|
|
|
|
if (ObjectUtil.isNotEmpty(addItem)) {
|
|
|
|
|
ProT1DTO proT1DTO = new ProT1DTO();
|
|
|
|
|
proT1DTO.setPOSNR(addItem.getItemNo());
|
|
|
|
|
proT1DTO.setMATNR("00000000" + addItem.getMaterialNo());
|
|
|
|
|
proT1DTO.setBDMNG(addItem.getCommandNum().toString());
|
|
|
|
|
proT1DTO.setMEINS(addItem.getUnit());
|
|
|
|
|
proT1DTO.setLGORT(addItem.getStorage());
|
|
|
|
|
proT1DTO.setOTYPE("1");
|
|
|
|
|
proT1DTOS.add(proT1DTO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (String remove : difference) {
|
|
|
|
|
ProductionOrderItemSapEntity removeItem = sapItemList.stream().filter(item -> remove.equals(item.getPOSNR() + "_" + item.getMATNR().replaceAll("^0+", ""))).findFirst().orElse(null);
|
|
|
|
|
if (ObjectUtil.isNotEmpty(removeItem)) {
|
|
|
|
|
ProT1DTO proT1DTO = new ProT1DTO();
|
|
|
|
|
proT1DTO.setPOSNR(removeItem.getPOSNR());
|
|
|
|
|
proT1DTO.setMATNR(removeItem.getMATNR());
|
|
|
|
|
proT1DTO.setBDMNG(removeItem.getBDMNG());
|
|
|
|
|
proT1DTO.setMEINS(removeItem.getMEINS());
|
|
|
|
|
proT1DTO.setLGORT(removeItem.getLGORT());
|
|
|
|
|
proT1DTO.setOTYPE("3");
|
|
|
|
|
proT1DTOS.add(proT1DTO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 遍历交集,如果旧版和新版物料的 需求数量、单位、存储地点、反冲 有一个字段值不一致,则认为是物料修改,否则是物料不变
|
|
|
|
|
for (String entity : intersection) {
|
|
|
|
|
ProductionOrderItemEntity dbItem = itemList.stream().filter(item -> entity.equals(item.getItemNo() + "_" + item.getMaterialNo())).findFirst().orElse(null);
|
|
|
|
|
ProductionOrderItemSapEntity sapItem = sapItemList.stream().filter(item -> entity.equals(item.getPOSNR() + "_" + item.getMATNR().replaceAll("^0+", ""))).findFirst().orElse(null);
|
|
|
|
|
ProT1DTO proT1DTO = new ProT1DTO();
|
|
|
|
|
proT1DTO.setPOSNR(dbItem.getItemNo());
|
|
|
|
|
proT1DTO.setMATNR("00000000" + dbItem.getMaterialNo());
|
|
|
|
|
proT1DTO.setBDMNG(dbItem.getCommandNum().toString());
|
|
|
|
|
proT1DTO.setMEINS(dbItem.getUnit());
|
|
|
|
|
proT1DTO.setLGORT(dbItem.getStorage());
|
|
|
|
|
proT1DTO.setOTYPE("0");
|
|
|
|
|
if (dbItem.getCommandNum().compareTo(new BigDecimal(sapItem.getBDMNG())) != 0
|
|
|
|
|
|| !dbItem.getUnit().equals(sapItem.getMEINS())
|
|
|
|
|
|| !dbItem.getStorage().equals(sapItem.getLGORT())
|
|
|
|
|
// || TODO 反冲
|
|
|
|
|
) {
|
|
|
|
|
proT1DTO.setOTYPE("2");
|
|
|
|
|
}
|
|
|
|
|
proT1DTOS.add(proT1DTO);
|
|
|
|
|
}
|
|
|
|
|
SapReqParams sapReqParams = new SapReqParams();
|
|
|
|
|
sapReqParams.setFunName("");
|
|
|
|
|
Map<String, Object> inputParams = new HashMap<>();
|
|
|
|
|
inputParams.put("I_AUFNR", "0000" + order.getProductionOrder());
|
|
|
|
|
sapReqParams.setInputParams(inputParams);
|
|
|
|
|
Map<String, List<Map<String, String>>> inputTables = new HashMap<>();
|
|
|
|
|
List<Map<String, String>> t1List = new ArrayList<>();
|
|
|
|
|
proT1DTOS.forEach(t1 -> {
|
|
|
|
|
t1List.add(Convert.convert(new TypeReference<Map<String, String>>() {
|
|
|
|
|
}, t1));
|
|
|
|
|
});
|
|
|
|
|
inputTables.put("T1", t1List);
|
|
|
|
|
sapReqParams.setInputTables(inputTables);
|
|
|
|
|
log.info("生产订单同步到SAP数据:{}", JSON.toJSONString(sapReqParams));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从SAP获取生产订单
|
|
|
|
|
@ -354,4 +467,40 @@ public class ProductionOrderService extends ServiceImpl<ProductionOrderMapper, P
|
|
|
|
|
}
|
|
|
|
|
return ResultVO.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<EbomQueryMaterialsVO> queryMaterials(List<QueryMaterialsQuery> query) {
|
|
|
|
|
List<BaseMaterialVO> datas = new ArrayList<>();
|
|
|
|
|
List<String> keys = query.stream().map(QueryMaterialsQuery::getMaterialNo)
|
|
|
|
|
.filter(StrUtil::isNotBlank)
|
|
|
|
|
.distinct()
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
if (CollUtil.isNotEmpty(keys)) {
|
|
|
|
|
datas.addAll(SpringUtil.getBean(MaterialMainMapper.class).getMaterialBaseInfo(keys));
|
|
|
|
|
}
|
|
|
|
|
return query.stream().map(q -> {
|
|
|
|
|
BaseMaterialVO mVO = datas.stream()
|
|
|
|
|
.filter(m -> StrUtil.isNotBlank(q.getMaterialNo()) ? StrUtil.equals(m.getMaterialNo(), q.getMaterialNo())
|
|
|
|
|
: StrUtil.equals(m.getDrawingNo(), q.getDrawingNo()))
|
|
|
|
|
.findFirst()
|
|
|
|
|
.orElse(null);
|
|
|
|
|
EbomQueryMaterialsVO vo = new EbomQueryMaterialsVO();
|
|
|
|
|
vo.setOrderNumber(q.getOrderNumber());
|
|
|
|
|
vo.setMaterialNo(q.getMaterialNo());
|
|
|
|
|
if (Objects.nonNull(mVO)) {
|
|
|
|
|
vo.setMaterialNo(mVO.getMaterialNo());
|
|
|
|
|
vo.setMaterialName(mVO.getMaterialName());
|
|
|
|
|
vo.setMaterialDesc(mVO.getMaterialDesc());
|
|
|
|
|
}
|
|
|
|
|
return vo;
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 手动同步到SAP
|
|
|
|
|
* @param rowIds
|
|
|
|
|
*/
|
|
|
|
|
public void sync2Sap(List<Long> rowIds) {
|
|
|
|
|
VUtils.isTure(CollUtil.isEmpty(rowIds)).throwMessage("请选择要同步数据");
|
|
|
|
|
rowIds.forEach(rowId -> syncChange2Sap(rowId, SessionUtil.getUserCode()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|