重庆打包

test-temp-wj-250117-pack
王杰 4 months ago
parent 51ba9f967f
commit 0c74c405de

@ -7,15 +7,20 @@ import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseSwsService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.function.IFsmModuleFunctionService;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPackage;
import cn.estsh.i3plus.pojo.mes.model.ButtonDynamicModel;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
@ -46,6 +51,7 @@ public class MesFunctionPackageProgressService extends BaseSwsService implements
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public Object doCustomApiDispatch(StationRequestBean reqBean, StationResultBean resultBean, ButtonDynamicModel buttonDynamicModel) {
//页面渲染数据集
Map<String, Object> resultMap = new HashMap<>();
//获取打包数据
@ -60,6 +66,7 @@ public class MesFunctionPackageProgressService extends BaseSwsService implements
//封装返回列表
List<MesPackageDataContext> resultList = new ArrayList<>();
//封装页面数据
for (String partNo : packageDataContextMap.keySet()) {
if (StringUtils.isEmpty(partNo)) continue;
@ -69,68 +76,121 @@ public class MesFunctionPackageProgressService extends BaseSwsService implements
//列表展示: 包装条码, 装箱个数, 包装规格数量, 装箱开始时间, 装箱结束时间
resultList.add(new MesPackageDataContext(
packageDataContextList.get(0).getPartNo(), packageDataContextList.get(0).getPartName(),
packageDataContextList.get(0).getPackageNo(), new Double(packageDataContextList.size()),
packageDataContextList.get(0).getPackSpecQty(), packageDataContextList.get(0).getCreateDatetime(), packageDataContextList.get(0).getModifyDatetime())
packageDataContextList.get(0).getPackageNo(), new Double(packageDataContextList.size()), packageDataContextList.get(0).getPackSpecQty(),
packageDataContextList.get(0).getCreateDatetime(), packageDataContextList.get(0).getModifyDatetime(), packageDataContextList.get(0).getGenerateType())
);
}
//页面数据更新时间倒序
resultList = resultList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesPackageDataContext::getModifyDatetime).reversed()).collect(Collectors.toList());
resultMap.put(MesPcnExtConstWords.DATA, resultList);
//打包进度页面业务操作[查询]
if (StringUtils.isEmpty(buttonDynamicModel.getFunctionValue())) return resultMap;
resultMap.put(MesPcnExtConstWords.DATA_TYPE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT.getValue());
//打包进度页面业务操作的当前数据
MesPackageDataContext packageDataContext = JSONObject.parseObject(buttonDynamicModel.getFunctionValue(), MesPackageDataContext.class);
resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PICK.getValue()).scanInfo(packageDataContext.getPackageNo());
if (null == packageDataContext) {
if (null == packageDataContext || StringUtils.isEmpty(packageDataContext.getBusiType())) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,参数异常!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));
String.format("生产线[%s]工位[%s]打包进度操作按钮执行失败,参数异常!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));
}
if (CollectionUtils.isEmpty(packageDataContextMap) || !packageDataContextMap.containsKey(packageDataContext.getPartNo())) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,当前已无零件号[%s]未封箱状态的包装信息!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPartNo()));
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,当前已无零件号[%s]未封箱状态的包装信息!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPartNo()));
}
//打包进度页面业务操作的当前数据对应的实际包装数据
List<MesPackageDataContext> packageDataContextList = JSONObject.parseArray(packageDataContextMap.get(packageDataContext.getPartNo()), MesPackageDataContext.class);
if (CollectionUtils.isEmpty(packageDataContextList) || !packageDataContextList.get(0).getPackageNo().equals(packageDataContext.getPackageNo())) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,打包进度列表中已经不存在包装条码[%s],请刷新重试!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,打包进度列表中已经不存在包装条码[%s],请刷新重试!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
}
//根据包装ID查询包装信息
MesPackage packageDb = packageNoGenerateStepService.getMesPackage(reqBean.getOrganizeCode(), packageDataContextList.get(0).getPackageId());
if (null == packageDb) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,包装条码[%s]信息已经不存在,请刷新重试!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,包装条码[%s]信息已经不存在,请刷新重试!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
}
StepResult stepResult = StepResult.getSuccessComplete();
try {
packageNoGenerateStepService.doForcePrint(reqBean, resultBean, stepResult, packageDataContextList, packageDb);
} catch (ImppBusiException e) {
stepResult.msg(e.getErrorDetail());
} catch (Exception e) {
String error = String.format("生产线[%s]工位[%s]强制打包%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode()));
this.cacheException(reqBean, reqBean.getStepName(), error, e, false);
stepResult.msg(error);
if (packageDb.getIsSealed().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) {
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,包装条码[%s]信息当前状态[已封箱],请刷新重试!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
}
if (!StringUtils.isEmpty(stepResult.getMsg())) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), stepResult.getMsg()));
//修改数量
if (BUSI_TYPE.THREE.getValue().equals(packageDataContext.getBusiType())) {
//仅统计包装才支持修改数量
if (packageDataContextList.get(0).getGenerateType().compareTo(MesExtEnumUtil.PACKING_RULE_GENERATE_TYPE.PACKAGE.getValue()) != 0) {
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]包装条码[%s]不支持修改数量,请刷新重试!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
}
if (packageDataContextList.size() == packageDataContext.getQty()) {
return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]包装条码[%s]修改数量操作无效,请刷新重试!",
reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
}
//修改包装信息的数量
packageNoGenerateStepService.savePackageData(reqBean, packageDb, packageDataContext.getQty());
//打包数据更新数量(判断是增加还是减少数量)
if (MathOperation.compareTo(packageDataContext.getQty(), new Double(packageDataContextList.size())) < 0) {
packageDataContextList = packageDataContextList.subList(0, packageDataContext.getQty().intValue());
} else {
for (int i = 0; i < (packageDataContext.getQty().intValue() - packageDataContextList.size()); i ++) {
MesPackageDataContext addPackageDataContext = new MesPackageDataContext();
BeanUtils.copyProperties(packageDataContextList.get(0), addPackageDataContext);
addPackageDataContext.setModifyDatetime(TimeTool.getNowTime(true));
packageDataContextList.add(addPackageDataContext);
}
}
//打包数据更新数量
packageDataContextMap.put(packageDataContext.getPartNo(), JSONObject.toJSONString(packageDataContextList));
//页面数据更新数量
resultList.stream().filter(o -> (null != o && o.getPackageNo().equals(packageDataContext.getPackageNo()))).findFirst().get().qty(packageDataContext.getQty(), TimeTool.getNowTime(true));
} else {
//强制打包
if (BUSI_TYPE.ONE.getValue().equals(packageDataContext.getBusiType())) {
StepResult stepResult = StepResult.getSuccessComplete();
try {
//强制打包
packageNoGenerateStepService.doForcePrint(reqBean, resultBean, stepResult, packageDataContextList, packageDb);
} catch (ImppBusiException e) {
stepResult.msg(e.getErrorDetail());
} catch (Exception e) {
String error = String.format("生产线[%s]工位[%s]强制打包%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode()));
this.cacheException(reqBean, reqBean.getStepName(), error, e, false);
stepResult.msg(error);
}
//判断强制打包的执行结果
if (!StringUtils.isEmpty(stepResult.getMsg())) {
return packResultMap(reqBean, resultBean, resultMap,
String.format("生产线[%s]工位[%s]强制打包失败,%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), stepResult.getMsg()));
}
} else {
//删除包装信息
packageNoGenerateStepService.deletePackageData(reqBean, packageDb, packageDataContextList.get(0).getGenerateType());
}
//打包数据移除当前零件的包装信息
packageDataContextMap.remove(packageDataContext.getPartNo());
//页面数据移除当前零件的包装信息
resultList = resultList.stream().filter(o -> (null != o && !o.getPackageNo().equals(packageDataContext.getPackageNo()))).collect(Collectors.toList());
}
packageDataContextMap.remove(packageDataContext.getPartNo());
//保存打包数据
productionCustomContextStepService.dispatchPackageDataContext(reqBean, packageDataContextMap);
resultList = resultList.stream().filter(o -> (null != o && !o.getPackageNo().equals(packageDataContext.getPackageNo()))).collect(Collectors.toList());
//重载页面数据
if (CollectionUtils.isEmpty(resultList)) resultMap.remove(MesPcnExtConstWords.DATA);
else resultMap.put(MesPcnExtConstWords.DATA, resultList);
resultMap.put(MesPcnExtConstWords.DATA_TYPE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT.getValue());
return packResultMap(reqBean, resultBean, resultMap, String.format("零件号[%s]强制封箱成功!", packageDataContext.getPartNo()));
return packResultMap(reqBean, resultBean, resultMap, String.format("零件号[%s]%s成功!", packageDataContext.getPartNo(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType())));
}
@ -140,10 +200,45 @@ public class MesFunctionPackageProgressService extends BaseSwsService implements
return resultMap;
}
private void doForcePrint(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult,
List<MesPackageDataContext> packageDataContextList, MesPackage packageDb, Map<String, String> packageDataContextMap) {
//打包进度页面业务操作
enum BUSI_TYPE {
}
ONE("1", "强制打包"),
TWO("2", "删除包装"),
THREE("3", "修改数量");
private String value;
private String description;
BUSI_TYPE(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static String valueOfDescription(String val) {
String tmp = null;
for (int i = 0; i < values().length; i++) {
if (val.equals(values()[i].value)) {
tmp = values()[i].description;
}
}
return tmp;
}
}
}

@ -9,10 +9,7 @@ import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepServ
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print.IPrintTemplateStrategyService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method.IMesPackageNoGenerateStepService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesPackageDataContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesPackageRuleContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesProduceSnPrintModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService;
@ -39,8 +36,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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 org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@ -117,10 +112,16 @@ public class MesPackageNoGenerateStepService extends BaseStepService implements
//获取上下文产出条码数据信息集合
List<MesProductionPsOutContext> productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean);
if (CollectionUtils.isEmpty(productionPsOutContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在产出零件条码信息,请重置工序解决!");
//获取上下文产品加工规则数据信息集合
List<MesProdRuleContext> prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean);
//产出条码根据零件号分组
Map<String, List<String>> productSnMap2Part = productionPsOutContextList.stream().filter(o -> null != o)
if (CollectionUtils.isEmpty(productionPsOutContextList) || CollectionUtils.isEmpty(prodRuleContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在产出零件条码信息,请重置工序解决!");
//在加工规则中搜集可以打包的数据的数据关联键集合
List<Integer> foreignKeyList = prodRuleContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsPackage()) && o.getIsPackage().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0)).map(MesProdRuleContext::getForeignKey).collect(Collectors.toList());
//搜集数据关联键集合对应的产出条码,根据零件号分组
Map<String, List<String>> productSnMap2Part = productionPsOutContextList.stream().filter(o -> (null != o && foreignKeyList.contains(o.getForeignKey())))
.collect(Collectors.groupingBy(MesProductionPsOutContext::getPartNo, Collectors.mapping(MesProductionPsOutContext::getProductSn, Collectors.toList())));
//获取包装规则信息
@ -370,25 +371,17 @@ public class MesPackageNoGenerateStepService extends BaseStepService implements
packageDb.setPrintStatus(MesExtEnumUtil.PRINT_STATUS.PRINTED.getValue());
}
//无须更新
if (!isSave) return packageDb;
if (StringUtils.isEmpty(packageDb.getId())) return packageRepository.insert(packageDb);
//更新操作
savePackageDbById(reqBean, packageDb);
return packageDb;
}
private void savePackageDbById(StationRequestBean reqBean, MesPackage packageDb) {
packageRepository.updateByPropertiesNoSync(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.ID},
new Object[]{reqBean.getOrganizeCode(), packageDb.getId()},
new String[]{MesPcnExtConstWords.QTY, MesPcnExtConstWords.IS_SEALED, MesPcnExtConstWords.PRINT_STATUS, MesPcnExtConstWords.LOT_NO,
MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
new Object[]{packageDb.getQty(), packageDb.getIsSealed(), packageDb.getPrintStatus(), packageDb.getLotNo(),
packageDb.getModifyUser(), packageDb.getModifyDatetime(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY});
}
//判断统计方式,是否生成包装明细信息, 返回当前未满包的包装条码明细数据
private List<MesPackageDataContext> insertPackageDetailAndBackUnSealedResultList(StationRequestBean reqBean, MesPackageRuleContext packageRuleContext,
MesPackage packageDb, List<String> productSnList2Cur, Boolean isSealed) {
@ -454,6 +447,7 @@ public class MesPackageNoGenerateStepService extends BaseStepService implements
return null;
}
//进行打印
private void doPrintPackageNo(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesPackageRuleContext packageRuleContext,
MesLabelTemplate labelTemplate, IPrintTemplateStrategyService strategyService, List<MesPackage> packageList, Boolean isAsyn) {
if (null == strategyService) {
@ -508,14 +502,54 @@ public class MesPackageNoGenerateStepService extends BaseStepService implements
printedSnLogRepository.saveAll(printModel.getMesPrintedSnLogList());
}
//打包进度-强制打包
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = {ImppBusiException.class, Exception.class})
public void doForcePrint(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, List<MesPackageDataContext> packageDataContextList, MesPackage packageDb) {
//标记满包状态跟打印状态
savePackageDb(reqBean, packageDb, packageDataContextList.size(), true, false);
List<MesPackage> packageList = new ArrayList<>();
packageList.add(packageDb);
//进行打印
doPrintPackageNo(reqBean, resultBean, stepResult, packageDataContextList.get(0), null, null, packageList, true);
//更新操作
savePackageDbById(reqBean, packageDb);
}
//更新操作
private void savePackageDbById(StationRequestBean reqBean, MesPackage packageDb) {
packageRepository.updateByPropertiesNoSync(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.ID},
new Object[]{reqBean.getOrganizeCode(), packageDb.getId()},
new String[]{MesPcnExtConstWords.QTY, MesPcnExtConstWords.IS_SEALED, MesPcnExtConstWords.PRINT_STATUS, MesPcnExtConstWords.LOT_NO,
MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
new Object[]{packageDb.getQty(), packageDb.getIsSealed(), packageDb.getPrintStatus(), packageDb.getLotNo(),
packageDb.getModifyUser(), packageDb.getModifyDatetime(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY});
}
//删除包装信息
@Override
public void deletePackageData(StationRequestBean reqBean, MesPackage packageDb, Integer generateType) {
int count = packageRepository.updateByPropertiesNoSync(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.ID, MesPcnExtConstWords.IS_SEALED},
new Object[]{reqBean.getOrganizeCode(), packageDb.getId(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()},
new String[]{MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
new Object[]{CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY});
if (count == 0 || generateType.compareTo(MesExtEnumUtil.PACKING_RULE_GENERATE_TYPE.PACKAGE.getValue()) == 0) return;
packageDetailRepository.updateByPropertiesNoSync(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.PACKAGE_NO},
new Object[]{reqBean.getOrganizeCode(), packageDb.getPackageNo()},
new String[]{MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
new Object[]{CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY});
}
//修改包装信息的数量
@Override
public void savePackageData(StationRequestBean reqBean, MesPackage packageDb, Double qty) {
packageRepository.updateByPropertiesNoSync(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.ID, MesPcnExtConstWords.IS_SEALED},
new Object[]{reqBean.getOrganizeCode(), packageDb.getId(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()},
new String[]{MesPcnExtConstWords.QTY, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
new Object[]{qty, reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY});
}
}

@ -6,6 +6,7 @@ import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -13,8 +14,19 @@ import java.util.List;
public interface IMesPackageNoGenerateStepService {
@ApiOperation(value = "根据包装ID查询包装信息")
MesPackage getMesPackage(String organizeCode, Long packageId);
@ApiOperation(value = "强制打包")
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = {ImppBusiException.class, Exception.class})
void doForcePrint(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, List<MesPackageDataContext> packageDataContextList, MesPackage packageDb);
@ApiOperation(value = "删除包装信息")
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = {ImppBusiException.class, Exception.class})
void deletePackageData(StationRequestBean reqBean, MesPackage packageDb, Integer generateType);
@ApiOperation(value = "修改包装信息的数量")
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = {ImppBusiException.class, Exception.class})
void savePackageData(StationRequestBean reqBean, MesPackage packageDb, Double qty);
}

