|
|
|
@ -7,6 +7,9 @@ import com.gaotao.common.utils.AgvClientUtil; |
|
|
|
import com.gaotao.common.utils.HttpClientUtil; |
|
|
|
import com.gaotao.common.utils.IfsClientUtil; |
|
|
|
import com.gaotao.common.utils.ResponseData; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
|
|
|
import java.util.Map; |
|
|
|
import com.gaotao.modules.handlingunit.entity.HandlingUnit; |
|
|
|
import com.gaotao.modules.handlingunit.entity.HandlingUnitDetail; |
|
|
|
import com.gaotao.modules.handlingunit.service.HandlingUnitDetailService; |
|
|
|
@ -35,6 +38,7 @@ import java.util.Date; |
|
|
|
import java.util.List; |
|
|
|
import java.util.UUID; |
|
|
|
|
|
|
|
@Slf4j |
|
|
|
@Service |
|
|
|
public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implements PoService { |
|
|
|
@Autowired |
|
|
|
@ -56,79 +60,208 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen |
|
|
|
@Autowired |
|
|
|
private IfsClientUtil ifsClientUtil; |
|
|
|
|
|
|
|
@Value("${custom.ifs-url}") |
|
|
|
private String ifsUrl; |
|
|
|
@Value("${custom.wcs-url}") |
|
|
|
private String wcsUrl; |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<PurchaseOrderDto> getPoList(PurchaseOrderDto purchaseOrder) { |
|
|
|
List<PurchaseOrderDto> list = new ArrayList<>(); |
|
|
|
PurchaseOrderDto po = new PurchaseOrderDto(); |
|
|
|
po.setWdr("1-1"); |
|
|
|
po.setPartNo("22090897" ); |
|
|
|
po.setUnit("卷" ); |
|
|
|
po.setDesc("PC模 230*230 UE PET" ); |
|
|
|
po.setQty(new BigDecimal(100)); |
|
|
|
po.setRecvQty(new BigDecimal(50)); |
|
|
|
po.setThisRecvQty(new BigDecimal(50)); |
|
|
|
po.setMakeDate("制单日期" ); |
|
|
|
po.setExpireDate("到期日期" ); |
|
|
|
po.setBatchNumber("批次号" ); |
|
|
|
po.setNeedHandlingUnit("N" ); |
|
|
|
po.setNeedCheck("N" ); |
|
|
|
list.add(po); |
|
|
|
|
|
|
|
PurchaseOrderDto po1 = new PurchaseOrderDto(); |
|
|
|
po1.setWdr("1-2"); |
|
|
|
po1.setPartNo("22090231" ); |
|
|
|
po1.setUnit("卷" ); |
|
|
|
po1.setDesc("PC模 230*230 UE PET" ); |
|
|
|
po1.setQty(new BigDecimal(100)); |
|
|
|
po1.setRecvQty(new BigDecimal(50)); |
|
|
|
po1.setThisRecvQty(new BigDecimal(50)); |
|
|
|
po1.setMakeDate("制单日期" ); |
|
|
|
po1.setExpireDate("到期日期" ); |
|
|
|
po1.setBatchNumber("批次号" ); |
|
|
|
po1.setNeedHandlingUnit("Y" ); |
|
|
|
po1.setNeedCheck("Y" ); |
|
|
|
list.add(po1); |
|
|
|
try { |
|
|
|
// 调用IFS接口获取PO数据 |
|
|
|
JSONObject ifsRequest = new JSONObject(); |
|
|
|
ifsRequest.put("ifsDBName", "IFSTEST"); |
|
|
|
ifsRequest.put("domainUserID", "CCL_WMS"); |
|
|
|
ifsRequest.put("ifsSiteID", "55"); |
|
|
|
ifsRequest.put("poNumber", purchaseOrder.getPoNumber()); |
|
|
|
ifsRequest.put("partNo", purchaseOrder.getPartNo()); |
|
|
|
ifsRequest.put("status", "RELEASED"); // 只获取已发布的PO |
|
|
|
|
|
|
|
log.info("调用IFS获取PO数据,请求参数: {}", ifsRequest); |
|
|
|
|
|
|
|
// 使用IfsClientUtil获取PO数据 |
|
|
|
// 注意:这里应该根据实际的IFS接口调用方式进行调整 |
|
|
|
// 如果需要获取多行数据,可能需要先获取PO头,再获取行数据 |
|
|
|
//ResponseData ifsResponse = ifsClientUtil.getPurchaseOrder("po00001"); |
|
|
|
|
|
|
|
ResponseData ifsResponse = testIfsClientUtil(); // 测试用,实际使用时替换为上面的调用 |
|
|
|
if (ifsResponse != null && "SUCCESS".equals(ifsResponse.getCode())) { |
|
|
|
// 解析IFS返回的PO数据 |
|
|
|
return parseIFSPOData(ifsResponse.getObj()); |
|
|
|
} else { |
|
|
|
log.error("从IFS获取PO数据失败: {}", ifsResponse); |
|
|
|
throw new XJException("从IFS获取PO数据失败"); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("获取PO列表异常: {}", e.getMessage()); |
|
|
|
throw new XJException("获取PO列表失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private ResponseData testIfsClientUtil() { |
|
|
|
ResponseData ifsResponse = new ResponseData(); |
|
|
|
ifsResponse.setSuccess(true); |
|
|
|
ifsResponse.setCode("SUCCESS"); |
|
|
|
ifsResponse.setMsg("模拟IFS采购订单成功"); |
|
|
|
|
|
|
|
java.util.List<java.util.Map<String, Object>> list = new java.util.ArrayList<>(); |
|
|
|
|
|
|
|
java.util.Map<String, Object> po1 = new java.util.HashMap<>(); |
|
|
|
po1.put("site", "1"); |
|
|
|
po1.put("poNumber", "PO00001"); |
|
|
|
po1.put("orderNo", "ORD00001"); |
|
|
|
po1.put("lineNo", "1"); |
|
|
|
po1.put("relNo", "R001"); |
|
|
|
po1.put("wdr", "WDR001"); |
|
|
|
po1.put("partNo", "MAT001"); |
|
|
|
po1.put("partDesc", "物料A"); |
|
|
|
po1.put("unit", "PCS"); |
|
|
|
po1.put("orderQty", new java.math.BigDecimal(100)); |
|
|
|
po1.put("receivedQty", new java.math.BigDecimal(20)); |
|
|
|
po1.put("unitPerBox", new java.math.BigDecimal(10)); |
|
|
|
po1.put("needHandlingUnit", "Y"); |
|
|
|
po1.put("needCheck", "N"); |
|
|
|
po1.put("needPallet", "Y"); |
|
|
|
po1.put("warehouseType", "AUTO"); |
|
|
|
po1.put("workshopFlag", "N"); |
|
|
|
po1.put("cuttingFlag", "N"); |
|
|
|
|
|
|
|
PurchaseOrderDto po2 = new PurchaseOrderDto(); |
|
|
|
po2.setWdr("1-3"); |
|
|
|
po2.setPartNo("45133221" ); |
|
|
|
po2.setUnit("罐" ); |
|
|
|
po2.setDesc("UV油墨 5KG/罐 金利宝" ); |
|
|
|
po2.setQty(new BigDecimal(100)); |
|
|
|
po2.setRecvQty(new BigDecimal(50)); |
|
|
|
po2.setThisRecvQty(new BigDecimal(50)); |
|
|
|
po2.setMakeDate("制单日期" ); |
|
|
|
po2.setExpireDate("到期日期" ); |
|
|
|
po2.setBatchNumber("批次号" ); |
|
|
|
java.util.Map<String, Object> po2 = new java.util.HashMap<>(); |
|
|
|
po2.put("site", "2"); |
|
|
|
po2.put("poNumber", "PO00002"); |
|
|
|
po2.put("orderNo", "ORD00002"); |
|
|
|
po2.put("lineNo", "2"); |
|
|
|
po2.put("relNo", "R002"); |
|
|
|
po2.put("wdr", "WDR002"); |
|
|
|
po2.put("partNo", "MAT002"); |
|
|
|
po2.put("partDesc", "物料B"); |
|
|
|
po2.put("unit", "BOX"); |
|
|
|
po2.put("orderQty", new java.math.BigDecimal(50)); |
|
|
|
po2.put("receivedQty", new java.math.BigDecimal(10)); |
|
|
|
po2.put("unitPerBox", new java.math.BigDecimal(5)); |
|
|
|
po2.put("needHandlingUnit", "N"); |
|
|
|
po2.put("needCheck", "Y"); |
|
|
|
po2.put("needPallet", "N"); |
|
|
|
po2.put("warehouseType", "MANUAL"); |
|
|
|
po2.put("workshopFlag", "Y"); |
|
|
|
po2.put("cuttingFlag", "Y"); |
|
|
|
|
|
|
|
list.add(po1); |
|
|
|
list.add(po2); |
|
|
|
|
|
|
|
PurchaseOrderDto po3 = new PurchaseOrderDto(); |
|
|
|
po3.setWdr("1-4"); |
|
|
|
po3.setPartNo("398090897" ); |
|
|
|
po3.setUnit("卷" ); |
|
|
|
po3.setDesc("UV油墨 5KG/罐 金利宝" ); |
|
|
|
po3.setQty(new BigDecimal(100)); |
|
|
|
po3.setRecvQty(new BigDecimal(50)); |
|
|
|
po3.setThisRecvQty(new BigDecimal(50)); |
|
|
|
po3.setMakeDate("制单日期" ); |
|
|
|
po3.setExpireDate("到期日期" ); |
|
|
|
po3.setBatchNumber("批次号" ); |
|
|
|
list.add(po3); |
|
|
|
|
|
|
|
PurchaseOrderDto po4 = new PurchaseOrderDto(); |
|
|
|
po4.setWdr("1-5"); |
|
|
|
po4.setPartNo("132090897" ); |
|
|
|
po4.setUnit("卷" ); |
|
|
|
po4.setDesc("PC模 230*230 UE PET" ); |
|
|
|
po4.setQty(new BigDecimal(100)); |
|
|
|
po4.setRecvQty(new BigDecimal(50)); |
|
|
|
po4.setThisRecvQty(new BigDecimal(50)); |
|
|
|
po4.setMakeDate("制单日期" ); |
|
|
|
po4.setExpireDate("到期日期" ); |
|
|
|
po4.setBatchNumber("批次号" ); |
|
|
|
list.add(po4); |
|
|
|
|
|
|
|
return list; |
|
|
|
ifsResponse.setObj(list); |
|
|
|
ifsResponse.setCount(list.size()); |
|
|
|
return ifsResponse; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 解析IFS返回的PO数据 |
|
|
|
*/ |
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
private List<PurchaseOrderDto> parseIFSPOData(Object ifsData) { |
|
|
|
List<PurchaseOrderDto> poList = new ArrayList<>(); |
|
|
|
try { |
|
|
|
if (ifsData == null) { |
|
|
|
log.warn("IFS返回数据为空"); |
|
|
|
return poList; |
|
|
|
} |
|
|
|
// 假设IFS返回的是JSON数组格式 |
|
|
|
if (ifsData instanceof List<?> rawList) { |
|
|
|
for (Object item : rawList) { |
|
|
|
if (item instanceof Map) { |
|
|
|
Map<String, Object> poData = (Map<String, Object>) item; |
|
|
|
PurchaseOrderDto po = createPurchaseOrderDto(poData); |
|
|
|
poList.add(po); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
log.warn("IFS返回数据格式不正确,期望List类型,实际类型: {}", ifsData.getClass().getSimpleName()); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("解析IFS PO数据完成,共{}条记录", poList.size()); |
|
|
|
return poList; |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("解析IFS PO数据异常: {}", e.getMessage()); |
|
|
|
throw new XJException("解析PO数据失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 创建PurchaseOrderDto对象 |
|
|
|
*/ |
|
|
|
private PurchaseOrderDto createPurchaseOrderDto(Map<String, Object> poData) { |
|
|
|
PurchaseOrderDto po = new PurchaseOrderDto(); |
|
|
|
try { |
|
|
|
// 映射IFS字段到PO实体 - 安全地处理null值 |
|
|
|
po.setSite(getStringValue(poData, "site")); |
|
|
|
po.setPoNumber(getStringValue(poData, "poNumber")); |
|
|
|
po.setOrderNo(getStringValue(poData, "orderNo")); |
|
|
|
po.setLineNo(getStringValue(poData, "lineNo")); |
|
|
|
po.setRelNo(getStringValue(poData, "relNo")); |
|
|
|
po.setWdr(getStringValue(poData, "wdr")); |
|
|
|
po.setPartNo(getStringValue(poData, "partNo")); |
|
|
|
po.setDesc(getStringValue(poData, "partDesc")); |
|
|
|
po.setUnit(getStringValue(poData, "unit")); |
|
|
|
|
|
|
|
// 数量信息 - 安全地处理数值转换 |
|
|
|
po.setQty(getBigDecimalValue(poData, "orderQty", BigDecimal.ZERO)); |
|
|
|
po.setRecvQty(getBigDecimalValue(poData, "receivedQty", BigDecimal.ZERO)); |
|
|
|
po.setThisRecvQty(po.getQty().subtract(po.getRecvQty())); // 待接收数量 |
|
|
|
po.setUnitPerBox(getBigDecimalValue(poData, "unitPerBox", BigDecimal.ONE)); |
|
|
|
|
|
|
|
// 业务控制字段(从物料主数据获取) |
|
|
|
po.setNeedHandlingUnit(getStringValue(poData, "needHandlingUnit", "N")); |
|
|
|
po.setNeedCheck(getStringValue(poData, "needCheck", "N")); |
|
|
|
po.setNeedPallet(getStringValue(poData, "needPallet", "N")); |
|
|
|
po.setWarehouseType(getStringValue(poData, "warehouseType", "MANUAL")); |
|
|
|
po.setWorkshopFlag(getStringValue(poData, "workshopFlag", "N")); |
|
|
|
po.setCuttingFlag(getStringValue(poData, "cuttingFlag", "N")); |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("创建PurchaseOrderDto对象异常: {}", e.getMessage()); |
|
|
|
throw new RuntimeException("创建PO对象失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
return po; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 安全地获取字符串值 |
|
|
|
*/ |
|
|
|
private String getStringValue(Map<String, Object> map, String key) { |
|
|
|
return getStringValue(map, key, null); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 安全地获取字符串值,带默认值 |
|
|
|
*/ |
|
|
|
private String getStringValue(Map<String, Object> map, String key, String defaultValue) { |
|
|
|
Object value = map.get(key); |
|
|
|
if (value == null) { |
|
|
|
return defaultValue; |
|
|
|
} |
|
|
|
return String.valueOf(value); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 安全地获取BigDecimal值 |
|
|
|
*/ |
|
|
|
private BigDecimal getBigDecimalValue(Map<String, Object> map, String key, BigDecimal defaultValue) { |
|
|
|
Object value = map.get(key); |
|
|
|
if (value == null) { |
|
|
|
return defaultValue; |
|
|
|
} |
|
|
|
try { |
|
|
|
if (value instanceof BigDecimal) { |
|
|
|
return (BigDecimal) value; |
|
|
|
} else if (value instanceof Number) { |
|
|
|
return new BigDecimal(value.toString()); |
|
|
|
} else { |
|
|
|
return new BigDecimal(String.valueOf(value)); |
|
|
|
} |
|
|
|
} catch (NumberFormatException e) { |
|
|
|
log.warn("无法转换{}为BigDecimal,使用默认值: {}", value, defaultValue); |
|
|
|
return defaultValue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@ -168,11 +301,25 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen |
|
|
|
handlingUnit.setUnitType("BOX"); |
|
|
|
handlingUnit.setUnitTypeDb("BOX"); |
|
|
|
handlingUnit.setPartNo(inData.getPartNo()); |
|
|
|
|
|
|
|
// RFID识别需要的关键字段 |
|
|
|
handlingUnit.setOrderNo(inData.getOrderNo()); |
|
|
|
handlingUnit.setLineNo(inData.getLineNo()); |
|
|
|
handlingUnit.setRelNo(inData.getRelNo()); |
|
|
|
handlingUnit.setReceiptNo(inData.getReceiptNo()); |
|
|
|
//handlingUnit.setPartDesc(inData.getPartDesc()); |
|
|
|
handlingUnit.setQty(BigDecimal.valueOf(huInfo.getPerQty())); |
|
|
|
handlingUnit.setBatchNo(inData.getBatchNo()); |
|
|
|
handlingUnit.setLocationId(inData.getLocationNo()); |
|
|
|
handlingUnit.setWarehouseId(transHeader.getWarehouseId()); |
|
|
|
|
|
|
|
// 设置制造日期和自动计算失效日期 |
|
|
|
if (inData.getManufactureDate() != null) { |
|
|
|
handlingUnit.setManufactureDate(inData.getManufactureDate()); |
|
|
|
// 自动计算失效日期 |
|
|
|
Date expiredDate = calculateExpiredDate(inData.getManufactureDate(), inData.getPartNo()); |
|
|
|
handlingUnit.setExpiredDate(expiredDate); |
|
|
|
} |
|
|
|
//handlingUnit.setWdr(inData.getWdr()); |
|
|
|
//handlingUnit.setAvailabilityControlId(inData.getAvailabilityControlId()); |
|
|
|
handlingUnit.setStatus("ACTIVE"); |
|
|
|
@ -240,14 +387,11 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen |
|
|
|
.eq(TransHeader::getTransNo, transHeader.getTransNo()) |
|
|
|
.update(); |
|
|
|
} |
|
|
|
// 业务处理成功后,调用IFS和WCS接口 |
|
|
|
/*JSONObject jsonObject = new JSONObject(); |
|
|
|
jsonObject.put("ifsDBName", "IFSTEST"); |
|
|
|
jsonObject.put("domainUserID", "CCL_WMS"); |
|
|
|
jsonObject.put("ifsSiteID", "55"); |
|
|
|
ResponseData ifsData = ifsClientUtil.receivePurchaseOrder(jsonObject);*/ |
|
|
|
// 直接入库,此时如果是立库,需call AGV小车 |
|
|
|
//ResponseData wcsData = agvClientUtil.createTask("", null, null, null); |
|
|
|
// 处理托盘和AGV调度逻辑 |
|
|
|
handlePalletAndAGVDispatch(inData, transHeader); |
|
|
|
|
|
|
|
// 同步到IFS |
|
|
|
syncToIFS(inData, transHeader); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new XJException("采购入库失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
@ -273,4 +417,252 @@ public class PoServiceImpl extends ServiceImpl<PoMapper, PurchaseOrder> implemen |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据制造日期和物料编码计算失效日期 |
|
|
|
*/ |
|
|
|
private Date calculateExpiredDate(Date manufactureDate, String partNo) { |
|
|
|
if (manufactureDate == null || partNo == null) { |
|
|
|
log.warn("制造日期或物料编码为空,无法计算失效日期"); |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 获取物料的保质期天数(实际应该从物料主数据表查询) |
|
|
|
int shelfLifeDays = getShelfLifeDays(partNo); |
|
|
|
|
|
|
|
// 计算失效日期 |
|
|
|
java.util.Calendar calendar = java.util.Calendar.getInstance(); |
|
|
|
calendar.setTime(manufactureDate); |
|
|
|
calendar.add(java.util.Calendar.DAY_OF_YEAR, shelfLifeDays); |
|
|
|
|
|
|
|
Date expiredDate = calendar.getTime(); |
|
|
|
log.info("计算失效日期 - 物料: {}, 制造日期: {}, 保质期: {}天, 失效日期: {}", |
|
|
|
partNo, manufactureDate, shelfLifeDays, expiredDate); |
|
|
|
|
|
|
|
return expiredDate; |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("计算失效日期异常,物料: {}, 制造日期: {}, 错误: {}", partNo, manufactureDate, e.getMessage()); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取物料的保质期天数 |
|
|
|
*/ |
|
|
|
private int getShelfLifeDays(String partNo) { |
|
|
|
// 根据物料编码规则判断保质期 |
|
|
|
// 实际应该从数据库的物料主数据表中查询 |
|
|
|
if (partNo == null || partNo.trim().isEmpty()) { |
|
|
|
return 365; // 默认1年 |
|
|
|
} |
|
|
|
|
|
|
|
String partNoUpper = partNo.toUpperCase(); |
|
|
|
|
|
|
|
if (partNoUpper.contains("UV") || partNoUpper.contains("INK")) { |
|
|
|
return 180; // UV油墨6个月 |
|
|
|
} else if (partNoUpper.contains("PET")) { |
|
|
|
return 730; // PET材料2年 |
|
|
|
} else if (partNoUpper.contains("CHEMICAL") || partNoUpper.contains("CHEM")) { |
|
|
|
return 90; // 化学品3个月 |
|
|
|
} |
|
|
|
|
|
|
|
return 365; // 默认1年 |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 处理托盘和AGV调度逻辑 |
|
|
|
*/ |
|
|
|
private void handlePalletAndAGVDispatch(TransDetailDto inData, TransHeader transHeader) { |
|
|
|
try { |
|
|
|
// 判断是否需要托盘管理(立库需要托盘) |
|
|
|
if ("AUTO".equals(inData.getWarehouseType()) && "Y".equals(inData.getNeedPallet())) { |
|
|
|
// 创建托盘并装载处理单元 |
|
|
|
String palletId = createPalletForHandlingUnits(inData, transHeader); |
|
|
|
|
|
|
|
// 调用WCS接口调度四向小车 |
|
|
|
if (palletId != null) { |
|
|
|
callWCSForPallet(palletId, inData.getLocationNo()); |
|
|
|
} |
|
|
|
} |
|
|
|
// 判断是否需要AGV调度(去车间或分切) |
|
|
|
else if ("Y".equals(inData.getWorkshopFlag()) || "Y".equals(inData.getCuttingFlag())) { |
|
|
|
// 调用AGV运输到车间或分切区域 |
|
|
|
callAGVDispatch(inData, transHeader); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("处理托盘和AGV调度异常: {}", e.getMessage()); |
|
|
|
// 不抛出异常,避免影响主流程 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 为处理单元创建托盘 |
|
|
|
*/ |
|
|
|
private String createPalletForHandlingUnits(TransDetailDto inData, TransHeader transHeader) { |
|
|
|
try { |
|
|
|
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal(); |
|
|
|
|
|
|
|
// 生成托盘ID |
|
|
|
String palletId = generateHandlingUnitId(inData.getSite(), "PALLET"); |
|
|
|
|
|
|
|
// 创建托盘处理单元 |
|
|
|
HandlingUnit pallet = new HandlingUnit(); |
|
|
|
pallet.setUnitId(palletId); |
|
|
|
pallet.setSite(inData.getSite()); |
|
|
|
pallet.setUnitType("PALLET"); |
|
|
|
pallet.setUnitTypeDb("PALLET"); |
|
|
|
pallet.setPartNo("PALLET"); // 托盘本身的物料编码 |
|
|
|
pallet.setQty(inData.getTransQty()); // 托盘承载的总数量 |
|
|
|
pallet.setLocationId(inData.getLocationNo()); |
|
|
|
pallet.setWarehouseId(transHeader.getWarehouseId()); |
|
|
|
pallet.setStatus("ACTIVE"); |
|
|
|
pallet.setStatusDb("A"); |
|
|
|
pallet.setFreezeFlag("N"); |
|
|
|
pallet.setMergedFlag("N"); |
|
|
|
pallet.setInStockFlag("Y"); |
|
|
|
pallet.setOrderRef1(inData.getPoNo()); |
|
|
|
pallet.setCreatedDate(new Date()); |
|
|
|
pallet.setCreatedBy(currentUser.getUserDisplay()); |
|
|
|
pallet.setModifiedDate(new Date()); |
|
|
|
pallet.setModifiedBy(currentUser.getUserDisplay()); |
|
|
|
pallet.setRemark("PO接收创建托盘"); |
|
|
|
pallet.setSourceType("PO_RECEIVE_PALLET"); |
|
|
|
pallet.setSourceRef(transHeader.getTransNo()); |
|
|
|
pallet.setBarCode(palletId); |
|
|
|
pallet.setQrCode("PALLET:" + palletId); |
|
|
|
|
|
|
|
// 保存托盘 |
|
|
|
handlingUnitService.save(pallet); |
|
|
|
|
|
|
|
log.info("托盘创建成功,托盘ID: {}, PO号: {}", palletId, inData.getPoNo()); |
|
|
|
return palletId; |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("创建托盘失败: {}", e.getMessage()); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 调用WCS接口调度四向小车 |
|
|
|
*/ |
|
|
|
private boolean callWCSForPallet(String palletId, String targetLocation) { |
|
|
|
try { |
|
|
|
JSONObject wcsRequest = new JSONObject(); |
|
|
|
wcsRequest.put("taskType", "PALLET_TRANSPORT"); |
|
|
|
wcsRequest.put("palletId", palletId); |
|
|
|
wcsRequest.put("targetLocation", targetLocation); |
|
|
|
wcsRequest.put("vehicleType", "FOUR_WAY_SHUTTLE"); |
|
|
|
wcsRequest.put("priority", "NORMAL"); |
|
|
|
wcsRequest.put("timestamp", System.currentTimeMillis()); |
|
|
|
|
|
|
|
log.info("调用WCS接口,托盘ID: {}, 目标库位: {}", palletId, targetLocation); |
|
|
|
|
|
|
|
ResponseData response = HttpClientUtil.doPostByRaw(wcsUrl + "/pallet/transport", wcsRequest); |
|
|
|
|
|
|
|
if (response != null && "SUCCESS".equals(response.getCode())) { |
|
|
|
log.info("WCS调度成功,托盘ID: {}", palletId); |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
log.error("WCS调度失败,托盘ID: {}, 响应: {}", palletId, response); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("调用WCS接口异常,托盘ID: {}, 错误: {}", palletId, e.getMessage()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 调用AGV调度 |
|
|
|
*/ |
|
|
|
private boolean callAGVDispatch(TransDetailDto inData, TransHeader transHeader) { |
|
|
|
try { |
|
|
|
String taskType; |
|
|
|
String targetArea; |
|
|
|
|
|
|
|
if ("Y".equals(inData.getWorkshopFlag())) { |
|
|
|
taskType = "WORKSHOP_TRANSPORT"; |
|
|
|
targetArea = "WORKSHOP"; |
|
|
|
} else if ("Y".equals(inData.getCuttingFlag())) { |
|
|
|
taskType = "CUTTING_TRANSPORT"; |
|
|
|
targetArea = "CUTTING_AREA"; |
|
|
|
} else { |
|
|
|
log.warn("未知的AGV调度类型,PO号: {}", inData.getPoNo()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
log.info("调用AGV调度,PO号: {}, 任务类型: {}", inData.getPoNo(), taskType); |
|
|
|
|
|
|
|
// 使用AgvClientUtil创建AGV任务 |
|
|
|
String taskId = "PO_" + inData.getPoNo() + "_" + System.currentTimeMillis(); |
|
|
|
List<String> targets = new ArrayList<>(); |
|
|
|
targets.add(targetArea); |
|
|
|
|
|
|
|
ResponseData response = agvClientUtil.createTask( |
|
|
|
taskId, |
|
|
|
targets, |
|
|
|
taskType, |
|
|
|
1 // 普通优先级 |
|
|
|
); |
|
|
|
|
|
|
|
if (response != null && "SUCCESS".equals(response.getCode())) { |
|
|
|
log.info("AGV调度成功,PO号: {}", inData.getPoNo()); |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
log.error("AGV调度失败,PO号: {}, 响应: {}", inData.getPoNo(), response); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("AGV调度异常,PO号: {}, 错误: {}", inData.getPoNo(), e.getMessage()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 同步到IFS |
|
|
|
*/ |
|
|
|
private void syncToIFS(TransDetailDto inData, TransHeader transHeader) { |
|
|
|
try { |
|
|
|
JSONObject ifsRequest = new JSONObject(); |
|
|
|
ifsRequest.put("ifsDBName", "IFSTEST"); |
|
|
|
ifsRequest.put("domainUserID", "CCL_WMS"); |
|
|
|
ifsRequest.put("ifsSiteID", "55"); |
|
|
|
ifsRequest.put("poNumber", inData.getPoNo()); |
|
|
|
ifsRequest.put("orderNo", inData.getOrderNo()); |
|
|
|
ifsRequest.put("lineNo", inData.getLineNo()); |
|
|
|
ifsRequest.put("relNo", inData.getRelNo()); |
|
|
|
ifsRequest.put("partNo", inData.getPartNo()); |
|
|
|
ifsRequest.put("receivedQty", inData.getTransQty()); |
|
|
|
ifsRequest.put("batchNo", inData.getBatchNo()); |
|
|
|
ifsRequest.put("locationId", inData.getLocationNo()); |
|
|
|
ifsRequest.put("transNo", transHeader.getTransNo()); |
|
|
|
ifsRequest.put("receiveDate", new Date()); |
|
|
|
|
|
|
|
if (inData.getManufactureDate() != null) { |
|
|
|
ifsRequest.put("manufactureDate", inData.getManufactureDate()); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("同步接收记录到IFS,PO号: {}", inData.getPoNo()); |
|
|
|
|
|
|
|
// 使用IfsClientUtil同步接收记录 |
|
|
|
ResponseData ifsResponse = ifsClientUtil.receivePurchaseOrder(ifsRequest); |
|
|
|
|
|
|
|
if (ifsResponse != null && "SUCCESS".equals(ifsResponse.getCode())) { |
|
|
|
log.info("IFS同步成功,PO号: {}", inData.getPoNo()); |
|
|
|
} else { |
|
|
|
log.error("IFS同步失败,PO号: {}, 响应: {}", inData.getPoNo(), ifsResponse); |
|
|
|
// 可以考虑记录同步失败的记录,后续重试 |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("IFS同步异常,PO号: {}, 错误: {}", inData.getPoNo(), e.getMessage()); |
|
|
|
// 不抛出异常,避免影响主流程 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |