【生产订单管理】
This commit is contained in:
parent
6e9466004b
commit
8447cf9ad9
|
|
@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.nflg.product.base.core.api.BaseApi;
|
||||
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.EbomQueryMaterialsVO;
|
||||
import com.nflg.product.bomnew.pojo.vo.ProductionOrderItemVO;
|
||||
import com.nflg.product.bomnew.pojo.vo.ProductionOrderVO;
|
||||
import com.nflg.product.bomnew.service.ProductionOrderService;
|
||||
|
|
@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -113,4 +116,26 @@ public class ProductionOrderApi extends BaseApi {
|
|||
return productionOrderService.syncProductionOrderFromSap(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询物料信息
|
||||
* @param query query
|
||||
* @return 物料信息
|
||||
*/
|
||||
@PostMapping("queryMaterials")
|
||||
@ApiOperation("批量查询物料信息")
|
||||
public ResultVO<List<EbomQueryMaterialsVO>> queryMaterials(@Valid @RequestBody @NotEmpty List<QueryMaterialsQuery> query) {
|
||||
return ResultVO.success(productionOrderService.queryMaterials(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动同步到SAP
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("sync2Sap")
|
||||
@ApiOperation("手动同步到SAP")
|
||||
public ResultVO<String> sync2Sap(@RequestBody List<Long> rowIds) {
|
||||
productionOrderService.sync2Sap(rowIds);
|
||||
return ResultVO.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.nflg.product.bomnew.job;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import com.nflg.product.bomnew.pojo.query.ProductionOrderQuery;
|
||||
import com.nflg.product.bomnew.service.ProductionOrderService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class SaticScheduleTask {
|
||||
|
||||
@Resource
|
||||
private ProductionOrderService productionOrderService;
|
||||
|
||||
/**
|
||||
* 每天2点,自动同步前一天SAP生产订单
|
||||
*/
|
||||
@Scheduled(cron = "${bom.production.sync.sap.time:0 0 2 * * ?}")
|
||||
public void syncProductionOrderFromSap() {
|
||||
ProductionOrderQuery query = new ProductionOrderQuery();
|
||||
String date = LocalDateTimeUtil.format(LocalDateTime.now().plusDays(-1), "yyyy-MM-dd");
|
||||
query.setStartDate(date);
|
||||
query.setEndDate(date);
|
||||
productionOrderService.syncProductionOrderFromSap(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.nflg.product.bomnew.pojo.dto.sap.production;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ProImportSapParamDTO {
|
||||
@ApiModelProperty("生产订单")
|
||||
private String I_AUFNR;
|
||||
|
||||
@ApiModelProperty("详情")
|
||||
private List<ProT1DTO> T1;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.nflg.product.bomnew.pojo.dto.sap.production;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ProT1DTO {
|
||||
|
||||
/**
|
||||
* 项目 POSNR
|
||||
* 组件 MATNR
|
||||
* 需求数量 BDMNG
|
||||
* 单位 MEINS
|
||||
* 存储地点 LGORT
|
||||
* 反冲
|
||||
* 操作类型 OTYPE
|
||||
*/
|
||||
|
||||
@ApiModelProperty("项目")
|
||||
private String POSNR;
|
||||
|
||||
@ApiModelProperty("组件")
|
||||
private String MATNR;
|
||||
|
||||
@ApiModelProperty("需求数量")
|
||||
private String BDMNG;
|
||||
|
||||
@ApiModelProperty("单位")
|
||||
private String MEINS;
|
||||
|
||||
@ApiModelProperty("LGORT")
|
||||
private String LGORT;
|
||||
|
||||
@ApiModelProperty("操作类型 0不变 1新增 2修改 3删除")
|
||||
private String OTYPE;
|
||||
}
|
||||
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue