/*
|
* Copyright (c) 2018-2025, ztt All rights reserved.
|
*
|
* Redistribution and use in source and binary forms, with or without
|
* modification, are permitted provided that the following conditions are met:
|
*
|
* Redistributions of source code must retain the above copyright notice,
|
* this list of conditions and the following disclaimer.
|
* Redistributions in binary form must reproduce the above copyright
|
* notice, this list of conditions and the following disclaimer in the
|
* documentation and/or other materials provided with the distribution.
|
* Neither the name of the pig4cloud.com developer nor the names of its
|
* contributors may be used to endorse or promote products derived from
|
* this software without specific prior written permission.
|
* Author: ztt
|
*/
|
package com.chinaztt.mes.warehouse.service.impl;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.chinaztt.mes.basic.dto.LocationIfsMoveDTO;
|
import com.chinaztt.mes.basic.entity.Location;
|
import com.chinaztt.mes.basic.entity.Part;
|
import com.chinaztt.mes.basic.mapper.PartMapper;
|
import com.chinaztt.mes.basic.service.LocationService;
|
import com.chinaztt.mes.warehouse.dto.PalletTransportsDetailDTO;
|
import com.chinaztt.mes.warehouse.dto.StockAddDTO;
|
import com.chinaztt.mes.warehouse.dto.StockDTO;
|
import com.chinaztt.mes.warehouse.entity.*;
|
import com.chinaztt.mes.warehouse.mapper.PalletTransportsDetailMapper;
|
import com.chinaztt.mes.warehouse.mapper.PalletTransportsMapper;
|
import com.chinaztt.mes.warehouse.mapper.PalletTransportsMaterialMapper;
|
import com.chinaztt.mes.warehouse.service.PalletTransportsDetailService;
|
import com.chinaztt.mes.warehouse.service.PalletTransportsMaterialService;
|
import com.chinaztt.mes.warehouse.service.StockService;
|
import com.chinaztt.mes.warehouse.state.constant.PalletTransportsState;
|
import com.chinaztt.mes.warehouse.state.pallettransportsdetail.PalletTransportsDetailStateStringValues;
|
import com.chinaztt.mes.warehouse.util.StockUtils;
|
import com.chinaztt.mes.warehouse.util.WareHouseUtils;
|
import com.chinaztt.ztt.common.core.util.R;
|
import lombok.AllArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.math.BigInteger;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 货盘运输任务移库明细表
|
*
|
* @author shz
|
* @date 2022-05-24 17:17:26
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
@Service
|
@AllArgsConstructor
|
public class PalletTransportsDetailServiceImpl extends ServiceImpl<PalletTransportsDetailMapper, PalletTransportsDetail> implements PalletTransportsDetailService {
|
|
private LocationService locationService;
|
private StockService stockService;
|
private JoinStockOrderServiceImpl joinStockOrderService;
|
private PalletTransportsMaterialMapper palletTransportsMaterialMapper;
|
private PartMapper partMapper;
|
private WareHouseUtils wareHouseUtils;
|
private StockUtils stockUtils;
|
private PalletTransportsMaterialService transportsMaterialService;
|
private PalletTransportsMapper palletTransportsMapper;
|
private PalletTransportsDetailMapper palletTransportsDetailMapper;
|
// @Autowired
|
// public PalletTransportsDetailServiceImpl(@Lazy PalletTransportsMaterialService palletTransportsMaterialService) {
|
// this.palletTransportsMaterialService = palletTransportsMaterialService;
|
// }
|
|
@Override
|
public synchronized void executeMoveLocation(List<Long> ids) {
|
List<PalletTransportsDetailDTO> list = this.baseMapper.getInitialDetailsByIds(ids);
|
if (list.isEmpty()) {
|
throw new RuntimeException("没有可执行数据");
|
}
|
|
|
|
Map<String, Location> locationMap = new HashMap<>();
|
// 判断至库位是否有值,是否绑定mes库位
|
for (PalletTransportsDetailDTO check : list) {
|
Part part = partMapper.selectById(check.getPartId());
|
if(!part.getLotTrackingIfs()){
|
if(!"*".equals(check.getWdr())){
|
throw new RuntimeException("零件号"+part.getPartNo()+"未启用批次管理,且wdr不为“*”");
|
}
|
|
}
|
if (StringUtils.isBlank(check.getToIfsLocationNo())) {
|
throw new RuntimeException(check.getPartNo() + "至库位为空");
|
}
|
List<Location> locationList = locationService.list(Wrappers.<Location>lambdaQuery()
|
.eq(Location::getIfsLocation, check.getToIfsLocationNo())
|
.isNotNull(Location::getTransportLocationNo)
|
.eq(Location::getLocStatus, 1).eq(Location::getActive, true));
|
if (locationList.isEmpty()) {
|
throw new RuntimeException("IFS库位:" + check.getToIfsLocationNo() + ",未找到MES库位对应的货盘运输库位");
|
}
|
// 根据货盘运输库位号找到原本对应的MES库位
|
Location location = locationService.getOne(Wrappers.<Location>lambdaQuery()
|
.eq(Location::getLocNo, locationList.get(0).getTransportLocationNo())
|
.eq(Location::getLocStatus, 1).eq(Location::getActive, true));
|
if (location == null) {
|
throw new RuntimeException("货盘运输库位:" + locationList.get(0).getTransportLocationNo() + ",未找到MES库位");
|
}
|
locationMap.put(check.getToIfsLocationNo(), location);
|
}
|
|
// ifs移库
|
LocationIfsMoveDTO moveDTO = new LocationIfsMoveDTO();
|
moveDTO.setRECORD_ID(UUID.randomUUID().toString().replace("-", ""));
|
List<LocationIfsMoveDTO.DataBean> dataBeans = new ArrayList<>();
|
moveDTO.setBATCH_INFO(dataBeans);
|
|
for (PalletTransportsDetailDTO detail : list) {
|
Part part = partMapper.selectById(detail.getPartId());
|
LocationIfsMoveDTO.DataBean bean = new LocationIfsMoveDTO.DataBean();
|
bean.setPART_NO(detail.getPartNo());
|
if (part.getLotTrackingIfs() != null && part.getLotTrackingIfs()) {
|
bean.setLOT_BATCH_NO(detail.getBatchNo());
|
bean.setWAIV_DEV_REJ_NO(detail.getWdr());
|
} else {
|
bean.setLOT_BATCH_NO("*");
|
bean.setWAIV_DEV_REJ_NO("*");
|
}
|
bean.setMOVE_QTY(detail.getTransferQuantity());
|
bean.setLOCATION_NO(detail.getFromIfsLocationNo());
|
bean.setTO_LOCATION_NO(detail.getToIfsLocationNo());
|
bean.setMOVE_COMMENT(detail.getTransportsNo());
|
dataBeans.add(bean);
|
}
|
|
R response = locationService.moveIfsLocation(moveDTO);
|
// ifs移库成功
|
if (response.getCode() == 0) {
|
UpdateWrapper<PalletTransportsDetail> updateWrapper = new UpdateWrapper<>();
|
this.update(updateWrapper.lambda().in(PalletTransportsDetail::getId, list.stream().map(PalletTransportsDetail::getId).collect(Collectors.toList()))
|
.set(PalletTransportsDetail::getIfsRecordId, moveDTO.getRECORD_ID()).set(PalletTransportsDetail::getState, PalletTransportsDetailStateStringValues.SUBMITTED));
|
//更改主表状态
|
changeTransportsState(list.get(0).getTransportsId());
|
|
// 物料入mes库
|
for (PalletTransportsDetailDTO detail : list) {
|
Location location = locationMap.get(detail.getToIfsLocationNo());
|
|
StockDTO stockDTO = new StockDTO();
|
stockDTO.setPartBatchNo(detail.getWdr());
|
stockDTO.setPartNo(detail.getPartNo());
|
stockDTO.setPartName(detail.getPartDesc());
|
stockDTO.setLocationNo(location.getLocNo());
|
stockDTO.setPartId(detail.getPartId());
|
stockDTO.setLocationId(location.getId());
|
stockDTO.setIfsBatchNo(detail.getBatchNo());
|
stockDTO.setStockQuantity(detail.getTransferQuantity());
|
|
StockAddDTO stockAdd = new StockAddDTO();
|
stockAdd.setPartsId(stockDTO.getPartId());
|
stockAdd.setNewLocationId(stockDTO.getLocationId());
|
stockAdd.setNewPartBatchNo(stockDTO.getPartBatchNo());
|
stockAdd.setReelNumber(stockDTO.getReelNumber());
|
|
Stock newStock = stockUtils.query(stockAdd);
|
stockUtils.updateById(newStock.getId(), stockDTO.getStockQuantity(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, null, "RECEIVE");
|
// 更新ifs批次号
|
Stock update = new Stock();
|
update.setId(newStock.getId());
|
update.setIfsBatchNo(detail.getBatchNo());
|
// 货盘运输任务来的物料,是否工序库存都为false
|
update.setOperationStockStatus(false);
|
stockService.updateById(update);
|
// 自动预留
|
if (null != detail.getOperationTaskId()) {
|
joinStockOrderService.addJoinStock(detail.getOperationTaskId(), newStock, detail.getTransferQuantity());
|
}
|
|
}
|
}
|
}
|
|
|
@Override
|
public R checkScanPalletTransportsDetail(Long transportsId, String partNo, String batchNo, String wdr) {
|
if (StringUtils.isBlank(partNo) || StringUtils.isBlank(Long.toString(transportsId)) || StringUtils.isBlank(batchNo) || StringUtils.isBlank(wdr)) {
|
return R.failed("零件号||货盘运输主表id||ifs批次号||wdr号为空");
|
}
|
//根据零件号获取零件id
|
List<Part> partList = partMapper.selectList(Wrappers.<Part>lambdaQuery().eq(Part::getPartNo, partNo));
|
if (CollectionUtil.isEmpty(partList)) {
|
return R.failed("零件号=" + partNo + "->mes无对应基础数据");
|
} else if (partList.size() > 1) {
|
return R.failed("零件号=" + partNo + "->mes中对应的基础数据存在多条");
|
}
|
|
//判断查询的零件号是否在对应的货盘运输物料需求计划明细中
|
List<PalletTransportsMaterial> palletTransportsMaterialList = palletTransportsMaterialMapper.selectList(Wrappers.<PalletTransportsMaterial>lambdaQuery().eq(PalletTransportsMaterial::getTransportsId, transportsId).eq(PalletTransportsMaterial::getPartId, partList.get(0).getId()));
|
if (CollectionUtil.isEmpty(palletTransportsMaterialList)) {
|
return R.failed("零件号=" + partNo + "->不在此货盘运输任务物料需求列表中");
|
}
|
|
//调ifs库存查询接口
|
R ifsres = wareHouseUtils.getIfsStockPrecise(partNo, batchNo, wdr);
|
JSONArray array = (JSONArray) JSON.toJSON(ifsres.getData());
|
BigDecimal qtyAvailable = new BigDecimal(BigInteger.ZERO);
|
for (int i = 0; i < array.size(); i++) {
|
qtyAvailable = qtyAvailable.add(array.getJSONObject(i).getBigDecimal("QTY_AVAILABLE"));//可用库存数量
|
}
|
return R.ok(array, qtyAvailable.toString());//将ifs可用库存数量:ifs库位号键值对及可用数量求和后返回
|
}
|
|
@Override
|
public Boolean saveBatchDetails(List<PalletTransportsDetail> details) {
|
transportsMaterialService.checkTransportsState(details.get(0).getTransportsId());
|
// 设置初始状态,增加移库数量
|
BigDecimal quantity = BigDecimal.ZERO;
|
for (PalletTransportsDetail detail : details) {
|
detail.setState(PalletTransportsDetailStateStringValues.INITIAL);
|
quantity = quantity.add(detail.getTransferQuantity());
|
}
|
// 更新物料需求
|
transportsMaterialService.calculateQuantity(details.get(0).getTransportsMaterialId(), quantity, true);
|
// 更新是否存在明细状态
|
PalletTransportsMaterial update = new PalletTransportsMaterial();
|
update.setId(details.get(0).getTransportsMaterialId());
|
update.setDetailExistState(true);
|
transportsMaterialService.updateById(update);
|
|
// 设置只库位
|
PalletTransportsMaterial material = this.transportsMaterialService.getById(update.getId());
|
if (StringUtils.isNotBlank(material.getToIfsLocationNo())) {
|
details.forEach(p -> {
|
p.setToIfsLocationNo(material.getToIfsLocationNo());
|
p.setToIfsLocationName(material.getToIfsLocationName());
|
});
|
}
|
return this.saveBatch(details);
|
}
|
|
@Override
|
public R update(PalletTransportsDetail detail) {
|
PalletTransportsDetail old = this.getById(detail.getId());
|
if (old.getState().equals(PalletTransportsDetailStateStringValues.SUBMITTED)) {
|
return R.failed("已执行数据无法更新");
|
}
|
|
if (detail.getTransferQuantity() != null && detail.getTransferQuantity().compareTo(old.getTransferQuantity()) != 0) {
|
if (detail.getTransferQuantity().compareTo(old.getTransferQuantity()) > 0) {
|
transportsMaterialService.calculateQuantity(old.getTransportsMaterialId(), detail.getTransferQuantity().subtract(old.getTransferQuantity()), true);
|
} else {
|
transportsMaterialService.calculateQuantity(old.getTransportsMaterialId(), old.getTransferQuantity().subtract(detail.getTransferQuantity()), false);
|
}
|
}
|
this.updateById(detail);
|
return R.ok();
|
}
|
|
@Override
|
public R remove(Long id) {
|
PalletTransportsDetail detail = this.getById(id);
|
Long transportsId = detail.getTransportsId();
|
if (detail.getState().equals(PalletTransportsDetailStateStringValues.SUBMITTED)) {
|
return R.failed("已执行无法删除");
|
}
|
// 重新计算数量
|
transportsMaterialService.calculateQuantity(detail.getTransportsMaterialId(), detail.getTransferQuantity(), false);
|
// 最后一条记录改回状态
|
int count = this.count(Wrappers.<PalletTransportsDetail>lambdaQuery().eq(PalletTransportsDetail::getTransportsMaterialId, detail.getTransportsMaterialId()));
|
if (count == 1) {
|
PalletTransportsMaterial update = new PalletTransportsMaterial();
|
update.setId(detail.getTransportsMaterialId());
|
update.setDetailExistState(false);
|
this.transportsMaterialService.updateById(update);
|
}
|
this.removeById(id);
|
changeTransportsState(transportsId);
|
return R.ok();
|
}
|
|
@Override
|
public R savePalletTransportsDetail(PalletTransportsDetail palletTransportsDetail) {
|
if(StringUtils.isBlank(Long.toString(palletTransportsDetail.getTransportsId()))){
|
return R.failed("货盘运输任务明细未绑定货盘运输物料需求计划行");//对PDA端的操作进行保险验证
|
}
|
transportsMaterialService.checkTransportsState(palletTransportsDetail.getTransportsId());
|
palletTransportsDetail.setState(PalletTransportsDetailStateStringValues.INITIAL);
|
return R.ok(save(palletTransportsDetail));
|
}
|
|
|
@Override
|
public void changeTransportsState(Long transportsId){
|
List<PalletTransportsDetail> palletTransportsDetailList = baseMapper.selectList(Wrappers.<PalletTransportsDetail>lambdaQuery()
|
.eq(PalletTransportsDetail::getTransportsId, transportsId));
|
boolean present = palletTransportsDetailList.stream()
|
.allMatch(a->PalletTransportsDetailStateStringValues.SUBMITTED.equals(a.getState()));
|
List<PalletTransportsMaterial> palletTransportsMaterialList = palletTransportsMaterialMapper.selectList(Wrappers.<PalletTransportsMaterial>lambdaQuery()
|
.eq(PalletTransportsMaterial::getTransportsId, transportsId));
|
Set<Long> materialIdList = palletTransportsMaterialList.stream().map(PalletTransportsMaterial::getId).collect(Collectors.toSet());
|
Set<Long> detailMaterialIdList = palletTransportsDetailList.stream().map(PalletTransportsDetail::getTransportsMaterialId).collect(Collectors.toSet());
|
Boolean flag = false;
|
if(materialIdList.size()==detailMaterialIdList.size()){
|
if(materialIdList.containsAll(detailMaterialIdList)){
|
flag = true;
|
}
|
}
|
if(present && flag){
|
PalletTransports palletTransports = new PalletTransports();
|
palletTransports.setId(transportsId);
|
palletTransports.setState(PalletTransportsState.FINISHED.getCode());
|
palletTransportsMapper.updateById(palletTransports);
|
}
|
}
|
}
|