|
|
|
@ -7,13 +7,18 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
|
|
|
|
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
|
|
|
|
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
|
|
|
|
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
|
|
|
|
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.feedingplan.vo.FeedingRecordPlanRespVO;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.feedingplan.vo.FeedingRecordPlanRespVO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.itemrequisition.vo.ItemRequisitionDetailRespVO;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.stockworkshop.vo.StockWorkShopTypeEnum;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.stockworkshop.vo.StockWorkShopTypeEnum;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingplan.FeedingRecordPlanDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingplan.FeedingRecordPlanDO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.itemrequisition.ItemRequisitionDO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.itemrequisition.ItemRequisitionDetailDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.stockworkshop.StockWorkshopDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.stockworkshop.StockWorkshopDO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.feedingplan.FeedingRecordPlanMapper;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.feedingplan.FeedingRecordPlanService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.feedingplan.FeedingRecordPlanService;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemRequisitionService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.plan.PlanService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.plan.PlanService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.stockworkshop.StockWorkshopDetailService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.stockworkshop.StockWorkshopDetailService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.stockworkshop.StockWorkshopService;
|
|
|
|
import cn.iocoder.yudao.module.mes.service.stockworkshop.StockWorkshopService;
|
|
|
|
@ -24,6 +29,8 @@ import org.springframework.validation.annotation.Validated;
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
|
|
|
import java.math.MathContext;
|
|
|
|
|
|
|
|
import java.math.RoundingMode;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.*;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.feedingrecord.vo.*;
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.feedingrecord.vo.*;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingrecord.FeedingRecordDO;
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingrecord.FeedingRecordDO;
|
|
|
|
@ -38,6 +45,7 @@ import cn.iocoder.yudao.module.mes.dal.mysql.feedingrecord.FeedingRecordDetailMa
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
|
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
|
|
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
|
|
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
|
|
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
|
|
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
|
|
|
|
|
|
|
|
|
|
|
@ -65,11 +73,10 @@ public class FeedingRecordServiceImpl implements FeedingRecordService {
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private FeedingRecordPlanService recordPlanService;
|
|
|
|
private FeedingRecordPlanService recordPlanService;
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private StockWorkshopService workshopService;
|
|
|
|
private FeedingRecordPlanMapper recordPlanMapper;
|
|
|
|
@Resource
|
|
|
|
|
|
|
|
private StockWorkshopDetailService workshopDetailService;
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private PlanService planService;
|
|
|
|
private StockWorkshopService workshopService;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
@ -80,6 +87,7 @@ public class FeedingRecordServiceImpl implements FeedingRecordService {
|
|
|
|
FeedingRecordDO feedingRecord = BeanUtils.toBean(createReqVO, FeedingRecordDO.class);
|
|
|
|
FeedingRecordDO feedingRecord = BeanUtils.toBean(createReqVO, FeedingRecordDO.class);
|
|
|
|
feedingRecord.setRecordStatus(FeedingStatusEnum.草稿.getValue());
|
|
|
|
feedingRecord.setRecordStatus(FeedingStatusEnum.草稿.getValue());
|
|
|
|
feedingRecordMapper.insert(feedingRecord);
|
|
|
|
feedingRecordMapper.insert(feedingRecord);
|
|
|
|
|
|
|
|
//todo 检查投料原料项,如果不是kg,则转为kg
|
|
|
|
|
|
|
|
|
|
|
|
// 插入子表
|
|
|
|
// 插入子表
|
|
|
|
createFeedingRecordDetailList(feedingRecord.getId(), createReqVO.getFeedingRecordDetails());
|
|
|
|
createFeedingRecordDetailList(feedingRecord.getId(), createReqVO.getFeedingRecordDetails());
|
|
|
|
@ -183,34 +191,123 @@ public class FeedingRecordServiceImpl implements FeedingRecordService {
|
|
|
|
* **/
|
|
|
|
* **/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
public void updateStatus(Long id, String status) {
|
|
|
|
public void updateStatus(FeedingRecordDO recordDO,List<FeedingRecordDetailDO> detailDOList, String status , Long userId
|
|
|
|
FeedingRecordDO recordDO = feedingRecordMapper.selectById(id);
|
|
|
|
,List<PlanDO> planDOList,Map<Long, List<ItemRequisitionDetailRespVO>> planItemListMap,
|
|
|
|
if(recordDO==null) throw exception(FEEDING_RECORD_NOT_EXISTS);
|
|
|
|
Map<String, ItemRequisitionDetailRespVO> planItemMap) {
|
|
|
|
//后续步骤只处理领料投料的投料单,湿废品和干废品投料暂不处理
|
|
|
|
|
|
|
|
if(!recordDO.getFeedingType().equals(FeedingTypeEnum.领料.getValue()))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
List<FeedingRecordDetailDO> detailDOList = getFeedingRecordDetailListByRecordId(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Integer> statusList = new ArrayList<>();
|
|
|
|
|
|
|
|
statusList.add(PlanStatusEnum.开工.getValue());
|
|
|
|
|
|
|
|
List<PlanDO> planDOList = planService.getPlanByStatus(statusList);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(status.equals(FeedingStatusEnum.提交.getValue())) {
|
|
|
|
if(status.equals(FeedingStatusEnum.提交.getValue())) {
|
|
|
|
|
|
|
|
//detailDOMap 汇总投料原料
|
|
|
|
|
|
|
|
Map<Long, FeedingRecordDetailDO>detailDOMap = new HashMap<>();
|
|
|
|
for (FeedingRecordDetailDO recordDetailDO: detailDOList) {
|
|
|
|
for (FeedingRecordDetailDO recordDetailDO: detailDOList) {
|
|
|
|
|
|
|
|
//车间仓投料出库
|
|
|
|
StockWorkshopDO workshopDO = new StockWorkshopDO()
|
|
|
|
StockWorkshopDO workshopDO = new StockWorkshopDO()
|
|
|
|
.setItemId(recordDetailDO.getItemId())
|
|
|
|
.setItemId(recordDetailDO.getItemId())
|
|
|
|
.setCount(recordDetailDO.getWeight().multiply(BigDecimal.valueOf(-1)))
|
|
|
|
.setCount(recordDetailDO.getWeight().multiply(BigDecimal.valueOf(-1)))
|
|
|
|
.setCategoryId(1L);
|
|
|
|
.setCategoryId(1L);
|
|
|
|
workshopService.updateStock(workshopDO, StockWorkShopTypeEnum.投料出库.getValue(),
|
|
|
|
workshopService.updateStock(workshopDO, StockWorkShopTypeEnum.投料出库.getValue(),
|
|
|
|
recordDO.getId(), recordDO.getFeedingRecordCode());
|
|
|
|
recordDO.getId(), recordDO.getFeedingRecordCode());
|
|
|
|
|
|
|
|
//合并同原料
|
|
|
|
|
|
|
|
if(detailDOMap.containsKey(recordDetailDO.getItemId())){
|
|
|
|
|
|
|
|
BigDecimal totalWeight = detailDOMap.get(recordDetailDO.getItemId()).getWeight()
|
|
|
|
|
|
|
|
.add(recordDetailDO.getWeight());
|
|
|
|
|
|
|
|
detailDOMap.get(recordDetailDO.getItemId()).setWeight(totalWeight);
|
|
|
|
|
|
|
|
}else detailDOMap.put(recordDetailDO.getItemId(), recordDetailDO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dealPlan(detailDOMap,recordDO, userId, planDOList, planItemListMap, planItemMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//todo 需要回退吗?
|
|
|
|
//todo 需要回退吗?
|
|
|
|
else if(status.equals(FeedingStatusEnum.草稿.getValue())) {
|
|
|
|
else if(status.equals(FeedingStatusEnum.草稿.getValue())) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void dealPlan(Map<Long, FeedingRecordDetailDO> detailDOMap , FeedingRecordDO recordDO, Long userId,
|
|
|
|
|
|
|
|
List<PlanDO> planDOList,Map<Long, List<ItemRequisitionDetailRespVO>> planItemListMap,
|
|
|
|
|
|
|
|
Map<String, ItemRequisitionDetailRespVO> planItemMap){
|
|
|
|
|
|
|
|
MathContext mc = new MathContext(3, RoundingMode.HALF_UP);
|
|
|
|
|
|
|
|
//分配计划
|
|
|
|
|
|
|
|
//totalPlanNeedItem记录所有计划需要的该原料总数,用于最后按比例分配原料
|
|
|
|
|
|
|
|
Map<Long, BigDecimal>totalPlanNeedItem = new HashMap<>();
|
|
|
|
|
|
|
|
//recordPlanDOMap 记录已分配计划id原料id对应的分配量,同计划id原料id的合并为一个记录,最终插入数据库
|
|
|
|
|
|
|
|
Map<String, FeedingRecordPlanDO> recordPlanDOMap = new HashMap<>();
|
|
|
|
|
|
|
|
for (int i = 0; i < planDOList.size(); i++) {
|
|
|
|
|
|
|
|
List<ItemRequisitionDetailRespVO> list = planItemListMap.get(planDOList.get(i).getId());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(ItemRequisitionDetailRespVO respVO: list){
|
|
|
|
|
|
|
|
//原料需要分配
|
|
|
|
|
|
|
|
int cp = respVO.getNumber().compareTo(respVO.getFinishNumber());
|
|
|
|
|
|
|
|
if(detailDOMap.containsKey(respVO.getProductId())
|
|
|
|
|
|
|
|
&& detailDOMap.get(respVO.getProductId()).getWeight().compareTo(BigDecimal.ZERO) > 0
|
|
|
|
|
|
|
|
&& cp > 0 ){
|
|
|
|
|
|
|
|
FeedingRecordDetailDO detailDO = detailDOMap.get(respVO.getProductId());
|
|
|
|
|
|
|
|
BigDecimal weight = respVO.getNumber().subtract(respVO.getFinishNumber(), mc);
|
|
|
|
|
|
|
|
//投料不能满足计划需求,则对该计划投料为实际投料数量, 否则满足,为需求数量
|
|
|
|
|
|
|
|
if(weight.compareTo(detailDO.getWeight()) > 0 ){
|
|
|
|
|
|
|
|
weight = detailDO.getWeight();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//未分配投料数量减少
|
|
|
|
|
|
|
|
detailDO.setWeight(detailDO.getWeight().subtract(weight));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String key = getMapKey(planDOList.get(i).getId(), respVO.getProductId());
|
|
|
|
|
|
|
|
if(recordPlanDOMap.containsKey(key)){
|
|
|
|
|
|
|
|
//正常来说单个计划再做物料分析的时候只会产生一条ItemRequisitionDetailRespVO
|
|
|
|
|
|
|
|
recordPlanDOMap.get(key).setWeight( recordPlanDOMap.get(key).getWeight().add(weight));
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
|
|
FeedingRecordPlanDO recordPlanDO = new FeedingRecordPlanDO()
|
|
|
|
|
|
|
|
.setPlanId(planDOList.get(i).getId())
|
|
|
|
|
|
|
|
.setItemId(respVO.getProductId())
|
|
|
|
|
|
|
|
.setRecordId(recordDO.getId()).setUserId(userId).setUnitId(respVO.getUnitId())
|
|
|
|
|
|
|
|
.setRecordDetailId(respVO.getId()).setFeedingTime(detailDO.getFeedingTime())
|
|
|
|
|
|
|
|
.setWeight(weight);
|
|
|
|
|
|
|
|
recordPlanDOMap.put(key, recordPlanDO);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(totalPlanNeedItem.containsKey(respVO.getProductId())){
|
|
|
|
|
|
|
|
BigDecimal totalNumber = totalPlanNeedItem.get(respVO.getProductId()).add(respVO.getNumber());
|
|
|
|
|
|
|
|
totalPlanNeedItem.put(respVO.getProductId(), totalNumber);
|
|
|
|
|
|
|
|
}else totalPlanNeedItem.put(respVO.getProductId(), respVO.getNumber());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dealLast(detailDOMap, recordDO.getId(), userId, planDOList, totalPlanNeedItem, recordPlanDOMap, planItemMap);
|
|
|
|
|
|
|
|
//插入
|
|
|
|
|
|
|
|
recordPlanMapper.insertBatch(recordPlanDOMap.values());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//处理剩余未分配原料,按照totalPlanNeedItem 比例分配到每个计划
|
|
|
|
|
|
|
|
private Map<String, FeedingRecordPlanDO> dealLast(Map<Long, FeedingRecordDetailDO> detailDOMap, Long recordId, Long userId
|
|
|
|
|
|
|
|
, List<PlanDO> planDOList, Map<Long, BigDecimal>totalPlanNeedItem, Map<String, FeedingRecordPlanDO> recordPlanDOMap ,
|
|
|
|
|
|
|
|
Map<String, ItemRequisitionDetailRespVO> planItemMap){
|
|
|
|
|
|
|
|
MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (Long itemId : detailDOMap.keySet()) {
|
|
|
|
|
|
|
|
//原料有未分配数量
|
|
|
|
|
|
|
|
if(detailDOMap.get(itemId).getWeight().compareTo(BigDecimal.ZERO) <= 0)continue;
|
|
|
|
|
|
|
|
BigDecimal factor = detailDOMap.get(itemId).getWeight().divide(totalPlanNeedItem.get(itemId), mc);
|
|
|
|
|
|
|
|
for (PlanDO plan : planDOList) {
|
|
|
|
|
|
|
|
ItemRequisitionDetailRespVO detailRespVO = planItemMap.get(getMapKey(plan.getId(),itemId));
|
|
|
|
|
|
|
|
//该计划不需要这种物料
|
|
|
|
|
|
|
|
if(detailRespVO==null){
|
|
|
|
|
|
|
|
System.out.println("~~~~~~~计算出错!~~~~~~");
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BigDecimal weight = factor.multiply(detailRespVO.getNumber());
|
|
|
|
|
|
|
|
String key = getMapKey(plan.getId(), itemId);
|
|
|
|
|
|
|
|
if(recordPlanDOMap.containsKey(key)){
|
|
|
|
|
|
|
|
recordPlanDOMap.get(key).setWeight( recordPlanDOMap.get(key).getWeight().add(weight));
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
|
|
FeedingRecordPlanDO recordPlanDO = new FeedingRecordPlanDO()
|
|
|
|
|
|
|
|
.setPlanId(plan.getId()).setItemId(itemId)
|
|
|
|
|
|
|
|
.setRecordId(recordId).setUserId(userId).setUnitId(detailRespVO.getUnitId())
|
|
|
|
|
|
|
|
.setRecordDetailId(detailDOMap.get(itemId).getId())
|
|
|
|
|
|
|
|
.setFeedingTime(detailDOMap.get(itemId).getFeedingTime())
|
|
|
|
|
|
|
|
.setWeight(weight);
|
|
|
|
|
|
|
|
recordPlanDOMap.put(key, recordPlanDO);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return recordPlanDOMap;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private String getMapKey(Long planId, Long itemId){
|
|
|
|
|
|
|
|
return planId + "-" + itemId;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|