@ -0,0 +1,292 @@
#\u9879\u76EE\u7AEF\u53E3
server.port=8350
#\u672C\u673Aip
impp.server.ip=localhost
#impp.server.ip=192.168.0.105
#andon ip
impp.andon.url=http://10.195.88.71:8750
#ptl-pcn ip
impp.ptl-pcn.url=http://10.195.88.71:8750
#pcn plc\u5168\u5C40\u4E1A\u52A1\u5F00\u5173 1.yfai-hnc
mes.plc.callback.open=123
#console\u63A7\u5236\u53F0\u670D\u52A1\uFF08zipkin\u8FFD\u8E2A\u5168\u8DEF\u5F84\uFF09
impp.console.ip=http://10.195.88.71:8010
################ \u529F\u80FD\u914D\u7F6E1 ################
#\u5DE5\u4F5C\u533AID,\u4E0D\u540C\u670D\u52A1\u5668\u4E0D\u540CID 0 - 31
impp.snowflake.work.id=22
#\u6570\u636E\u4ED3\u533AID 0 - 31 \u6709\u9ED8\u8BA4\u56FA\u5B9AID
impp.snowflake.database.id=22
#\u82E5\u65E0\u6CD5\u8FDE\u63A5\u6CE8\u518C\u4E2D\u5FC3\uFF0C\u662F\u5426\u9700\u8981\u4E00\u76F4\u68C0\u6D4B\u52A0\u5165
impp.cluster.fetch=false
#\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3
impp.cluster.regist.center=http://10.195.88.71:8000/eureka/
#\u65E5\u5FD7\u9ED8\u8BA4\u4F7F\u7528log4j2
logging.config=classpath:log4j2-spring.xml
mes.ws=ws://10.197.190.121:8300/ws/pcn-regist/
#mes-pcn.ws.path=ws://10.197.176.77:8350
mes-pcn.ws.path=ws://localhost:8350
pcn.code=PCN-U7
########\u5E73\u53F0\u76F8\u5173\u53C2\u6570##########
#\u662F\u5426\u5F00\u5x42Fredis\u7F13\u5B58
impp.config.redis=true
#\u662F\u5426\u5F00\u542FrabbitMQ
impp.config.rabbitmq=false
#\u662F\u5426\u5F00\u542Fswagger
impp.config.swagger=true
#\u662F\u5426\u5F00\u542Fwebsocket
impp.config.websocket=true
#\u662F\u5426\u5F00\u542F\u6587\u4EF6\u670D\u52A1
impp.config.fileserver=false
#\u662F\u5426\u5BF9\u53D1\u5E03\u670D\u52A1\u8FDB\u884C\u8BE6\u7EC6\u65E5\u5FD7\u5206\u6790
impp.log.detail.controller=true
#\u662F\u5426\u5BF9\u8C03\u7528\u670D\u52A1\u8FDB\u884C\u8BE6\u7EC6\u65E5\u5FD7\u5206\u6790
impp.log.detail.service=true
################ \u961F\u5217\u5904\u7406 ################
#\u7AD9\u5185\u4FE1
impp.mq.queue.letter=true
#\u90AE\u4EF6
impp.mq.queue.mail=true
#\u5B9A\u65F6\u4EFB\u52A1
impp.mq.queue.schedule=true
#SWEB\u901A\u77E5\u5904\u7406\u961F\u5217
impp.mq.queue.sweb.notice=true
################################ \u5176\u4ED6\u529F\u80FD\u8BBE\u7F6E ################################
#redisIP
redis.hostName=10.195.88.71
#\u7AEF\u53E3\u53F7
redis.port=6379
#\u5982\u679C\u6709\u5BC6\u7801
redis.password=Admin123!
##\u5176\u4ED6redis\u914D\u7F6E\u9700\u8981\u8C03\u6574\u7684\u52A0\u5728\u6B64\u5904
################## rabbitMQ\u914D\u7F6E ####################
spring.rabbitmq.vhost=/
spring.rabbitmq.host=10.195.88.71
spring.rabbitmq.port=5672
spring.rabbitmq.username=estsh
spring.rabbitmq.password=estsh123
##\u5176\u4ED6rabbitMq\u914D\u7F6E\u9700\u8981\u8C03\u6574\u7684\u52A0\u5728\u6B64\u5904
################ \u529F\u80FD\u914D\u7F6E2 ################
#\u662F\u5426\u5F00\u542Fredis
mes.pcn.redis.open=true
#\u662F\u5426\u5141\u8BB8\u524D\u7AEF\u8DE8\u57DF\u63D0\u4EA4
impp.web.cross=true
################ \u6388\u6743\u8FC7\u6EE4\u914D\u7F6E ################
#\u7528\u6237\u6388\u6743\u8FC7\u6EE4\u8DEF\u5F84
filter.shiro.user.filteruri=/mes-pcn/operate/*
#\u7528\u6237\u6388\u6743\u8FC7\u6EE4\u8DEF\u5F84
filter.shiro.admin.filteruri=/mes-pcn/adoperate/*
#\u7528\u6237\u6388\u6743\u8FC7\u6EE4\u8DEF\u5F84
filter.shiro.saadmin.filteruri=/mes-pcn/saoperate/*
################ \u4E91\u914D\u7F6E \uFF08\u4EE5projectName\u4F5C\u4E3A\u5E94\u7528\u540D\uFF09 ################
#\u662F\u5426\u5F00\u542F\u5FAE\u670D
eureka.client.enabled=false
#\uFF08\u53C2\u6570\u914D\u7F6E\uFF09\u6CE8\u518C\u4E2D\u5FC3\u5730\u5740 -\u300B i3plus-ics\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694
eureka.client.service-url.defaultZone=${impp.cluster.regist.center}
#\u533A\u57DF\uFF08\u6E90\u7801\u4E2D\u5305\u542BdefaultZone\uFF0C\u6241\u4EE5\u9ED8\u8BA4\u4F7F\u7528defaultZone\uFF09
#eureka.client.region=estsh
#eureka.client.service-url.estsh:http://192.168.1.20:8000/eureka/,http://192.168.1.20:8001/eureka/
################ \u672C\u673A\u5FAE\u670D\u914D\u7F6E ################
#\u672C\u670D\u52A1\u4E3B\u673Aip\uFF08\u82E5\u591A\u4E2A\u7F51\u5361\uFF0C\u5219\u9700\u8981\u8BBE\u7F6E\u672C\u670D\u52A1ip\uFF09
eureka.instance.ip-address=${impp.server.ip}
#\u672C\u670D\u52A1\u5B9E\u4F8BID
eureka.instance.instance-id=${impp.server.ip}:${server.port}
#\u672C\u670D\u52A1\u4E3B\u673A\u540D
eureka.instance.hostname=${impp.server.ip}
#\u672C\u670D\u52A1\u72B6\u6001\u9875\u9762
eureka.instance.status-page-url=http://${impp.server.ip}:${server.port}/swagger-ui.html
#\u5C06\u81EA\u5DF1\u7684IP\u6CE8\u518C\u5230Eureka Server\u3002\u82E5\u4E0D\u914D\u7F6E\u6216\u8BBE\u7F6E\u4E3Afalse\uFF0C\u8868\u793A\u6CE8\u518C\u5FAE\u670D\u52A1\u6241\u5728\u64CD\u4F5C\u7CFB\u7EDF\u7684hostname\u5230Eureka Server
eureka.instance.prefer-ip-address=false
#\u662F\u5426\u8FDB\u884C\u5065\u5EB7\u68C0\u67E5
eureka.client.healthcheck.enabled=true
################ \u68C0\u6D4B\u673A\u5236 ################
#\u5FC3\u8DF3\u95F4\u9694\u5468\u671F\uFF0C\u5B95\u673A\u9650\u5236\uFF08\u79D2\uFF09\uFF0C30\u79D2\u6CA1\u53CD\u5E94\u89C6\u4E3A\u5B95\u673A
eureka.instance.lease-expiration-duration-in-seconds=30
#\u5FC3\u8DF3\u5468\u671F
eureka.instance.lease-renewal-interval-in-seconds=20
#client\u8FDE\u63A5Eureka\u670D\u52A1\u7AEF\u540E\u7684\u7A7A\u95F2\u7B49\u5F85\u65F6\u95F4\uFF0C\u9ED8\u8BA4\u4E3A30 \u79D2
eureka.client.eureka-connection-idle-timeout-seconds=1
#\u6700\u521D\u590D\u5236\u5B9E\u4F8B\u4FE1\u606F\u5230eureka\u670D\u52A1\u5668\u6241\u9700\u7684\u65F6\u95F4\uFF08s\uFF09\uFF0C\u9ED8\u8BA4\u4E3A40\u79D2
eureka.client.initial-instance-info-replication-interval-seconds=1
#\u95F4\u9694\u591A\u957F\u65F6\u95F4\u518D\u6B21\u590D\u5236\u5B9E\u4F8B\u4FE1\u606F\u5230eureka\u670D\u52A1\u5668\uFF0C\u9ED8\u8BA4\u4E3A30\u79D2
eureka.client.instance-info-replication-interval-seconds=1
#\u4ECEeureka\u670D\u52A1\u5668\u6CE8\u518C\u8868\u4E2D\u83B7\u53D6\u6CE8\u518C\u4FE1\u606F\u7684\u65F6\u95F4\u95F4\u9694\uFF08s\uFF09\uFF0C\u9ED8\u8BA4\u4E3A30\u79D2
eureka.client.registry-fetch-interval-seconds=1
################ \u6253\u5F00feign\u7684\u7194\u65AD ################
feign.hystrix.enabled=true
#\u8BFB\u53D6\u6570\u636E\u65F6\u957F
ribbon.ReadTimeout=10000
#\u8FDE\u63A5\u65F6\u957F
ribbon.ConnectTimeout=10000
#\u91CD\u8BD5
ribbon.maxAutoRetries=2
#\u54CD\u5E94\u8D85\u8FC7\u65F6\u957F\uFF0C\u8FDB\u884C\u7194\u65AD\uFF08\u7194\u65AD\u8D85\u65F6\u9700\u8981\u5927\u4E8E\u8BFB\u53D6\u65F6\u957F\u53CA\u8FDE\u63A5\u65F6\u957F\uFF09
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000
#\u96C6\u7FA4\u540D
eureka.instance.metadata-map.cluster=impp_cluster
################ \u94FE\u8DEF\u8FFD\u8E2A ################
#\u4F7F\u7528web\u65B9\u5F0F\u4F20\u8F93\u4FE1\u606F
spring.zipkin.sender.type=web
#\u94FE\u8DEF\u8FFD\u8E2A\u670D\u52A1\u7684\u5730\u5740
spring.zipkin.base-url=${impp.console.ip}
#\u8FFD\u8E2A\u6DF1\u5EA6\uFF0C\u767E\u5206\u6BD4\uFF0C1\u662F\u5168\u90E8
spring.sleuth.sampler.probability=1.0
# mysql
#impp.write.datasource.type=com.zaxxer.hikari.HikariDataSource
#impp.write.datasource.driver-class-name=com.mysql.jdbc.Driver
#impp.write.datasource.jdbc-url=jdbc:mysql://10.195.88.71:3316/impp_i3_mes?autoReconnect=true&useSSL=false&characterEncoding=utf-8
#impp.write.datasource.username=root
#impp.write.datasource.password=estsh123
#impp.read.datasource.type=com.zaxxer.hikari.HikariDataSource
#impp.read.datasource.driver-class-name=com.mysql.jdbc.Driver
#impp.read.datasource.jdbc-url=jdbc:mysql://10.195.88.71:3316/impp_i3_mes?autoReconnect=true&useSSL=false&characterEncoding=utf-8
#impp.read.datasource.username=root
#impp.read.datasource.password=estsh123
#
###########################\u8BFB\u5199\u5206\u79BB#######################################
spring.shardingsphere.datasource.names=master,slave
##\u5199\u5E93
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name= com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.JdbcUrl=jdbc:mysql://10.195.88.71:3316/impp_i3_mes?autoReconnect=true&useSSL=false&characterEncoding=utf-8
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=estsh123
spring.shardingsphere.datasource.master.maximum-pool-size=400
spring.shardingsphere.datasource.master.minimum-idle=200
spring.shardingsphere.datasource.master.idle-timeout=500000
spring.shardingsphere.datasource.master.connection-timeout=600000
spring.shardingsphere.datasource.master.max-lifetime=7000000
spring.shardingsphere.datasource.master.connection-test-query=select 1
spring.shardingsphere.datasource.master.keep-alive-time=3500000
##\u8BFB\u5E93
spring.shardingsphere.datasource.slave.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave.driver-class-name= com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave.JdbcUrl=jdbc:mysql://10.195.88.71:3316/impp_i3_mes?autoReconnect=true&useSSL=false&characterEncoding=utf-8
spring.shardingsphere.datasource.slave.username=root
spring.shardingsphere.datasource.slave.password=estsh123
spring.shardingsphere.datasource.slave.maximum-pool-size=200
spring.shardingsphere.datasource.slave.minimum-idle=200
spring.shardingsphere.datasource.slave.idle-timeout=500000
spring.shardingsphere.datasource.slave.connection-timeout=600000
spring.shardingsphere.datasource.slave.max-lifetime=7000000
spring.shardingsphere.datasource.slave.connection-test-query=select 1
spring.shardingsphere.datasource.slave.keep-alive-time=3500000
##\u8BFB\u5199\u5206\u79BB\u914D\u7F6E
spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=master
spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=slave
#\u9ED8\u8BA4datasource \u9ED8\u8BA4\u6570\u636E\u6E90\uFF0C\u672A\u5206\u7247\u7684\u8868\u9ED8\u8BA4\u6267\u884C\u5E93
#spring.shardingsphere.sharding.default-data-source-name=ds0
#\u7CFB\u7EDF\u5C5E\u6027\uFF0C\u663E\u793A\u6B63\u5E38\u7684sql\u8BED\u53E5
spring.shardingsphere.props.sql.show=false
#spring.shardingsphere.sharding.tables.mes_equipment_log.actual-data-nodes=ds0.mes_equipment_log_$->{[152,156,300]}
spring.shardingsphere.sharding.tables.mes_equipment_log.actual-data-nodes=ds0.mes_equipment_log_$->{1..300}
spring.shardingsphere.sharding.tables.mes_equipment_log.table-strategy.inline.sharding-column=equip_id
spring.shardingsphere.sharding.tables.mes_equipment_log.table-strategy.inline.algorithm-expression=mes_equipment_log_$->{equip_id}
#spring.shardingsphere.sharding.tables.mes_equipment_log_detail.actual-data-nodes=ds0.mes_equipment_log_detail_$->{[152,156,300]}
spring.shardingsphere.sharding.tables.mes_equipment_log_detail.actual-data-nodes=ds0.mes_equipment_log_detail_$->{1..500}
spring.shardingsphere.sharding.tables.mes_equipment_log_detail.table-strategy.inline.sharding-column=equip_id
spring.shardingsphere.sharding.tables.mes_equipment_log_detail.table-strategy.inline.algorithm-expression=mes_equipment_log_detail_$->{equip_id}
#\u7ED1\u5B9A\u8868
spring.shardingsphere.sharding.binding-tables[0]=mes_equipment_log,mes_equipment_log_detail
#\u4E2D\u822A\u6570\u636E\u6E90
##############\u5B9A\u65F6\u4EFB\u52A1\u6301\u4E45\u5316##############
impp.schedule.open=true
impp.schedule.datasource.driver-class-name=com.mysql.jdbc.Driver
impp.schedule.datasource.jdbc-url=jdbc:mysql://10.195.88.71:3306/impp_i3_schedule?autoReconnect=true&useSSL=false&characterEncoding=utf-8
impp.schedule.datasource.username=root
impp.schedule.datasource.password=estsh123
impp.schedule.datasource.max-connections=20
#\u5B9A\u65F6\u4EFB\u52A1\u5728\u670D\u52A1\u542F\u52A8\u540E\u591A\u5C11\u79D2\u6267\u884C
impp.schedule.start.after-second=20
#\u662F\u5426\u96C6\u7FA4\u90E8\u7F72
impp.schedule.datasource.is-clustered=true
#\u6267\u884C\u68C0\u6D4B\uFF08\u6BEB\u79D2\uFF09\uFF0C\u82E5\u5B95\u673A\u7531\u5176\u4ED6\u5B9A\u65F6\u5668\u6267\u884C
impp.schedule.datasource.cluster-checkin-interval=30000
#\u7EBF\u7A0B\u6570
impp.schedule.thread-count=10
#\u7EBF\u7A0B\u4F18\u5148\u7EA7\uFF081-10\uFF09\u9ED8\u8BA4\u4E3A5
impp.schedule.thread-priority=5
################ \u6570\u636E\u6C60\u8BBE\u7F6E ################
## \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF0C\u9ED8\u8BA4\u662F10
spring.datasource.maximum-pool-size=100
## \u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\u6570\u91CF
spring.datasource.min-idle=10
################ JPA\u8BBE\u7F6E\u8BBE\u7F6E ################
# mysql
spring.jpa.database=MYSQL
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
##Sql-server##
#spring.jpa.database=sql_server
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
##oracle##
#spring.jpa.database=oracle
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
# mysql
#spring.datasource.validationQuery=SELECT 1
##Sql-server##
spring.datasource.validationQuery=SELECT 1
##oracle##
# spring.datasource.validationQuery=SELECT 1 FROM DUAL
#ImprovedNamingStrategy / physical_naming_strategy java\u5C5E\u6027\u6620\u5C04\u5230\u6570\u636E\u5E93\u5B57\u6BB5\u65F6\u547D\u540D\u89C4\u5219
# spring.jpa.properties.hibernate.physical_naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy/org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#\u8868\u5173\u7CFBcreate,create-drop,update,validate
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#\u662F\u5426\u663E\u793Asql
spring.jpa.show-sql=true
################ \u6388\u6743\u914D\u7F6E ################
slm.api.password=4C9479EBEFA6FA6E232EF25EFA49C4D2
slm.app.id=20190513
# \u811A\u672C\u5728\u7EBF\u8C03\u8BD5\u751F\u6210\u7684\u65E5\u5FD7\u6587\u4EF6\u76F8\u5BF9\u8DEF\u5F84\uFF0Cclasspath:xx
pcn.script.logger.path=pluginlogs
pcn.schedule.job=false
server.tomcat.max-threads=300
server.tomcat.max-connections=300
plugin.mainPackage=cn.estsh.i3plus
impp.xxlJob.admin.enable=true
impp.schedule.scheduleType=xxljob
xxl.job.admin.addresses=http://10.195.88.71:10010/xxl-job-admin
### xxl-job, access token
xxl.job.accessToken=
### xxl-job executor appname
#xxl.job.executor.appname=${project.name}
xxl.job.executor.appname=i3mes-pcn
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=10.195.88.71
#xxl.job.executor.ip=
xxl.job.executor.port=12345
### xxl-job executor log-path
xxl.job.executor.logpath=
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=10
xxl.job.basePackage=cn.estsh.i3plus.lac.scheduler.schedulejob
mqtt.host=tcp://10.195.88.71:1883
mqtt.userName=estsh
mqtt.passWord=estsh123
mqtt.qos=1
mqtt.clientId=pcn
mqtt.timeout=10
mqtt.keepalive=30
mqtt.clearSession=true
pcn.mqtt.flag = true
mqtt.topic.list=ABC,ABD,ADE
xxl.job.execute.methodName=executeImppJob,execute

@ -34,9 +34,12 @@ public class MesPackageDataContext extends MesPackageRuleContext implements Seri
@ApiParam("打包结束时间")
private String modifyDatetime;
@ApiParam("业务操作类型")
private String busiType;
public MesPackageDataContext() {}
public MesPackageDataContext(String partNo, String partName, String packageNo, Double qty, Double packSpecQty, String createDatetime, String modifyDatetime) {
public MesPackageDataContext(String partNo, String partName, String packageNo, Double qty, Double packSpecQty, String createDatetime, String modifyDatetime, Integer generateType) {
this.partNo = partNo;
this.partName = partName;
this.packageNo = packageNo;
@ -44,5 +47,12 @@ public class MesPackageDataContext extends MesPackageRuleContext implements Seri
this.packSpecQty = packSpecQty;
this.createDatetime = createDatetime;
this.modifyDatetime = modifyDatetime;
this.generateType = generateType;
}
public MesPackageDataContext qty(Double qty, String modifyDatetime) {
this.qty = qty;
this.modifyDatetime = modifyDatetime;
return this;
}
}

Loading…
Cancel
Save