package com.aps.core.service.impl;
|
|
import java.math.BigDecimal;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Optional;
|
|
import cn.hutool.core.util.IdUtil;
|
import com.aps.common.core.utils.DateUtils;
|
import com.aps.common.security.utils.DictUtils;
|
import com.aps.common.security.utils.SecurityUtils;
|
import com.aps.core.domain.*;
|
import com.aps.core.mapper.*;
|
import com.aps.core.service.IApsBomService;
|
import com.aps.core.service.IApsPlateStandardRequireBomOrderDetailService;
|
import com.aps.core.service.IApsPlateStandardRequireBomStockDetailService;
|
import com.aps.system.api.domain.SysDictData;
|
import jakarta.annotation.Resource;
|
import com.aps.core.domain.ApsPlateStandardRequire;
|
import com.aps.core.mapper.ApsPlateStandardRequireMapper;
|
import com.aps.core.service.IApsPlateStandardRequireService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import com.aps.core.service.IApsPlateStandardRequireService;
|
|
import java.util.List;
|
|
/**
|
* 钣金工单标准需求Service业务层处理
|
*
|
* @author zhl
|
* @date 2025-05-06
|
*/
|
@Service
|
public class ApsPlateStandardRequireServiceImpl implements IApsPlateStandardRequireService
|
{
|
@Autowired
|
private ApsPlateStandardRequireMapper apsPlateStandardRequireMapper;
|
|
@Resource
|
private ApsPlateStandardRequireBatchMapper requireBatchMapper;
|
|
@Resource
|
ApsPlatePlanMapper platePlanMapper;
|
|
@Resource
|
ApsBomHeaderMapper bomHeaderMapper;
|
@Resource
|
IApsBomService bomLineService;
|
|
@Resource
|
ApsMaterialStorageManagementMapper itemStorageMapper;
|
|
@Resource
|
ApsPlateStandardRequireBomStockDetailMapper plateBomStockDetailMapper;
|
|
@Resource
|
IApsPlateStandardRequireBomStockDetailService bomStockDetailService;
|
@Resource
|
ApsStandardProcessRouteHeaderMapper standardProcessRouteHeaderMapper;
|
|
@Resource
|
ApsStandardProcessRouteLineMapper ApsStandardProcessRouteLineMapper;
|
|
@Resource
|
ApsPlateStandardRequireBomOrderDetailMapper plateBomOrderDetailMapper;
|
|
@Autowired
|
private ApsPlatePlanMapper apsPlatePlanMapper;
|
|
@Resource
|
IApsPlateStandardRequireBomOrderDetailService bomOrderDetailService;
|
|
|
/**
|
* 查询钣金工单标准需求
|
*
|
* @param id 钣金工单标准需求主键
|
* @return 钣金工单标准需求
|
*/
|
@Override
|
public ApsPlateStandardRequire selectApsPlateStandardRequireById(Long id)
|
{
|
return apsPlateStandardRequireMapper.selectApsPlateStandardRequireById(id);
|
}
|
|
/**
|
* 查询钣金工单标准需求列表
|
*
|
* @param apsPlateStandardRequire 钣金工单标准需求
|
* @return 钣金工单标准需求
|
*/
|
@Override
|
public List<ApsPlateStandardRequire> selectApsPlateStandardRequireList(ApsPlateStandardRequire apsPlateStandardRequire)
|
{
|
return apsPlateStandardRequireMapper.selectApsPlateStandardRequireList(apsPlateStandardRequire);
|
}
|
|
/**
|
* 新增钣金工单标准需求
|
*
|
* @param apsPlateStandardRequire 钣金工单标准需求
|
* @return 结果
|
*/
|
@Override
|
public int insertApsPlateStandardRequire(ApsPlateStandardRequire apsPlateStandardRequire)
|
{
|
apsPlateStandardRequire.setCreateTime(DateUtils.getNowDate());
|
return apsPlateStandardRequireMapper.insertApsPlateStandardRequire(apsPlateStandardRequire);
|
}
|
|
/**
|
* 修改钣金工单标准需求
|
*
|
* @param apsPlateStandardRequire 钣金工单标准需求
|
* @return 结果
|
*/
|
@Override
|
public int updateApsPlateStandardRequire(ApsPlateStandardRequire apsPlateStandardRequire)
|
{
|
apsPlateStandardRequire.setUpdateTime(DateUtils.getNowDate());
|
return apsPlateStandardRequireMapper.updateApsPlateStandardRequire(apsPlateStandardRequire);
|
}
|
|
/**
|
* 批量删除钣金工单标准需求
|
*
|
* @param ids 需要删除的钣金工单标准需求主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteApsPlateStandardRequireByIds(Long[] ids)
|
{
|
return apsPlateStandardRequireMapper.deleteApsPlateStandardRequireByIds(ids);
|
}
|
|
/**
|
* 删除钣金工单标准需求信息
|
*
|
* @param id 钣金工单标准需求主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteApsPlateStandardRequireById(Long id)
|
{
|
return apsPlateStandardRequireMapper.deleteApsPlateStandardRequireById(id);
|
}
|
|
/**
|
* 钣金供应缺口报表
|
* @param apsPlateStandardRequire
|
* @return
|
*/
|
@Override
|
public List<ApsPlateStandardRequire> selectPlateSupplyGapList(ApsPlateStandardRequire apsPlateStandardRequire) {
|
return apsPlateStandardRequireMapper.selectPlateSupplyGapList(apsPlateStandardRequire);
|
}
|
|
private void generatorPlan(){
|
|
/*定义工厂为南通 */
|
String plantCode="FORTUNA";
|
/*定义主单类型为钣金主单*/
|
String mainOrderType = "钣金主件";
|
/*定义子单类型为钣金子单*/
|
String subOrderType = "钣金子件";
|
/*生成新批次号*/
|
String batchNum=getBatch();
|
/*获取钣金主单信息*/
|
List<ApsPlatePlan> mainPlans = platePlanMapper.selectPlatePlanByPlantMajor(plantCode,mainOrderType);
|
List<ApsPlateStandardRequire> requiresList=new ArrayList<>();
|
for (ApsPlatePlan mainPlan : mainPlans) {
|
String itemNumber = mainPlan.getItemNumber();
|
/*根据料号 获取BOM Header */
|
}
|
|
|
|
}
|
private void getBomRequires(String plant, ApsBom bomLine, String batchNum, Date upLevelStartDate, ApsPlatePlan plan, List<ApsPlateStandardRequire> allRequires, Long level){
|
|
String itemNumber = bomLine.getItemCode();
|
String productivityModel_combined_batch="合批";
|
String productivityModel_monopolize="独占";
|
Optional<ApsStandardProcessRouteHeader> firstProcessRoute = standardProcessRouteHeaderMapper.queryStandardProcessRouteHeaderByPlantAndItemCode(plant, itemNumber).stream().findFirst();
|
if (firstProcessRoute.isPresent()) {
|
/*获取工艺路线Header信息*/
|
ApsStandardProcessRouteHeader routeHeader = firstProcessRoute.get();
|
/*构建需求信息*/
|
ApsPlateStandardRequire require = new ApsPlateStandardRequire();
|
require.setId(IdUtil.getSnowflakeNextId());
|
require.setRequireId(plan.getId());
|
require.setBatchNumber(batchNum);
|
require.setOrgCode(plant);
|
require.setBomLineCode(itemNumber);
|
require.setBomLineLevel(level);
|
require.setBomUseAmount(bomLine.getNum());
|
require.setCreateTime(DateUtils.getNowDate());
|
require.setCreateBy(SecurityUtils.getUsername());
|
/*计算需求数量*/
|
if (level == 0) {
|
require.setBomUseAmount(BigDecimal.ONE);
|
require.setCompleteDate(plan.getPlanEndDay());
|
require.setDemandDate(plan.getPlanEndDay());
|
} else {
|
require.setBomUseAmount(bomLine.getNum().multiply(plan.getProductionQuantity()));
|
}
|
/*查找库存,计算净需求,保存剩余库存,保存库存扣减明细*/
|
BigDecimal remainderStock = BigDecimal.ZERO;
|
Optional<ApsMaterialStorageManagement> itemStorage = getItemStorage(plant, itemNumber);
|
if (itemStorage.isPresent()) {
|
ApsMaterialStorageManagement storage = itemStorage.get();
|
/*剩余库存*/
|
remainderStock = storage.getRemainderStock();
|
/*计算净需求 默认=需求数量*/
|
if (remainderStock.compareTo(BigDecimal.ZERO) == 0) {
|
require.setNetRequirement(require.getBomUseAmount());
|
}
|
if (remainderStock.compareTo(BigDecimal.ZERO) > 0) {
|
BigDecimal subtract = require.getBomUseAmount().subtract(remainderStock);
|
BigDecimal deductionAmount = BigDecimal.ZERO;
|
BigDecimal afterStockAmount = BigDecimal.ZERO;
|
if (subtract.compareTo(BigDecimal.ZERO) >= 0) {
|
deductionAmount = remainderStock;
|
afterStockAmount = BigDecimal.ZERO;
|
require.setNetRequirement(subtract);
|
} else {
|
deductionAmount = require.getBomUseAmount();
|
afterStockAmount = remainderStock.subtract(deductionAmount);
|
require.setNetRequirement(BigDecimal.ZERO);
|
}
|
bomStockDetailService.saveStorageAndDetail(storage, plan, bomLine, batchNum, deductionAmount, afterStockAmount);
|
}
|
}
|
/*净需求*/
|
BigDecimal netRequirement = require.getNetRequirement();
|
/*工艺路线总需求*/
|
BigDecimal totalRouteTime = getRouteLineTotalTime(routeHeader, productivityModel_monopolize, netRequirement);
|
long millisecond = 60*60*1000L;
|
long totalRouteMillisecond = totalRouteTime.multiply(BigDecimal.valueOf(millisecond)).longValue();
|
/*完成时间,level=0 时默认为工单的计划完成日期*/
|
Date completeDate= plan.getPlanEndDay();
|
/*预留天数*/
|
Long reservedDay = getReservedDays();
|
if(level>0){
|
/* 当前需求完成日期为上阶层需求的开始时间 - 预留天数(转换为毫秒)*/
|
long reservedMillisecond = reservedDay *24* millisecond;
|
completeDate.setTime(upLevelStartDate.getTime()-reservedMillisecond);
|
}
|
/*设置完成日期*/
|
require.setCompleteDate(completeDate);
|
require.setDemandDate(require.getCompleteDate());
|
/*设置开始时间*/
|
Date startDay = new Date();
|
startDay.setTime(completeDate.getTime() - totalRouteMillisecond);
|
require.setStartDate(startDay);
|
require.setMatchState("已匹配");
|
require.setMatchMode("库存匹配");
|
if(require.getNetRequirement().compareTo(BigDecimal.ZERO)>0){
|
require.setMatchState("待匹配");
|
require.setMatchMode("工单匹配");
|
}
|
require.setHasDelayRisk("无风险");
|
|
allRequires.add(require);
|
/*当前Bom节点处理完成后,处理下级BOM*/
|
List<ApsBom> bomLineList = bomLineService.selectApsBomLineList(plant, itemNumber);
|
if(!bomLineList.isEmpty()){
|
bomLineList.forEach(line -> {
|
getBomRequires(plant, line, batchNum, require.getStartDate(), plan, allRequires, level+1);
|
});
|
}
|
|
} else {
|
throw new RuntimeException("未找到标准工艺路线");
|
}
|
}
|
|
private BigDecimal getRouteLineTotalTime(ApsStandardProcessRouteHeader routeHeader, String productivityModel_monopolize, BigDecimal netRequirement) {
|
ApsStandardProcessRouteLine routeLineParam = ApsStandardProcessRouteLine.builder()
|
.routeId(routeHeader.getRouteId())
|
.build();
|
List<ApsStandardProcessRouteLine> apsStandardProcessRouteLines = ApsStandardProcessRouteLineMapper.selectApsStandardProcessRouteLineList(routeLineParam);
|
/*工艺路线Line 总工时*/
|
BigDecimal totalRouteTime = BigDecimal.ZERO;
|
apsStandardProcessRouteLines.forEach(line -> {
|
line.setRouteTime(line.getDesignCapacity());
|
if (line.getProductivityModel().equals(productivityModel_monopolize)) {
|
line.setRouteTime(line.getDesignCapacity().multiply(netRequirement));
|
}
|
totalRouteTime.add(line.getRouteTime());
|
});
|
return totalRouteTime;
|
}
|
|
/**
|
* 生成新批次号
|
* */
|
private String getBatch() {
|
String batchNum = System.currentTimeMillis() + "";
|
ApsPlateStandardRequireBatch batchBuilder = ApsPlateStandardRequireBatch.builder()
|
.id(IdUtil.getSnowflakeNextId())
|
.batchNumber(batchNum)
|
.delFlag("0").build();
|
batchBuilder.setCreateBy(SecurityUtils.getUsername());
|
batchBuilder.setCreateTime(DateUtils.getNowDate());
|
requireBatchMapper.insertApsPlateStandardRequireBatch(batchBuilder);
|
return batchNum;
|
}
|
/**
|
* 获取物料库存信息
|
* */
|
private Optional<ApsMaterialStorageManagement> getItemStorage(String plant, String itemNumber) {
|
ApsMaterialStorageManagement storageParam = new ApsMaterialStorageManagement();
|
storageParam.setItemNumber(itemNumber);
|
storageParam.setApplicableFactories(plant);
|
Optional<ApsMaterialStorageManagement> firstStorage = itemStorageMapper.selectApsMaterialStorageManagementList(storageParam).stream()
|
.findFirst();
|
|
return firstStorage;
|
}
|
|
/**
|
* 获取钣金计划 预留天数
|
* */
|
private Long getReservedDays(){
|
Long days=0L;
|
List<SysDictData> dictDataList = DictUtils.getDictCache("aps_is_suspended");
|
if (dictDataList != null) {
|
Long.getLong(dictDataList.get(0).getDictValue());
|
}
|
return days;
|
}
|
|
/**
|
* 使用子件工单匹配需求中的净需求
|
* */
|
private void matchRequireAndSubPlan(ApsPlateStandardRequire require) {
|
BigDecimal netRequirement = require.getNetRequirement();
|
if (netRequirement.compareTo(BigDecimal.ZERO) > 0) {
|
ApsPlatePlan platePlan = apsPlatePlanMapper.selectUnMatchPlateSubPlan(require.getOrgCode());
|
/*子件工单的未匹配数量 作为当前的库存*/
|
BigDecimal stock = platePlan.getUnmatchedQuantity();
|
if (netRequirement.compareTo(stock) < 0) {
|
/* 库存数量 大于 净需求数量*/
|
/* 净需求数量=0 ,子件工单未匹配数量= 库存-净需求*/
|
netRequirement = BigDecimal.ZERO;
|
require.setNetRequirement(netRequirement);
|
BigDecimal subtract = stock.subtract(netRequirement);
|
bomOrderDetailService.savePlastPlanAndBomOrderDetail(require, platePlan, subtract, stock, netRequirement);
|
/*净需求已经被满足,不需要继续匹配*/
|
|
} else if (netRequirement.compareTo(stock) == 0) {
|
/*净需求数量 == 库存数量*/
|
netRequirement = BigDecimal.ZERO;
|
require.setNetRequirement(netRequirement);
|
BigDecimal subtract = BigDecimal.ZERO;
|
bomOrderDetailService.savePlastPlanAndBomOrderDetail(require, platePlan, subtract, stock, netRequirement);
|
/*净需求已经被满足,不需要继续匹配*/
|
}
|
if (netRequirement.compareTo(stock) > 0) {
|
while (platePlan != null && netRequirement.compareTo(BigDecimal.ZERO) > 0) {
|
/*需求大于库存*/
|
/*净需求 被部分满足 */
|
BigDecimal rest = netRequirement.subtract(stock);
|
require.setNetRequirement(rest);
|
require.setMatchState("匹配中");
|
/*工单 未匹配数量为0 全部用于匹配需求*/
|
bomOrderDetailService.savePlastPlanAndBomOrderDetail(require, platePlan, BigDecimal.ZERO, stock, netRequirement);
|
/*净需求未被满足,需要继续匹配*/
|
platePlan = apsPlatePlanMapper.selectUnMatchPlateSubPlan(require.getOrgCode());
|
netRequirement = rest;
|
}
|
}
|
|
}
|
}
|
|
|
|
}
|