SorterManagerImpl.java
package com.mycim.server.sorter.manager.imp;
import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.logging.Logger;
import com.mycim.framework.logging.LoggerFactory;
import com.mycim.framework.oid.IDGenerators;
import com.mycim.framework.oid.type.IDNames;
import com.mycim.framework.oid.type.SequenceNames;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.server.asm.manager.MaterialManager;
import com.mycim.server.automonitor.manager.LotAutoMonitorInqManager;
import com.mycim.server.automonitor.manager.LotAutoMonitorReqManager;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.carrier.manager.CarrierManager;
import com.mycim.server.carrier.manager.PcdManager;
import com.mycim.server.sorter.dao.SorterDAO;
import com.mycim.server.sorter.dao.SorterQueryDAO;
import com.mycim.server.sorter.manager.SorterManager;
import com.mycim.server.sorter.manager.SorterQueryManager;
import com.mycim.server.spec.manager.ProcessSpecItemManager;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.server.wip.manager.*;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.automonitor.entity.LotAutoMonitorInfo;
import com.mycim.valueobject.automonitor.entity.MonitorCarrierMapping;
import com.mycim.valueobject.automonitor.util.AutoMonitorUtils;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.*;
import com.mycim.valueobject.ems.Carrier;
import com.mycim.valueobject.inv.MaterialDO;
import com.mycim.valueobject.runcard.dto.RunCardMergeInfoDTO;
import com.mycim.valueobject.runcard.dto.RunCardSplitInfoDTO;
import com.mycim.valueobject.runcard.util.RunCardConstants;
import com.mycim.valueobject.runcard.util.RunCardUtils;
import com.mycim.valueobject.sorter.*;
import com.mycim.valueobject.wip.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
/**
* @author yibing.liu
* @version 1.0
* @date 2021/06/29
*/
@Service
@Transactional
public class SorterManagerImpl implements SorterManager {
@Autowired
SorterDAO sorterDAO;
@Autowired
SorterQueryDAO sorterQueryDAO;
@Autowired
NamedObjectManager namedObjectManager;
@Autowired
TransactionLogManager transactionLogManager;
@Autowired
LotManager lotManager;
@Autowired
LotQueryManager lotQueryManager;
@Autowired
LotInqManager lotInqManager;
@Autowired
LotRunCardManager lotRunCardManager;
@Autowired
RunCardQueryManager runCardQueryManager;
@Autowired
UnitQueryManager unitQueryManager;
@Autowired
CarrierManager carrierManager;
@Autowired
SorterManager sorterManager;
@Autowired
SorterQueryManager sorterQueryManager;
@Autowired
LotAutoMonitorInqManager lotAutoMonitorInqManager;
@Autowired
LotAutoMonitorReqManager lotAutoMonitorReqManager;
@Autowired
ProcessSpecItemManager processSpecItemManager;
@Autowired
UnitManager unitManager;
@Autowired
WipQueryManager wipQueryManager;
@Autowired
ReferenceFileManager referenceFileManager;
@Autowired
PcdManager pcdManager;
@Autowired
LotTransHistoryReqManager lotTransHistoryReqManager;
@Autowired
MaterialManager materialManager;
private Logger logger = LoggerFactory.getLogger(SorterManagerImpl.class);
@Override
public void addSortJob(SortJobBean sortJobBean, TransactionLog tl) {
//1 先分配主任务的 mainJobRrn
long mainJobRrn = Long.parseLong(
IDGenerators.get(IDNames.SEQUENCE).generateId(SequenceNames.MODULE_SEQ_OBJECT_RRN));
for (SorterBean sorterBean : sortJobBean.getSorterBeans()) {
Assert.isFalse(CollectionUtils.isEmpty(sorterBean.getSorterDetailBeanList()),
Errors.create().key(MessageIdList.UNIT_DATA_ERROR).build());
sorterBean.setMainJobRrn(mainJobRrn);
long subJobRrn = Long.parseLong(
IDGenerators.get(IDNames.SEQUENCE).generateId(SequenceNames.MODULE_SEQ_OBJECT_RRN));
sorterBean.setSubJobRrn(subJobRrn);
sorterBean.setCreateTime(tl.getTransStartTimestamp());
//2 在分配子任务的 subJobRrn ,一个mainJobRrn对应一个subJobRrn,也可能对应对个subJobRrn 比如:多PORT和multiLot
sorterDAO.addSorter(sorterBean, tl.getTransRrn());
//3 添加创建时的sorter carrier mapping 记录。
insertSorterCarrierMap(sorterBean);
}
}
private void insertSorterCarrierMap(SorterBean sorterBean) {
List<SorterCarrierMap> carrierMapList=new ArrayList<>();
carrierMapList.addAll(buildSourceSorterCarrierMap(sorterBean));
carrierMapList.addAll(buildTargetSorterCarrierMap(sorterBean));
sorterDAO.insertSorterCarrierMapList(carrierMapList);
}
private List<SorterCarrierMap> buildSourceSorterCarrierMap(SorterBean sorterBean) {
Long carrierMapRrn = sorterBean.getSourceCarrierMapRrn();
Long carrierRrn = sorterBean.getSourceCarrierRrn();
String carrierId = sorterBean.getSourceCarrierId();
return buildSourceSorterCarrierMap(sorterBean, carrierMapRrn, carrierRrn, carrierId);
}
private List<SorterCarrierMap> buildTargetSorterCarrierMap(SorterBean sorterBean) {
Long carrierMapRrn = sorterBean.getTargetCarrierMapRrn();
Long carrierRrn = sorterBean.getTargetCarrierRrn();
String carrierId = sorterBean.getTargetCarrierId();
return buildSourceSorterCarrierMap(sorterBean, carrierMapRrn, carrierRrn, carrierId);
}
private List<SorterCarrierMap> buildSourceSorterCarrierMap(SorterBean sorterBean, Long carrierMapRrn,
Long carrierRrn, String carrierId) {
List<SorterCarrierMap> sorterCarrierMapList = new ArrayList<>();
List<Map<String, Object>> list = unitQueryManager.getUnitListByCarrierMapRrn(carrierMapRrn);
for (Map<String, Object> map : list) {
SorterCarrierMap carrierMap = new SorterCarrierMap();
carrierMap.setMainJobRrn(sorterBean.getMainJobRrn());
carrierMap.setSubJobRrn(sorterBean.getSubJobRrn());
carrierMap.setCarrierMapRrn(carrierMapRrn);
carrierMap.setCarrierRrn(carrierRrn);
carrierMap.setCarrierId(carrierId);
carrierMap.setLotRrn(MapUtils.getLong(map, "lotRrn"));
carrierMap.setLotId(MapUtils.getString(map, "lotid"));
carrierMap.setUnitRrn(MapUtils.getLong(map, "unitRrn"));
carrierMap.setUnitId(MapUtils.getString(map, "unitId"));
carrierMap.setPosition(MapUtils.getInteger(map, "position"));
sorterCarrierMapList.add(carrierMap);
}
return sorterCarrierMapList;
}
@Override
public void addSortJobList(List<SortJobBean> sortJobBeanList, TransactionLog tl) {
for (SortJobBean sortJobBean : sortJobBeanList) {
addSortJob(sortJobBean, tl);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateSorter(SortJobBean sortJob) {
sorterDAO.updateSorter(sortJob);
}
@Override
public void deleteSorter(SorterBean sorterBean, TransactionLog tl) {
sorterBean.setUpdateTime(tl.getTransStartTimestamp());
sorterBean.setUpdateUser(LocalContext.getUserId());
//先检查一下此Sort任务的状态是否已经被修改
List<SorterBean> sorterBeans = checkSorterTaskStatus(sorterBean);
if (SorterEnum.Constant.CREATE_MONITOR.equalsIgnoreCase(SorterEnum.getListFirst(sorterBeans).getJobType())) {
int finishTask = 0;
for (SorterBean s : sorterBeans) {
if (SorterEnum.Constant.FINISH.equalsIgnoreCase(s.getStatus())) {
finishTask++;
}
}
if (finishTask > 0) {
//CreateMonitor 的 SortJob 已经执行了一部分,因此不能取消剩余的 SortTask。
throw new SystemIllegalArgumentException(
Errors.create().key(MessageIdList.SORT_JOB_CAN_NOT_CANCEL).build());
}
}
sorterDAO.deleteSorterByJobRrn(sorterBean, tl.getTransRrn());
}
@Override
public String endSortJob(SortJobBean sortJobBean) {
TransactionLog transactionLog = transactionLogManager.startTransactionLog(sortJobBean.getTransPerformedby(),
sortJobBean.getTransId());
//1 处理 JobType 对应的业务操作
SortJobBean sortJob = sorterQueryDAO.getSortJob(sortJobBean);//通过晶舟的RRN去查
Assert.isFalse(CollectionUtils.isEmpty(sortJob.getSorterBeans()),
Errors.create().key(MessageIdList.NO_SORT_JOB).build());
String msg = "";
try {
sortJob.setEquipmentId(sortJobBean.getEquipmentId());
msg = continueDealJob(sortJob);
//2 修改 SORT_JOB 、 删除 SORT_JOB_DETAIL
sortJob.setLastUpdateTimestamp(transactionLog.getTransStartTimestamp());
sortJob.setLastUpdateUserId(LocalContext.getUserId());
sorterDAO.endSorter(sortJob, transactionLog.getTransRrn());
transactionLogManager.markTransactionLog(transactionLog);
} catch (Exception e) {
sortJob.setStatus(SorterEnum.Status.DISPATCH.getStatus());
sorterManager.updateSorter(sortJob);
logger.error(e);
throw new SystemIllegalArgumentException(Errors.create().content(e.getMessage()).build());
}
return msg;
}
@Override
public void manualSortJob(SorterBean sorterBean) {
//先检查一下此Sort任务的状态是否已经被修改
checkSorterTaskStatus(sorterBean);
sorterBean.setTransPerformedby(LocalContext.getUserId());
SortJobBean sjb = new SortJobBean();
//multiLot时,需要SubJobRRN
sjb.setMainJobRrn(sorterBean.getMainJobRrn());
sjb.setTransId(SorterEnum.Constant.MANUAL_END_SORTER);
endSortJob(sjb);
}
@Override
public void manualAutoMonitorSorterJob(SorterBean sorterBean) {
//先检查一下此Sort任务的状态是否已经被修改
checkSorterTaskStatus(sorterBean);
sorterBean.setTransPerformedby(LocalContext.getUserId());
SortJobBean sjb = new SortJobBean();
//multiLot时,需要SubJobRRN
sjb.setMainJobRrn(sorterBean.getMainJobRrn());
sjb.setTransId(SorterEnum.Constant.MANUAL_AUTO_MONITOR_SORTER);
endSortJob(sjb);
}
@Override
public void synAutoMonitorSortJob(Long sourceCarrierRrn, Long monitorCarrierRrn) {
//1. 检查预设关系
List<MonitorCarrierMapping> carrierMappings = lotAutoMonitorInqManager
.getMonitorCarrierMappings(monitorCarrierRrn);
// 预设关系中的 lot rrn
List<Long> lotRrnList = carrierMappings.stream().map(MonitorCarrierMapping::getLotRrn)
.collect(Collectors.toList()).stream().distinct()
.collect(Collectors.toList());
//2. 检查预设批次状态
List<Long> createSorterLotRrn = new ArrayList<>();
Boolean canCreateSorter = Boolean.TRUE;
for (Long lotRrn : lotRrnList) {
LotAutoMonitorInfo autoInfo = lotAutoMonitorInqManager.getLotAutoMonitorInfo(lotRrn);
// 确认还未进入mcst
if (autoInfo.getCarrierRrn().longValue() == sourceCarrierRrn) {
if (lotAutoMonitorInqManager.checkAutoMonitorLotCanCreateSortJob(autoInfo)) {
createSorterLotRrn.add(lotRrn);
} else {
canCreateSorter = Boolean.FALSE;
break;
}
}
}
if (canCreateSorter && CollectionUtils.isEmpty(createSorterLotRrn)) {
canCreateSorter = Boolean.FALSE;
}
//3. 删除已有sorter
TransactionLog transactionLog = transactionLogManager
.startTransactionLog(LocalContext.getUserId(), SorterEnum.Constant.SYN_MONITOR_SORTER);
List<SorterBean> sorterList = sorterQueryManager.getSoterListByCarrier(sourceCarrierRrn, monitorCarrierRrn);
if (CollectionUtils.isNotEmpty(sorterList)) {
for (SorterBean sorterBean : sorterList) {
sorterDAO.deleteSorterByJobRrn(sorterBean, transactionLog.getTransRrn());
}
}
//4. 创建sorter
if(canCreateSorter) {
// 检查状态
Assert.state(CollectionUtils.isEmpty(unitQueryManager.getUnitListByCarrier(monitorCarrierRrn)),
Errors.create().key(MessageIdList.TARGET_BE_USED).build());
List<SorterDetailBean> detailList = new ArrayList<>();
for (MonitorCarrierMapping carrierMapping : carrierMappings) {
if(createSorterLotRrn.contains(carrierMapping.getLotRrn())) {
SorterDetailBean sorterDetailBean = new SorterDetailBean();
BeanUtils.copyProperties(carrierMapping, sorterDetailBean);
sorterDetailBean.setSourcePosition(carrierMapping.getSourcePosition());
sorterDetailBean.setTargetPosition(carrierMapping.getPosition());
detailList.add(sorterDetailBean);
}
}
if (CollectionUtils.isEmpty(detailList)) {
transactionLogManager.markTransactionLog(transactionLog);
return;
}
SorterBean sorterBean = buildSorterBean(sourceCarrierRrn, monitorCarrierRrn, detailList);
sorterBean.setJobType(SorterEnum.Constant.AUTO_MONITOR);
sorterBean.setCreateTime(transactionLog.getTransStartTimestamp());
sorterBean.setCreateUser(LocalContext.getUserId());
SortJobBean sortJobBean = new SortJobBean();
sortJobBean.setSorterBeans(sorterBean);
sortJobBean.setTransPerformedby(LocalContext.getUserId());
addSortJob(sortJobBean, transactionLog);
}
transactionLogManager.markTransactionLog(transactionLog);
}
@Override
public void addAutoMonitorMergeSortJob(Long targetCarrierRrn, Long monitorCarrierRrn) {
List<Lot> monitorLotList = lotInqManager.getLotListByCarrierRrn(monitorCarrierRrn);
addAutoMonitorMergeSortJob(monitorLotList, targetCarrierRrn, monitorCarrierRrn);
}
@Override
public void addAutoMonitorMergeSortJob(List<Lot> lotList, Long targetCarrierRrn, Long monitorCarrierRrn) {
String userId = LocalContext.getUserId();
List<MonitorCarrierMapping> carrierMappings = lotAutoMonitorInqManager
.getMonitorCarrierMappings(monitorCarrierRrn);
List<SorterDetailBean> detailList = new ArrayList<>();
for (Lot lot : lotList) {
Assert.state(!LotStatus.isProcessingStatus(lot.getLotStatus()),
Errors.create().key(MessageIdList.EQUIPMENT_CHECK_STATUS).args(lot.getLotId()).build());
for (MonitorCarrierMapping carrierMapping : carrierMappings) {
if (lot.getLotRrn() == carrierMapping.getLotRrn().longValue()) {
SorterDetailBean sorterDetailBean = new SorterDetailBean();
BeanUtils.copyProperties(carrierMapping, sorterDetailBean);
sorterDetailBean.setSourcePosition(carrierMapping.getPosition());
sorterDetailBean.setTargetPosition(carrierMapping.getSourcePosition());
detailList.add(sorterDetailBean);
}
}
}
TransactionLog tl = transactionLogManager.startTransactionLog(userId, SorterEnum.Constant.CREATE_SORTER);
SorterBean sorterBean = buildSorterBean(monitorCarrierRrn, targetCarrierRrn, detailList);
sorterBean.setJobType(SorterEnum.Constant.AUTO_MONITOR_MERGE);
sorterBean.setCreateTime(tl.getTransStartTimestamp());
sorterBean.setCreateUser(LocalContext.getUserId());
SortJobBean sortJobBean = new SortJobBean();
sortJobBean.setSorterBeans(sorterBean);
sortJobBean.setTransPerformedby(userId);
sorterManager.addSortJob(sortJobBean, tl);
transactionLogManager.markTransactionLog(tl);
}
@Override
public void autoCancelAutoMonitorSortJob(Long sourceCarrierRrn) {
List<SorterBean> sorterList = sorterQueryManager.getSoterListByCarrier(sourceCarrierRrn);
if (CollectionUtils.isNotEmpty(sorterList)) {
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
SorterEnum.Constant.CANCEL_SORTER);
for (SorterBean sorterBean : sorterList) {
sorterDAO.deleteSorterByJobRrn(sorterBean, transactionLog.getTransRrn());
}
transactionLogManager.markTransactionLog(transactionLog);
}
}
@Override
public List<SorterBean> checkSorterTaskStatus(SorterBean sorterBean) {
List<SorterBean> sorterBeans = sorterQueryDAO.getJobStatusList(sorterBean);
boolean canDo = false;
for (SorterBean s : sorterBeans) {
if (StringUtils.equalsIgnoreCase(s.getStatus(), SorterEnum.Status.CREATE.getStatus()) ||
StringUtils.equalsIgnoreCase(s.getStatus(), SorterEnum.Status.DISPATCH.getStatus())) {
canDo = true;
}
}
if (!canDo) { //没有可执行的子任务
throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.REFRESH_AGAIN).build());
}
return sorterBeans;
}
@Override
public void assignTargetCarriers(long sourceCarrierRrn, SorterBean assignSorterBean,
TransactionLog transactionLog) {
SorterBean sbStr = new SorterBean();
sbStr.setMainJobRrn(assignSorterBean.getMainJobRrn());
sbStr.setSubJobRrn(assignSorterBean.getSubJobRrn());
sbStr.setTargetCarrierId(assignSorterBean.getTargetCarrierId());
sbStr.setTargetCarrierRrn(assignSorterBean.getTargetCarrierRrn());
sorterDAO.updateSorterBean(sbStr);
transactionLog.setComments(Long.toString(assignSorterBean.getSubJobRrn()));//记录修改的sub_job_rrn,以便以后关联排查记录。
}
@Override
public void createSorterJobByInLine(SorterModel sorterModel, Lot lot, String targetCarrierId) {
SortJobBean queryBean = sorterQueryManager.querySortJobByCarrierRrn(lot.getCarrierRrn());
if (queryBean.getMainJobRrn() == 0) {
String transPerformedBy = SystemConstants.SYSTEM_USER;
TransactionLog tl = transactionLogManager.startTransactionLog(transPerformedBy,
SorterEnum.Constant.CREATE_SORTER);
SortJobBean sortJobBean = new SortJobBean();
if (SorterEnum.Constant.EXCHANGE.equalsIgnoreCase(sorterModel.getJobType())) {
sortJobBean = buildSorterJobBeanForExchange(sorterModel, lot, targetCarrierId);
}else {
// 根据Model 构建数据
sortJobBean = buildSorterJobBeanByModel(sorterModel, lot);
}
// 添加数据
addSortJob(sortJobBean, tl);
transactionLogManager.markTransactionLog(tl);
} else if (queryBean.getMainJobRrn() > 0) {
// check 是否已经存在Offline 类型的Job
queryBean.getSorterBeans().forEach(job -> {
Assert.state(StringUtils.equalsIgnoreCase(job.getSorterType(), SorterEnum.Type.OFFLINE.getName()),
Errors.create().key(MessageIdList.SORTER_CST_HAVE_JOB)
.content("Current CST has a Offline Sorter Job, Complete the Job first").build());
});
}
}
private SortJobBean buildSorterJobBeanByModel(SorterModel sorterModel, Lot lot) {
// 获取Lot的Carrier
Long sourceCarrierRrn = lot.getCarrierRrn();
// 构建基础数据
SorterBean sorterBean = buildSorterBean(sourceCarrierRrn, sourceCarrierRrn, new ArrayList<>());
sorterBean.setSorterType(SorterEnum.Type.INLINE.getName());
sorterBean.setJobType(sorterModel.getJobType());
sorterBean.setCreateUser(SystemConstants.SYSTEM_USER);
//根据不同类型构建特殊数据 预留扩展
switch (sorterModel.getJobType()) {
case SorterEnum.Constant.FLIP_SIDE:
buildFlipSideSortInfo(sorterBean, lot);
break;
case SorterEnum.Constant.READ_T7CODE:
buildReadT7CodeSortInfo(sorterBean, lot);
break;
default:
Assert.isTrue(true, Errors.create().content("Job Type Error").build());
}
SortJobBean sortJobBean = new SortJobBean();
sortJobBean.setSorterBeans(sorterBean);
return sortJobBean;
}
private SortJobBean buildSorterJobBeanForExchange(SorterModel sorterModel, Lot lot, String targetCarrierId) {
Long sourceCarrierRrn = lot.getCarrierRrn();
Long targetCarrierRrn = null;
if (StringUtils.isNotBlank(targetCarrierId)) {
Carrier carrier = carrierManager.getCarrier(LocalContext.getFacilityRrn(), targetCarrierId);
if (carrier != null && carrier.getInstanceRrn() > 0) {
targetCarrierRrn = carrier.getInstanceRrn();
}
}
// 构建基础数据
SorterBean sorterBean = buildSorterBean(sourceCarrierRrn, targetCarrierRrn, new ArrayList<>());
sorterBean.setSorterType(SorterEnum.Type.INLINE.getName());
sorterBean.setJobType(sorterModel.getJobType());
sorterBean.setCreateUser(SystemConstants.SYSTEM_USER);
// 构建units
List<Map> sourceUnits = unitQueryManager.getUnitListByCarrier(lot.getCarrierRrn());
List<SorterDetailBean> sourceUnitList = sourceUnits.stream().map(unitMap -> {
String unitId = MapUtils.getString(unitMap, "unitId");
long unitRrn = MapUtils.getLong(unitMap, "unitRrn", 0L);
String lotId = MapUtils.getString(unitMap, "lotId");
long lotRrn = MapUtils.getLong(unitMap, "lotRrn", 0L);
int position = MapUtils.getIntValue(unitMap, "position", 0);
return new SorterDetailBean(lotRrn, lotId, unitRrn, unitId, position, position);
}).collect(Collectors.toList());
sorterBean.setSorterDetailBeanList(sourceUnitList);
sorterBean.setExchangeTotalQty(sourceUnits.size());
SortJobBean sortJobBean = new SortJobBean();
sortJobBean.setSorterBeans(sorterBean);
return sortJobBean;
}
private void buildFlipSideSortInfo(SorterBean sorterBean, Lot lot) {
String flipType = sorterQueryManager.getFlipTypeByLot(lot);
sorterBean.setJsonAttributeData3(StringUtils.replace(flipType, "-", "|"));
// 构建units
List<Map> sourceUnits = unitQueryManager.getUnitListByCarrier(lot.getCarrierRrn());
List<SorterDetailBean> sourceUnitList = sourceUnits.stream().map(unitMap -> {
String unitId = MapUtils.getString(unitMap, "unitId");
long unitRrn = MapUtils.getLong(unitMap, "unitRrn", 0L);
String lotId = MapUtils.getString(unitMap, "lotId");
long lotRrn = MapUtils.getLong(unitMap, "lotRrn", 0L);
int position = MapUtils.getIntValue(unitMap, "position", 0);
return new SorterDetailBean(lotRrn, lotId, unitRrn, unitId, position, position);
}).collect(Collectors.toList());
sorterBean.setSorterDetailBeanList(sourceUnitList);
sorterBean.setExchangeTotalQty(sourceUnits.size());
}
private SorterBean buildSorterBean(Long sourceCarrierRrn, Long targetCarrierRrn, List<SorterDetailBean> unitList) {
Carrier sourceCarrier = carrierManager.getCarrier(sourceCarrierRrn);
Carrier targetCarrier = null;
if (targetCarrierRrn != null && targetCarrierRrn > 0) {
targetCarrier = carrierManager.getCarrier(targetCarrierRrn);
}
SorterBean sorterBean = new SorterBean();
sorterBean.setSourceCarrierId(sourceCarrier.getInstanceId());
sorterBean.setSourceCarrierRrn(sourceCarrier.getInstanceRrn());
sorterBean.setSourceCarrierMapRrn(sourceCarrier.getCarrierMapRrn());
sorterBean.setTargetCarrierId(targetCarrier == null ? StringUtils.EMPTY : targetCarrier.getInstanceId());
sorterBean.setTargetCarrierRrn(targetCarrier == null ? NumberUtils.LONG_ZERO : targetCarrier.getInstanceRrn());
sorterBean.setTargetCarrierMapRrn(targetCarrier == null ? NumberUtils.LONG_ZERO : targetCarrier.getCarrierMapRrn());
sorterBean.setStatus(SorterEnum.Constant.CREATE);
sorterBean.setCreateUser(LocalContext.getUserId());
sorterBean.setExchangeTotalQty(unitList.size());
sorterBean.setSorterDetailBeanList(unitList);
sorterBean.setJsonAttributeData5(StringUtils.EMPTY + sourceCarrier.getCarrierMapRrn());
return sorterBean;
}
private String continueDealJob(SortJobBean sortJobBean) {
NamedObject eqpt = namedObjectManager.getNamedObject(sortJobBean.getEquipmentId(),
namedObjectManager.getNamedSpace(
LocalContext.getFacilityRrn(),
ObjectList.ENTITY_KEY), ObjectList.ENTITY_KEY);
sortJobBean.setEquipmentRrn(Objects.isNull(eqpt) ? -1L : eqpt.getInstanceRrn());
String message = SorterEnum.HardCode.SUCCESS;
switch (sortJobBean.getJobType().toUpperCase()) {
case SorterEnum.Constant.MERGE:
merge(sortJobBean);
break;
case SorterEnum.Constant.SPLIT:
splitLot(sortJobBean, SorterEnum.Constant.SPLIT);
break;
case SorterEnum.Constant.EXCHANGE:
exchangeCarrier(sortJobBean, SorterEnum.Constant.EXCHANGE);
break;
case SorterEnum.Constant.SPLIT_3PORT:
splitTo3Port(sortJobBean);
break;
case SorterEnum.Constant.SRC_SPLIT:
runCardSplit(sortJobBean);
break;
case SorterEnum.Constant.SRC_MERGE:
runCardMerge(sortJobBean);
break;
case SorterEnum.Constant.AUTO_MONITOR:
autoMonitorExchange(sortJobBean);
break;
case SorterEnum.Constant.AUTO_MONITOR_MERGE:
autoMonitorMergeCarrier(sortJobBean);
break;
case SorterEnum.Constant.FLIP_SIDE:
flipSideCarrier(sortJobBean);
break;
case SorterEnum.Constant.PILOT_SPLIT:
splitLot(sortJobBean, SorterEnum.Constant.PILOT_SPLIT);
break;
case SorterEnum.Constant.SPECIAL_EXCHANGE:
exchangeCarrier(sortJobBean, SorterEnum.Constant.SPECIAL_EXCHANGE);
break;
case SorterEnum.Constant.SRC_EXCHANGE:
srcExchangeCarrier(sortJobBean, SorterEnum.Constant.SRC_EXCHANGE);
break;
case SorterEnum.Constant.SRC_SPECIAL_EXCHANGE:
srcExchangeCarrier(sortJobBean, SorterEnum.Constant.SRC_SPECIAL_EXCHANGE);
break;
case SorterEnum.Constant.OFFLINE_CHECK_T7CODE:
recordSortLotTrans(sortJobBean, TransactionNames.OFFLINE_CHECK_T7CODE);
break;
case SorterEnum.Constant.OFFLINE_READ_MATERIALID:
recordSortLotTrans(sortJobBean, TransactionNames.OFFLINE_READ_MATERIALID);
break;
default:
return null;
}
return message;
}
//TODO
private void srcExchangeCarrier(SortJobBean sortJobBean, String srcExchangeType) {
long facilityRrn = LocalContext.getFacilityRrn();
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean sorterBean = SorterEnum.getListFirst(sorterBeans);
List<SorterDetailBean> sorterDetailBeans = sorterBean.getSorterDetailBeanList();
Lot lot = lotQueryManager.getLotByCarrierRrn(sorterBean.getSourceCarrierRrn());//SRC 的LOT
if (LotStatus.isRunCardHold(lot.getLotStatus())) {//MAINRC
lot = lotQueryManager.getLot(RunCardUtils.buildMainRcLotId(lot.getLotId()),
lot.getFacilityRrn());
}
// List<Unit> parentUnitList = unitQueryManager.getUnitList(lot.getLotRrn());
lot.setLotComments(
(SorterEnum.Constant.SRC_EXCHANGE.equalsIgnoreCase(srcExchangeType) ? "普通" : "特殊") + "交换晶舟,初始晶舟为: " +
sorterBean.getSourceCarrierId() + ", SortJob Finish. ");
lot.setTransPerformedby(sorterBean.getCreateUser());
lot.setTransId(srcExchangeType);
lot.setSorterFlag(true);
lot.setLocation(sortJobBean.getEquipmentId());
lot.setEqptRrn(sortJobBean.getEquipmentRrn());
Carrier toCarrier = carrierManager.getCarrier(sorterBean.getTargetCarrierRrn());
//carrier的一些校验
Assert.isFalse(!StringUtils.equalsIgnoreCase(toCarrier.getCarrierStatus(), PcdStatus.FREE_KEY) &&
!StringUtils.equalsIgnoreCase(toCarrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
Errors.create().key(MessageIdList.CARRIER_STATUS_INVALID).args(toCarrier.getInstanceId())
.build());
List<Map> carrierMappings = buildCarrierMapping(sorterDetailBeans);
carrierManager.exchangeCarrierSpecial4Src(lot, toCarrier.getInstanceRrn(), carrierMappings, toCarrier, facilityRrn,
sorterBean.getCreateUser());
}
private void recordSortLotTrans(SortJobBean sortJobBean, String transName) {
//无需做其他处理,只需记录trans
TransactionLog transactionLog = transactionLogManager
.startTransactionLog(LocalContext.getUserId(), transName);
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean firstSorterBean = SorterEnum.getListFirst(sorterBeans);
List<Lot> lotListByCarrierRrn = lotInqManager.getLotListByCarrierRrn(firstSorterBean.getSourceCarrierRrn());
if (CollectionUtils.size(lotListByCarrierRrn) > 1 || CollectionUtils.isEmpty(lotListByCarrierRrn)) {
return;
}
Lot lot = lotListByCarrierRrn.get(0);
if (Objects.isNull(lot)) {
return;
}
if (LotStatus.isRunCardHold(lot.getLotStatus())) {
lot = lotInqManager.getLot(RunCardUtils.buildMainRcLotId(lot.getLotId()));
}
String transComments = sortJobBean.getJobType() + ",SortJob Finish。";
lotTransHistoryReqManager.createLotTransHistory(transactionLog, lot, transComments);
transactionLogManager.markTransactionLog(transactionLog);
}
private void autoMonitorExchange(SortJobBean sortJobBean) {
SorterBean sb = SorterEnum.getListFirst(sortJobBean.getSorterBeans());
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.AUTO_MONITOR_EXCHANGE);
Long sourceCarrierRrn = sortJobBean.getSourceCarrierRrn();
Long targetCarrierRrn = sortJobBean.getTargetCarrierRrn();
List<Long> exchangeLotRrnList = new ArrayList<>();
for(SorterDetailBean sorterDetailBean: sb.getSorterDetailBeanList()) {
if(!exchangeLotRrnList.contains(sorterDetailBean.getLotRrn())) {
exchangeLotRrnList.add(sorterDetailBean.getLotRrn());
}
}
for (Long lotRrn : exchangeLotRrnList) {
LotAutoMonitorInfo monitorInfo = lotAutoMonitorInqManager.getLotActiveAutoMonitorInfo(lotRrn);
if (monitorInfo != null && monitorInfo.getMonitorCarrierRrn() != null) {
monitorInfo.setBySort(true);
monitorInfo.setSorterEqptId(sortJobBean.getEquipmentId());
monitorInfo.setSorterEqptRrn(sortJobBean.getEquipmentRrn());
lotAutoMonitorReqManager.exchangeAutoMonitorLotCarrier(transactionLog, monitorInfo, targetCarrierRrn);
}
}
buildCarrierMappingInfo(transactionLog, sourceCarrierRrn);
buildCarrierMappingInfo(transactionLog, targetCarrierRrn);
SorterBean temp = new SorterBean(sb.getMainJobRrn());
temp.setSubJobRrn(sb.getSubJobRrn());
sorterDAO.updateSorterBean(temp);//回填子批ID
transactionLogManager.markTransactionLog(transactionLog);
}
private void autoMonitorMergeCarrier(SortJobBean sortJobBean) {
SorterBean sb = SorterEnum.getListFirst(sortJobBean.getSorterBeans());
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.AUTO_MONITOR_MERGE);
Long sourceCarrierRrn = sortJobBean.getSourceCarrierRrn();
Long targetCarrierRrn = sortJobBean.getTargetCarrierRrn();
List<Long> exchangeLotRrnList = new ArrayList<>();
for(SorterDetailBean sorterDetailBean: sb.getSorterDetailBeanList()) {
if(!exchangeLotRrnList.contains(sorterDetailBean.getLotRrn())) {
exchangeLotRrnList.add(sorterDetailBean.getLotRrn());
}
}
for(Long exchangeLotRrn:exchangeLotRrnList) {
LotAutoMonitorInfo monitorInfo = lotAutoMonitorInqManager.getLotActiveAutoMonitorInfo(exchangeLotRrn);
if (monitorInfo != null && monitorInfo.getMonitorCarrierRrn() != null &&
monitorInfo.getCarrierRrn().longValue() == monitorInfo.getMonitorCarrierRrn().longValue()) {
monitorInfo.setBySort(true);
monitorInfo.setSorterEqptId(sortJobBean.getEquipmentId());
monitorInfo.setSorterEqptRrn(sortJobBean.getEquipmentRrn());
lotAutoMonitorReqManager.exchangeAutoMonitorLotCarrier(transactionLog, monitorInfo, targetCarrierRrn);
if(AutoMonitorUtils.checkJobStatusIsFixed(monitorInfo.getJobStatus())) {
lotAutoMonitorReqManager.deleteMonitorCarrierMappingByLot(monitorInfo.getLotRrn());
}
}
}
buildCarrierMappingInfo(transactionLog, sourceCarrierRrn);
buildCarrierMappingInfo(transactionLog, targetCarrierRrn);
SorterBean temp = new SorterBean(sb.getMainJobRrn());
temp.setSubJobRrn(sb.getSubJobRrn());
sorterDAO.updateSorterBean(temp);//回填子批ID
transactionLogManager.markTransactionLog(transactionLog);
}
private void runCardSplit(SortJobBean sortJobBean) {
//回填子批的LotID
SorterBean sb = SorterEnum.getListFirst(sortJobBean.getSorterBeans());
long lotRrn = SorterEnum.getListFirst(sb.getSorterDetailBeanList()).getLotRrn();
//先把子批split出去
Lot childLot = splitRcLotForSort(sortJobBean, sb, "");
LotRunCardStore runCardStore = runCardQueryManager.getSplitRunCardLotStore(lotRrn);
List<LotRunCardSplit> splitSet = runCardQueryManager.getLotRunCardSplit(runCardStore.getRuncardRrn());
List<Map<String, Object>> splitedLots = runCardQueryManager.getSplitedRunCardLots(runCardStore.getRuncardRrn());
List<LotRunCardSplit> splitsList = new ArrayList<>();
for (LotRunCardSplit lotRunCardSplit : splitSet) {
boolean notSplit = true;
for (Map<String, Object> splitedLot : splitedLots) {
int splitSeq = MapUtils.getIntValue(splitedLot, "splitSeq");
if (splitSeq != 0 && splitSeq == lotRunCardSplit.getSplitSeq()) {
notSplit = false;
break;
}
}
if (notSplit) {
splitsList.add(lotRunCardSplit);
}
}
if (splitsList.size() == 1) {
sb.setJsonAttributeData2(splitsList.get(0).getSplitSeq().toString());
splitRcLotForSort(sortJobBean, sb, "1");
}
SorterBean temp = new SorterBean(sb.getMainJobRrn());
temp.setSubJobRrn(sb.getSubJobRrn());
temp.setJsonAttributeData4(childLot.getLotId());
sorterDAO.updateSorterBean(temp);//回填子批ID
}
private void runCardMerge(SortJobBean sortJobBean) {
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean firstSorterBean = SorterEnum.getListFirst(sorterBeans);
String userId = firstSorterBean.getCreateUser();
Long sourceCarrierRrn = sortJobBean.getSourceCarrierRrn();
Long targetCarrierRrn = sortJobBean.getTargetCarrierRrn();
Lot parentLot = lotQueryManager.getLotByCarrierRrn(targetCarrierRrn);//需要放母批
Lot childLot = lotQueryManager.getLotByCarrierRrn(sourceCarrierRrn); //必须放子批
if (LotStatus.isRunCardHold(parentLot.getLotStatus())) {
parentLot = lotQueryManager.getLot(RunCardUtils.buildMainRcLotId(parentLot.getLotId()),
LocalContext.getFacilityRrn());
}
List<Unit> childUnitList = unitQueryManager.getUnitList(childLot.getLotRrn());
List<Unit> parentUnitList = unitQueryManager.getUnitList(parentLot.getLotRrn());
List<Unit> newUnitList = new ArrayList<>();
newUnitList.addAll(parentUnitList);
newUnitList.addAll(childUnitList);
RunCardMergeInfoDTO mergeInfoDTO = new RunCardMergeInfoDTO();
mergeInfoDTO.setParentLot(parentLot);
mergeInfoDTO.setChildLot(childLot);
mergeInfoDTO.setParentUnitList(parentUnitList);
mergeInfoDTO.setChildUnitList(childUnitList);
mergeInfoDTO.setNewUnitList(newUnitList);
mergeInfoDTO.setBySort(true);
mergeInfoDTO.setSorterEqptRrn(sortJobBean.getEquipmentRrn() > 0 ? sortJobBean.getEquipmentRrn() : null);
mergeInfoDTO.setSorterEqptId(sortJobBean.getEquipmentId());
lotRunCardManager.mergeSplitRunCardLot(mergeInfoDTO, userId);
childLot = lotQueryManager.getLot(childLot.getLotRrn());
lotManager.calcStepSpeedTime(childLot.getLotStatus(), childLot.getBeforeStatus(), childLot.getLotRrn(), false);
parentLot = lotQueryManager.getLot(parentLot.getLotRrn());
lotManager.calcStepSpeedTime(parentLot.getLotStatus(), parentLot.getBeforeStatus(), parentLot.getLotRrn(),
false);
}
private Lot splitRcLotForSort(SortJobBean sortJobBean, SorterBean sb, String isMainLot) {
Lot lot = lotQueryManager.getLotByCarrierRrn(sb.getSourceCarrierRrn()); //mainLotId
String mainLotId = lot.getLotId();
Long facilityRrn = lot.getFacilityRrn();
if (StringUtils.equals(lot.getLotStatus(), LotStatus.RUNCARD_HOLD)) {
lot = lotQueryManager.getLot(lot.getLotId() + RunCardConstants.MAINLOT_ID_IN_MES,
facilityRrn);//RunCard LotId
}
LotRunCardStore runCardStore = runCardQueryManager.getSplitRunCardLotStore(lot.getLotRrn());
//组装RunCardSplitLot必要的参数
int splitSeq = NumberUtils.toInt(sb.getJsonAttributeData2(), -1);
String carrierId = sb.getTargetCarrierId();
String lotId = lot.getLotId();
String runcardId = runCardStore.getRuncardId();
long runCardRrn = namedObjectManager.getNamedObjectRrn(runcardId, facilityRrn, ObjectList.ECN_KEY);
long carrierRrn = sb.getTargetCarrierRrn();
List<LotRunCardSplit> splitSet = runCardQueryManager.getLotRunCardSplit(runCardRrn);
LotRunCardSplit splitInfo = splitSet.stream().filter(set -> set.getSplitSeq() == splitSeq).findFirst().get();
//校验Runcard的子批是否已经被分出去了
List<Map<String, Object>> lotMaps = runCardQueryManager.getRunCardLotsByRuncardRrn(runCardRrn);
for (Map<String, Object> lotMap : lotMaps) {
Assert.isFalse(MapUtils.getLongValue(lotMap, "splitSeq") == splitSeq,
Errors.create().key(MessageIdList.LOT_HAS_SPLIT).build());
}
int childLotCount = runCardQueryManager.getRCChildLotCount(mainLotId, StringUtils.substring(runcardId, 0, 1));
String childLotIdMax = SorterEnum.HardCode.S +
(childLotCount + 1 < 10 ? SorterEnum.HardCode.ZERO_STR + (childLotCount + 1) : childLotCount + 1);
List<RunCardSplitInfoDTO> lotList = new ArrayList<>();
if (splitInfo != null) {
lotList = lotRunCardManager.buildSplitInfo(splitInfo, lotList, lot, splitSeq, runCardRrn, carrierRrn,
childLotCount, lotId, mainLotId, isMainLot, runcardId,
facilityRrn, carrierId);
SorterEnum.getListFirst(lotList).setBySort(true);
SorterEnum.getListFirst(lotList).setSorterEqptId(sortJobBean.getEquipmentId());
SorterEnum.getListFirst(lotList).setSorterEqptRrn(sortJobBean.getEquipmentRrn());
}
lotRunCardManager.splitRunCardLots(lotList, LocalContext.getUserId());
if (CollectionUtils.isNotEmpty(lotList)) {
for (RunCardSplitInfoDTO dto : lotList) {
if (dto.getChildLot() != null) {
Long childLotRrn = dto.getChildLot().getLotRrn();
if (childLotRrn > 0) {
Lot currentLot = lotQueryManager.getLot(childLotRrn);
lotManager.calcStepSpeedTime(currentLot.getLotStatus(), currentLot.getBeforeStatus(),
currentLot.getLotRrn(), false);
}
}
}
}
return lotQueryManager.getLot(mainLotId + "." + childLotIdMax, facilityRrn);
}
private void splitTo3Port(SortJobBean sortJobBean) {
List<SorterBean> jobList = sortJobBean.getSorterBeans();
Assert.isFalse(CollectionUtils.isEmpty(jobList) || jobList.size() != 2,
Errors.create().key(MessageIdList.UNIT_DATA_ERROR).build());
SorterBean t1 = SorterEnum.getListFirst(jobList);
SorterBean t2 = jobList.get(1);
// 1.将details中的晶圆分批到P1晶舟
// childLot = splitLotForSort(sortJob, details, user, transactionLog);
SortJobBean job1 = new SortJobBean();
job1.setSorterBeans(t1);
splitLot(job1, null); //子批通过Split动作拆分出去
// 2.将其余晶圆交换到P2晶舟
SortJobBean job2 = new SortJobBean();
job2.setSorterBeans(t2);
exchangeCarrier(job2, SorterEnum.Constant.EXCHANGE); //剩余晶圆通过Exchange交换出去
}
private void exchangeCarrier(SortJobBean sortJobBean, String type) {
long facilityRrn = LocalContext.getFacilityRrn();
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean sorterBean = SorterEnum.getListFirst(sorterBeans);
List<SorterDetailBean> sorterDetailBeans = sorterBean.getSorterDetailBeanList();
String lotId = SorterEnum.getListFirst(sorterDetailBeans).getLotId();
Lot lot = lotQueryManager.getLot(lotId, facilityRrn);
lot.setLotComments((SorterEnum.Constant.EXCHANGE.equalsIgnoreCase(type) ? "普通" : "特殊") + "交换晶舟,初始晶舟为: " +
sorterBean.getSourceCarrierId() + ",SortJob Finish。");
lot.setTransPerformedby(sorterBean.getCreateUser());
lot.setTransId(type);
lot.setSorterFlag(true);
lot.setLocation(sortJobBean.getEquipmentId());
lot.setEqptRrn(sortJobBean.getEquipmentRrn());
Carrier toCarrier = carrierManager.getCarrier(sorterBean.getTargetCarrierRrn());
//Carrier 的一些校验
Assert.isFalse(!StringUtils.equalsIgnoreCase(toCarrier.getCarrierStatus(), PcdStatus.FREE_KEY) &&
!StringUtils.equalsIgnoreCase(toCarrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
Errors.create().key(MessageIdList.CARRIER_STATUS_INVALID).args(toCarrier.getInstanceId()).build());
List<Map> carrierMappings = buildCarrierMapping(sorterDetailBeans);
carrierManager.exchangeCarrierSpecial(lot, toCarrier.getInstanceRrn(), carrierMappings, toCarrier, facilityRrn,
sorterBean.getCreateUser());
}
private void splitLot(SortJobBean sortJobBean, String type) {
//目前仅支持 永久分批
List<Map> childLots = new ArrayList<>();
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean firstSorterBean = SorterEnum.getListFirst(sorterBeans);
String userId = firstSorterBean.getCreateUser();
List<SorterDetailBean> sorterDetailBeans = firstSorterBean.getSorterDetailBeanList();
SorterDetailBean firstSorterDetailBean = SorterEnum.getListFirst(sorterDetailBeans);
long baseLotRrn = firstSorterDetailBean.getLotRrn();
Lot lot = lotQueryManager.getLot(baseLotRrn);
Carrier targetCarrier = carrierManager.getCarrier(firstSorterBean.getTargetCarrierRrn());
// carrier的一些校验
Assert.isFalse(!StringUtils.equalsIgnoreCase(targetCarrier.getCarrierStatus(), PcdStatus.FREE_KEY) &&
!StringUtils.equalsIgnoreCase(targetCarrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
Errors.create().key(MessageIdList.CARRIER_STATUS_INVALID).args(targetCarrier.getInstanceId())
.build());
//创建子批ID
String childLotId = lotManager.buildChildLotId(lot.getLotId(), new ArrayList());
//解析子批中的晶圆
List<Map> childLotUnits = buildCarrierMapping(sorterDetailBeans);
Map childLot = buildChildLot(lot, childLotId, targetCarrier, childLotUnits);
childLots.add(childLot);
List<Unit> parentLotUnits = unitQueryManager.getUnitList(lot.getLotRrn());
//计算排除,先收集需要分批出去的晶圆,然后用母批现有晶圆去减
List unitsOfParentLot = calculateRemainUnitList(parentLotUnits, childLots);
Assert.isFalse(parentLotUnits.size() == unitsOfParentLot.size(),
Errors.create().key(MessageIdList.CHILD_LOT_UNIT_DATA_ERROR).build());
HashMap valueMap = new HashMap();
lot.setSorterFlag(true);
lot.setLocation(sortJobBean.getEquipmentId());
lot.setEqptRrn(sortJobBean.getEquipmentRrn());
valueMap.put("lot", lot);
valueMap.put("childLots", childLots);
valueMap.put("splitType", SorterEnum.HardCode.PERMANENT);
// valueMap.put("subSplitType", copyForm.getSubSplitType());
valueMap.put("unitOfParent", unitsOfParentLot);
String comment = "Sort Job Split ParentLot:" + lot.getLotId() + " ChildLot:" + childLotId;
valueMap.put("comment", comment);
valueMap.put("facilityRrn", LocalContext.getFacilityRrn());
valueMap.put("user", userId);
TransReason transReason = new TransReason();
transReason.setReasonCode(SorterEnum.Constant.BLANK);
transReason.setReason(comment);
transReason.setResponsibility(userId);
transReason.setTransQty1((double) childLotUnits.size());
HashMap map = null;
// 先获取母批中的所有晶圆数量,减去要分批出去的晶圆,就是 remainQty
if (CollectionUtils.isEmpty(unitsOfParentLot)) {//重新计算 remainQty 目标会涉及到释放晶舟
map = new HashMap();
map.put("lotRrn", lot.getLotRrn());
map.put("transId", SorterEnum.HardCode.TERMINATE);
map.put("user", userId);
TransReason transR = new TransReason();
transR.setReasonCategory(SorterEnum.HardCode.TERM);
transR.setReason(SorterEnum.HardCode.NO_QTY);
transR.setReasonCode(SorterEnum.Constant.SPLIT);
transR.setResponsibility(userId);
transR.setTransQty1(lot.getQty1());
transR.setTransQty2(lot.getQty2());
map.put("transReason", transR);
map.put("comments", "");
}
valueMap.put("terminateMap", map);
valueMap.put("transReason", transReason);
valueMap.put(SystemConstant.Str.ACTION_FLAG, SystemConstant.Str.CAL_STEP_TIME);
if (StringUtils.equals(sortJobBean.getJobType().toUpperCase(), SorterEnum.Constant.PILOT_SPLIT)) {
valueMap.put("subSplitType", "pilot");
}
lotManager.splitLotWithTerminate(valueMap);
if (CollectionUtils.isNotEmpty(childLots)) {
//子批次开始时间
for (Map childLotMap : childLots) {
String childLotIdTemp = MapUtils.getString(childLotMap, "childLotId");
Lot childLotTemp = lotQueryManager.getLot(childLotIdTemp, LocalContext.getFacilityRrn());
if (childLotTemp == null) {
continue;
}
//#39709 xsl split之后子批重置计时 计时重置,根据当前状态开始计时
//劈出来的新批次
lotManager.calcStepSpeedTime(childLotTemp.getLotStatus(), childLotTemp.getBeforeStatus(),
childLotTemp.getLotRrn(), true);
}
}
SorterBean sb = new SorterBean(firstSorterBean.getMainJobRrn());
sb.setSubJobRrn(firstSorterBean.getSubJobRrn());
sb.setJsonAttributeData4(childLotId);
sorterDAO.updateSorterBean(sb);//回填子批ID
}
private void merge(SortJobBean sortJobBean) {
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean firstSorterBean = SorterEnum.getListFirst(sorterBeans);
String userId = firstSorterBean.getCreateUser();
Long sourceCarrierRrn = sortJobBean.getSourceCarrierRrn();
Long targetCarrierRrn = sortJobBean.getTargetCarrierRrn();
Lot parentLot = lotQueryManager.getLotByCarrierRrn(targetCarrierRrn);
parentLot.setSorterFlag(true);
parentLot.setLocation(sortJobBean.getEquipmentId());
parentLot.setEqptRrn(sortJobBean.getEquipmentRrn());
Lot childLot = lotQueryManager.getLotByCarrierRrn(sourceCarrierRrn);
// build子批信息
List<Map<String, Object>> childLots = new ArrayList<>();// 被合子批
Map<String, Object> childLotMap = new HashMap<>();
childLotMap.put("childLotId", childLot.getLotId());
childLotMap.put("carrierId", childLot.getCarrierId());
childLotMap.put("qty1", childLot.getQty1());
childLotMap.put("qty2", childLot.getQty2());
childLotMap.put("productId", childLot.getProductId());
childLotMap.put("processId", childLot.getProcessId());
childLotMap.put("operationId", childLot.getOperationId());
List<Map> childUnits = unitQueryManager.getUnitListByCarrier(sourceCarrierRrn);
childLotMap.put("units", childUnits);
childLots.add(childLotMap);
Assert.isFalse(firstSorterBean.getSorterDetailBeanList().size() != childUnits.size(),
Errors.create().key(MessageIdList.CHILD_LOT_UNIT_ERROR).args(childLot.getLotId()).build());
//母批现有的晶圆列表
List<Map> unitOfParent = unitQueryManager.getUnitListByLot(parentLot.getLotRrn());
//需要母批最新的晶圆列表,母批现有晶圆+需要合批的子批的晶圆
List newUnits = buildMergeUnit(unitOfParent, sortJobBean.getSorterBeans());
//
Map<String, Object> valueMap = new HashMap<>();
valueMap.put("lot", parentLot);// 目标批次 Lot对象, lotRrn即可
valueMap.put("childLots", childLots);//childLotId、qty1、qty2、units
valueMap.put("unitOfParent", unitOfParent);//母批当前在晶舟中的所有晶圆
String comment = "Sort Job Merge ParentLot:" + parentLot.getLotId() + " ChildLot:" + childLot.getLotId();
valueMap.put("comment", comment);
valueMap.put("newUnits", newUnits);
TransReason transReason = new TransReason();
transReason.setReasonCode("");
transReason.setResponsibility(userId);
transReason.setReason(comment);
valueMap.put("transReason", transReason);
checkLotPriority(valueMap, parentLot, childLots);
//创建需要上锁的 rrn arry
List<String> needLockLotRrns = new ArrayList<>();
needLockLotRrns.add(StringUtils.toString(childLot.getLotRrn()));
valueMap.put(SystemConstant.Str.ACTION_FLAG, SystemConstant.Str.NORMAL_MERGE);
valueMap.put(SystemConstant.Str.LOT_RRN_LIST, needLockLotRrns);
lotManager.mergeLot(valueMap);
}
private void flipSideCarrier(SortJobBean sortJobBean) {
List<SorterBean> sorterBeans = sortJobBean.getSorterBeans();
SorterBean firstSorterBean = SorterEnum.getListFirst(sorterBeans);
String flipStr = firstSorterBean.getJsonAttributeData3();
String[] flipArr = StringUtils.split(flipStr, "|");
Assert.isFalse(StringUtils.isBlank(flipStr) || flipArr.length != 2,
Errors.create().key(MessageIdList.FLIP_DATA_ERROR).content("Flip data Error!").build());
Lot sourceLot = lotQueryManager.getLotByCarrierRrn(firstSorterBean.getSourceCarrierRrn());
if (LotStatus.isRunCardHold(sourceLot.getLotStatus())) {
sourceLot = lotQueryManager.getLot(RunCardUtils.buildMainRcLotId(sourceLot.getLotId()),
sourceLot.getFacilityRrn());
}
Boolean state = StringUtils.equalsIgnoreCase(sourceLot.getFlipType(), flipArr[0]);
Assert.state(state, Errors.create().key(MessageIdList.FLIP_DATA_ERROR).content("Flip data Error!").build());
//记录机台号
sourceLot.setEqptRrn(sortJobBean.getEquipmentRrn());
sourceLot.setLocation(sourceLot.getEqptID());
lotManager.flipSideByLot(sourceLot, flipArr[1], true);
}
private List<Map> dealSelectedUnits(List<Map> currentUnits, List<Map> selectedUnitList, String positionKey,
boolean isRemove) {
List<Map> unitMapList;
Map[] unitArr = new Map[26];
for (Map m : currentUnits) {
int position = MapUtils.getIntValue(m, "position");
if (checkArrIndexRange(position)) {
unitArr[position] = m;
}
}
for (Map sm : selectedUnitList) {
int position = MapUtils.getIntValue(sm, positionKey);
if (checkArrIndexRange(position)) {
if (isRemove) {
unitArr[position] = null;
} else {
unitArr[position] = sm;
}
}
}
unitMapList = Arrays.stream(unitArr).filter(Objects::nonNull).collect(Collectors.toList());
return unitMapList;
}
/**
* 计算母批在分批后的剩余晶圆
*
* @param parentLotUnits
* @param childLots
* @return
*/
private List calculateRemainUnitList(List<Unit> parentLotUnits, List<Map> childLots) {
if (CollectionUtils.isEmpty(childLots)) {
return parentLotUnits;
}
List<Map> unitMapList;
Map[] unitMapArr = new Map[25];
for (Unit u : parentLotUnits) {
Map<String, Object> unitMap = new HashMap<>(8);
if (checkArrIndexRange(u.getPositionInCarrier())) {
unitMap.put("position", u.getPositionInCarrier());
unitMap.put("unitId", u.getUnitId());
unitMap.put("unitRrn", u.getUnitRrn());
unitMap.put("lotId", u.getLotId());
unitMapArr[u.getPositionInCarrier() - 1] = unitMap;
}
}
for (Map map : childLots) {
List<Map> units = (List<Map>) MapUtils.getObject(map, "unitList");
List<Map> unitList = new ArrayList<>();//获得移除空位置后的晶圆列表
if (CollectionUtils.isNotEmpty(units)) {
for (Map unit : units) {
//"unitId":"A0P001#22","unitRrn":"6172996","lotId":"A0P001"
String lotId = MapUtils.getString(unit, "lotId");
String unitId = MapUtils.getString(unit, "unitId");
Long unitRrn = MapUtils.getLong(unit, "unitRrn");
if (StringUtils.isNotEmpty(lotId) && StringUtils.isNotEmpty(unitId) && unitRrn != null) {
int postion = MapUtils.getIntValue(unit, "position");
if (checkArrIndexRange(postion)) {
unitMapArr[postion - 1] = null;
unitList.add(unit);
}
}
}
map.put("units", unitList);
}
}
unitMapList = Arrays.stream(unitMapArr).filter(Objects::nonNull).collect(Collectors.toList());
return unitMapList;
}
private List<Map> buildCarrierMapping(List<SorterDetailBean> sorterDetailBeans) {
return sorterDetailBeans.stream().map(m -> {
Map map = new HashMap();
map.put("lotRrn", m.getLotRrn());
map.put("lotId", m.getLotId());
map.put("unitRrn", m.getUnitRrn());
map.put("unitId", m.getUnitId());
map.put("oldPosition", m.getSourcePosition());
map.put("position", m.getTargetPosition());
return map;
}).collect(Collectors.toList());
}
private List buildMergeUnit(List<Map> unitOfParent, List<SorterBean> sorterBeans) {
Map[] unitMaps = new Map[25];
for (Map m : unitOfParent) {
int position = MapUtils.getIntValue(m, "position");
if (position > 0)
unitMaps[position - 1] = m;
}
for (SorterBean sb : sorterBeans) {
for (SorterDetailBean sdb : sb.getSorterDetailBeanList()) {
if (sdb.getTargetPosition() > 0) {
Map m = new HashMap();
m.put("position", sdb.getTargetPosition());
m.put("unitId", sdb.getUnitId());
m.put("unitRrn", sdb.getUnitRrn());
m.put("lotId", sdb.getLotId());
m.put("lotRrn", sdb.getLotRrn());
unitMaps[sdb.getTargetPosition() - 1] = m;
}
}
}
return Arrays.stream(unitMaps).filter(Objects::nonNull).collect(Collectors.toList());
}
private boolean checkArrIndexRange(int range) {
return range >= 1 && range <= 25;
}
/**
* @param parentLot
* @param childLotId
* @param targetCarrier
* @param units
* @return Map<String, Object>
* @Description 分批时构建子批信息
* @author Aiden
*/
private Map<String, Object> buildChildLot(Lot parentLot, String childLotId, Carrier targetCarrier,
List<Map> units) {
Map<String, Object> childLot = new HashMap<>();
childLot.put("childLotId", childLotId);
childLot.put("carrierId", targetCarrier.getInstanceId());
childLot.put("carrierRrn", targetCarrier.getInstanceRrn());
childLot.put("splitQty", (double) units.size());
childLot.put("intSplitQty", units.size() + StringUtils.EMPTY);
childLot.put("technologyRrn", parentLot.getProcessRrn());
childLot.put("wflStepPath", null);
childLot.put("routeId", parentLot.getRouteId());
childLot.put("operationId", parentLot.getOperationId());
childLot.put("operationRrn", parentLot.getOperationRrn());
childLot.put("operationDesc", parentLot.getOperationDesc());
childLot.put("unitList", units);
childLot.put("units", units);
childLot.put("changeProcessFlag", SorterEnum.HardCode.FALSE);
childLot.put("changeAcutl", SorterEnum.HardCode.MINUS_ONE);
return childLot;
}
private void checkLotPriority(Map<String, Object> valueMap, Lot lot, List<Map<String, Object>> childLots) {
// Check the priority size of sub-lot and lot
Integer tempHotFlag = NumberUtils.toInt(lot.getHotFlag(), Integer.MAX_VALUE);
Integer tempProirity = Optional.ofNullable(lot.getPriority()).orElse(Integer.MAX_VALUE);
boolean changeFlag = false;
for (Map<String, Object> subLotMap : childLots) {
Lot subLot = lotQueryManager.getLot(MapUtils.getString(subLotMap, "childLotId"), lot.getFacilityRrn());
Integer hotFlag = NumberUtils.toInt(subLot.getHotFlag(), Integer.MAX_VALUE);
Integer priority = Optional.ofNullable(subLot.getPriority()).orElse(Integer.MAX_VALUE);
if (hotFlag < tempHotFlag || (hotFlag.equals(tempHotFlag) && priority < tempProirity)) {
changeFlag = true;
tempHotFlag = hotFlag;
tempProirity = priority;
}
}
if (changeFlag) {
valueMap.put("hotFlag", tempHotFlag);
valueMap.put("priority", tempProirity);
}
}
private void buildCarrierMappingInfo(TransactionLog transactionLog, Long carrierRrn) {
List<Unit> carrierUnitList = new ArrayList<>();
lotInqManager.getLotListByCarrierRrn(carrierRrn).stream().forEach(lot -> {
carrierUnitList.addAll(unitQueryManager.getUnitList(lot.getLotRrn()));
});
carrierManager.updateCarrierMapping(transactionLog, carrierRrn, carrierUnitList);
}
private void buildReadT7CodeSortInfo(SorterBean sorterBean, Lot lot) {
// 构建units
List<Map> sourceUnits = unitQueryManager.getUnitListByCarrier(lot.getCarrierRrn());
List<SorterDetailBean> sourceUnitList = sourceUnits.stream().map(unitMap -> {
String unitId = MapUtils.getString(unitMap, "unitId");
long unitRrn = MapUtils.getLong(unitMap, "unitRrn", 0L);
String lotId = MapUtils.getString(unitMap, "lotId");
long lotRrn = MapUtils.getLong(unitMap, "lotRrn", 0L);
int position = MapUtils.getIntValue(unitMap, "position", 0);
String customerT7Code = StringUtils.EMPTY;
long operationRrn = lot.getOperationRrn();
return new SorterDetailBean(lotRrn, lotId, unitRrn, unitId, position, position);
}).collect(Collectors.toList());
sorterBean.setSorterDetailBeanList(sourceUnitList);
sorterBean.setExchangeTotalQty(sourceUnits.size());
}
@Override
public void endReadT7Code(List<Unit> units) {
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.CUSTOMER_T7CODE);
try {
//校验数据正确性
Lot lot = new Lot();
StringBuffer unitT7Code = new StringBuffer();
if(units.get(0).getLotRrn()!=null&&units.get(0).getLotRrn()>0){
lot = lotQueryManager.getLot(units.get(0).getLotRrn());
}
for (Unit unit : units){
if(unit.getUnitRrn()<=0){
Unit validUnit = unitQueryManager.getUnit(LocalContext.getFacilityRrn(),unit.getUnitId());
Assert.isTrue(validUnit!=null,Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
Assert.isTrue(validUnit.getUnitRrn()>0,Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
unit.setUnitRrn(validUnit.getUnitRrn());
}
unitT7Code.append(unit.getUnitId()+"->"+(StringUtils.isEmpty(unit.getCustomerT7Code())?StringUtils.EMPTY: unit.getCustomerT7Code())+"; ");
//更新unit表中customer t7code字段
unitManager.updateCustomerT7Code(unit);
}
//插入数据到UNIT_T7CODE_MAPPING_H表中
unitManager.insertUnitT7CodeMappingH(units,transactionLog);
lot.setTransId(TransactionNames.CUSTOMER_T7CODE);
lot.setLotComments(unitT7Code.toString());
//插入数据到lot trans history中
lotManager.insertLotTransH(transactionLog.getTransRrn(),1L,lot);
transactionLogManager.markTransactionLog(transactionLog);
} catch (Exception e) {
logger.error(e);
throw new SystemIllegalArgumentException(Errors.create().content(e.getMessage()).build());
}
}
@Override
public void checkCustomerT7Code(List<Unit> units) {
//校验units不能为空
Assert.isFalse(CollectionUtils.isEmpty(units),Errors.create().key(MessageIdList.CUSTOMER_T7CODE_CAN_NOT_EMPTY).build());
Lot lot = lotQueryManager.getLot(units.get(0).getLotRrn());
Assert.state(lot != null, Errors.create().key(MessageIdList.LOT_MISSING_ID).content("No such lotId!").build());
Assert.state(lot.getLotRrn() > 0, Errors.create().key(MessageIdList.LOT_MISSING_ID).content("No such lotId!").build());
//卡控每片wafer上都要有t7code
List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());
Assert.isTrue(NumberUtils.compare(unitList.size(),units.size())==0,Errors.create().key(MessageIdList.UNIT_AND_CUSTOMERT7CODE_COUNT_NOT_SAME).build());
units.stream().forEach(unit -> {
//校验unit id是否存在
Unit validUnit = unitQueryManager.getUnit(LocalContext.getFacilityRrn(),unit.getUnitId());
Assert.isTrue(validUnit!=null, Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
Assert.isTrue(validUnit.getUnitRrn()>0, Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
//晶圆位置不能为空
Assert.isFalse(unit.getPositionInCarrier()==null,Errors.create().key(MessageIdList.SLOT_CAN_NOT_EMPTY).build());
//校验卡槽数是否一致
List<Unit> compareUnitList = unitList.stream().filter(u ->
StringUtils.equals(u.getUnitId(),unit.getUnitId())&&NumberUtils.compare(u.getPositionInCarrier(),unit.getPositionInCarrier())==0
).collect(Collectors.toList());
Assert.isTrue(CollectionUtils.isNotEmpty(compareUnitList),Errors.create().key(MessageIdList.UNIT_ID_AND_SLOT_NOT_MATCH).args(new Object[]{unit.getUnitId(),unit.getPositionInCarrier()}).build());
//校验是否有空的customer t7code
Assert.isFalse(StringUtils.isEmpty(unit.getCustomerT7Code()), Errors.create().key(MessageIdList.UNIT_T7CODE_CAN_NOT_EMPTY).args(unit.getUnitId()).build());
//customer t7code只能绑定一个unit
List<Unit> currentT7codeUnits = unitQueryManager.getUnitListByCustomerT7Code(unit.getCustomerT7Code());
Assert.isFalse(CollectionUtils.isNotEmpty(currentT7codeUnits),Errors.create().key(MessageIdList.CUSTOMER_T7CODE_IS_EXIST).args(unit.getCustomerT7Code()).build());
});
List<Unit> beforeUnits = new ArrayList<>();
//校验同一个卡槽中customer t7code不能相同
int beforeCount = units.size();
beforeUnits = units;
units = units.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(Comparator.comparing(Unit::getCustomerT7Code))), ArrayList::new));
List<Unit> finalUnits = units;//去重后的数据
beforeUnits.stream().forEach(beforeUnit -> {
Assert.isTrue(finalUnits.contains(beforeUnit),Errors.create().key(MessageIdList.CUSTOMER_T7CODE_IS_EXIST).args(beforeUnit.getCustomerT7Code()).build());
});
}
@Override
public void updateSorterJobForInLineExchange(SortJobBean sortJobBean, Lot lot) {
Carrier carrier = checkTargetCarrier(sortJobBean.getTargetCarrierId(), lot);
SorterBean endSortJobBean = new SorterBean();
endSortJobBean.setMainJobRrn(sortJobBean.getMainJobRrn());
endSortJobBean.setTargetCarrierId(sortJobBean.getTargetCarrierId());
endSortJobBean.setTargetCarrierRrn(carrier.getInstanceRrn());
sorterDAO.updateSorterBean(endSortJobBean);
}
@Override
public String endSortJobForInlineExchange(SortJobBean sortJobBean, Lot lot) {
updateSorterJobForInLineExchange(sortJobBean, lot);
return sorterManager.endSortJob(sortJobBean);
}
@Override
public Carrier checkTargetCarrier(String targetCarrierId, Lot lot) {
Carrier carrier = carrierManager.getCarrier(LocalContext.getFacilityRrn(), targetCarrierId);
Assert.state(carrier != null,
Errors.create().key(MessageIdList.CARRIER_CASSETTE_ID_NOT_EXIST).build());
Assert.state(carrier.getInstanceRrn() > 0,
Errors.create().key(MessageIdList.CARRIER_CASSETTE_ID_NOT_EXIST).build());
String targetCSTType = lotQueryManager.getToCarrierTypeForChange(lot);
Assert.state(StringUtils.equalsIgnoreCase(targetCSTType, carrier.getObjectSubtype()),
Errors.create().key(MessageIdList.BOND_CARRIER_TYPE_MIS_MATCH).build());
boolean isAssemblyNeed = StringUtils.equalsIgnoreCase(
referenceFileManager.getReferenceDetailExchange(ReferenceDetailNames.CARRIER_TYPE,
carrier.getObjectSubtype(), null,
ReferenceFileConst.DATA_2_VALUE),
SorterEnum.HardCode.ASSEMBLY_NEED_KEY);
Assert.isFalse(isAssemblyNeed && !StringUtils.equals(carrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
Errors.create().key(MessageIdList.CARRIER_NEED_ASSEMBLED).args(carrier.getInstanceId()).build());
Assert.isTrue(isAssemblyNeed || StringUtils.equals(carrier.getCarrierStatus(), PcdStatus.FREE_KEY),
Errors.create().key(MessageIdList.CARRIER_STATUS_INVALID).args(carrier.getInstanceId()).build());
//判断是否超过清洗时间
boolean overCleanFlag = pcdManager.checkPcdOverClean(carrier.getInstanceRrn());
Assert.isTrue(overCleanFlag, Errors.create().key(MessageIdList.CARRIER_OUT_OF_CLEAN_DATE)
.content("Cassette is out of clean date!").build());
return carrier;
}
@Override
public void checkUnitMaterialID(List<Unit> units) {
//校验units不能为空
Assert.isFalse(CollectionUtils.isEmpty(units),
Errors.create().key(MessageIdList.MATERIAL_ID_NOT_EMPTY).build());
Lot lot = lotInqManager.getLot(units.get(0).getLotRrn());
Assert.state(lot != null, Errors.create().key(MessageIdList.LOT_MISSING_ID).content("No such lotId!").build());
Assert.state(lot.getLotRrn() > 0,
Errors.create().key(MessageIdList.LOT_MISSING_ID).content("No such lotId!").build());
//卡控每片wafer上都要有materialID
List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());
Assert.isFalse(unitList.size() != units.size(),
Errors.create().key(MessageIdList.UNIT_MATERIALID_COUNT_NOT_SAME).build());
units.stream().forEach(unit -> {
//校验unit id是否存在
Unit validUnit = unitQueryManager.getUnit(LocalContext.getFacilityRrn(), unit.getUnitId());
Assert.isTrue(validUnit != null,
Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
Assert.isTrue(validUnit.getUnitRrn() > 0,
Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
//晶圆位置不能为空
Assert.isFalse(unit.getPositionInCarrier() == null,
Errors.create().key(MessageIdList.SLOT_CAN_NOT_EMPTY).build());
//校验卡槽数是否一致
List<Unit> compareUnitList = unitList.stream()
.filter(u -> StringUtils.equals(u.getUnitId(), unit.getUnitId()) &&
NumberUtils.compare(u.getPositionInCarrier(),
unit.getPositionInCarrier()) == 0)
.collect(Collectors.toList());
Assert.isTrue(CollectionUtils.isNotEmpty(compareUnitList),
Errors.create().key(MessageIdList.UNIT_ID_AND_SLOT_NOT_MATCH)
.args(new Object[]{unit.getUnitId(), unit.getPositionInCarrier()}).build());
//校验是否有空的MaterialID
Assert.isFalse(StringUtils.isEmpty(unit.getMaterialId()),
Errors.create().key(MessageIdList.UNIT_MATERIALID_CAN_NOT_EMPTY).args(unit.getUnitId())
.build());
//material Id只能绑定一个unit
List<Unit> materialIdUnits = unitQueryManager.getUnitListByMaterialId(unit.getMaterialId());
Assert.isFalse(CollectionUtils.isNotEmpty(materialIdUnits),
Errors.create().key(MessageIdList.UNIT_MATERIALID_EXISTS).args(unit.getCustomerT7Code())
.build());
});
List<Unit> beforeUnits = new ArrayList<>();
//校验同一个卡槽中material Id不能相同
beforeUnits = units;
//去重后的数据
units = units.stream().collect(
collectingAndThen(toCollection(() -> new TreeSet<>(Comparator.comparing(Unit::getMaterialId))),
ArrayList::new));
List<Unit> finalUnits = units;
beforeUnits.stream().forEach(beforeUnit -> {
Assert.isTrue(finalUnits.contains(beforeUnit),
Errors.create().key(MessageIdList.UNIT_MATERIALID_EXISTS).args(beforeUnit.getMaterialId())
.build());
});
}
@Override
public void updateUnitMaterialID(List<Unit> units) {
TransactionLog transactionLog = transactionLogManager
.startTransactionLog(LocalContext.getUserId(), TransactionNames.OFFLINE_READ_MATERIALID);
try {
//校验数据正确性
Lot lot = new Lot();
StringBuilder transComments = new StringBuilder();
if (units.get(0).getLotRrn() != null && units.get(0).getLotRrn() > 0) {
lot = lotInqManager.getLot(units.get(0).getLotRrn());
}
for (Unit unit : units) {
if (unit.getUnitRrn() <= 0) {
Unit validUnit = unitQueryManager.getUnit(LocalContext.getFacilityRrn(), unit.getUnitId());
Assert.isTrue(validUnit != null,
Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
Assert.isTrue(validUnit.getUnitRrn() > 0,
Errors.create().key(MessageIdList.UNIT_ID_MISSING).args(unit.getUnitId()).build());
unit.setUnitRrn(validUnit.getUnitRrn());
}
transComments.append(unit.getUnitId() + "->" +
(StringUtils.isEmpty(unit.getMaterialId()) ? StringUtils.EMPTY : unit
.getMaterialId()) + "; ");
//更新unit表中Material_ID字段
unitManager.updateUnitMaterialID(unit);
}
//插入数据到UNIT_MATERIAL_MAPPING_H表中
unitManager.insertUnitMaterialMappingH(units, transactionLog);
lot.setTransId(TransactionNames.OFFLINE_READ_MATERIALID);
lot.setLotComments(transComments.toString());
//插入数据到lot trans history中
lotTransHistoryReqManager.createLotTransHistory(transactionLog, lot, transComments.toString());
transactionLogManager.markTransactionLog(transactionLog);
} catch (Exception e) {
logger.error(e);
throw new SystemIllegalArgumentException(Errors.create().content(e.getMessage()).build());
}
}
}