no message

main
HUOJIN\92525 2025-12-12 21:17:24 +08:00
parent 73b1247ebc
commit 74564b64ab
17 changed files with 350 additions and 268 deletions

View File

@ -9,7 +9,6 @@ import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
/**
@ -318,22 +317,21 @@ public class RestUtil {
* JSONObject a=1&b=2&c=3...&n=n
*/
public static String asUrlVariables(JSONObject variables) {
Map<String, Object> source = variables.getInnerMap();
Iterator<String> it = source.keySet().iterator();
StringBuilder urlVariables = new StringBuilder();
while (it.hasNext()) {
String key = it.next();
String value = "";
Object object = source.get(key);
if (object != null) {
if (!StringUtils.isEmpty(object.toString())) {
value = object.toString();
}
for (Map.Entry<String, Object> entry : variables.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value != null && !StringUtils.isEmpty(value.toString())) {
urlVariables.append("&").append(key).append("=").append(value.toString());
} else {
urlVariables.append("&").append(key).append("=");
}
urlVariables.append("&").append(key).append("=").append(value);
}
// 去掉第一个&
return urlVariables.substring(1);
if (!urlVariables.isEmpty()) {
return urlVariables.substring(1);
}
return urlVariables.toString();
}
}

View File

@ -36,22 +36,11 @@ public interface PointMapper extends BaseMapper<Point> {
/**
*
*
* @param itemId ID
* @param whCode
* @param projects
* @param taskNos
* @param propC1List
* @param propC3List
* @param itemKeyIds
* @param areaCode
* @return List<Point>
*/
List<Point> findPointsWithSkuBatchPo(@Param("itemId") Long itemId,
@Param("whCode") String whCode,
@Param("projects") List<String> projects,
@Param("taskNos") List<String> taskNos,
@Param("propC1List") List<String> propC1List,
@Param("propC3List") List<String> propC3List,
@Param("areaCode") String areaCode);
List<Point> findPointsWithSkuBatchPo(@Param("itemKeyIds") List<Long> itemKeyIds, @Param("areaCode") String areaCode);
// 查询同一巷道占用数量
@Select("SELECT COUNT(id) FROM base_point WHERE col_num = #{colNum} AND layer_num = #{layerNum} AND status = 1")

View File

@ -22,60 +22,12 @@
JOIN base_area ba ON bp1.area_id = ba.id
JOIN base_point bp2 ON bp1.col_num = bp2.col_num
JOIN data_inventory inv ON bp2.id = inv.point_id
WHERE inv.item_id = #{itemId}
AND bp1.status = 0
JOIN base_item_key bik ON inv.item_key_id = bik.id
WHERE bp1.status = 0
AND ba.area_code = #{areaCode}
<choose>
<when test="whCode != null and whCode != ''">
AND inv.wh_code = #{whCode}
</when>
<otherwise>
AND (inv.wh_code IS NULL OR inv.wh_code = '')
</otherwise>
</choose>
<choose>
<when test="projects != null and !projects.isEmpty()">
AND inv.project IN
<foreach collection="projects" item="project" open="(" separator="," close=")">
#{project}
</foreach>
</when>
<otherwise>
AND (inv.project IS NULL OR inv.project = '')
</otherwise>
</choose>
<choose>
<when test="taskNos != null and !taskNos.isEmpty()">
AND inv.task_no IN
<foreach collection="taskNos" item="taskNo" open="(" separator="," close=")">
#{taskNo}
</foreach>
</when>
<otherwise>
AND (inv.task_no IS NULL OR inv.task_no = '')
</otherwise>
</choose>
<choose>
<when test="propC1List != null and !propC1List.isEmpty()">
AND inv.prop_c1 IN
<foreach collection="propC1List" item="propC1" open="(" separator="," close=")">
#{propC1}
</foreach>
</when>
<otherwise>
AND (inv.prop_c1 IS NULL OR inv.prop_c1 = '')
</otherwise>
</choose>
<choose>
<when test="propC3List != null and !propC3List.isEmpty()">
AND inv.prop_c3 IN
<foreach collection="propC3List" item="propC3" open="(" separator="," close=")">
#{propC3}
</foreach>
</when>
<otherwise>
AND (inv.prop_c3 IS NULL OR inv.prop_c3 = '')
</otherwise>
</choose>
AND bik.id IN
<foreach collection="itemKeyIds" item="itemKeyId" open="(" separator="," close=")">
#{itemKeyId}
</foreach>
</select>
</mapper>

View File

@ -50,10 +50,13 @@ public interface IItemService extends IService<Item> {
/**
*
*
* @param material
* @param itemCode
* @param itemName
* @param unit
* @param izActive
* @return Item
*/
Item buildItem(ItemResponse.MaterialDTO material);
Item buildItem(String itemCode, String itemName, String unit, Integer izActive);
/**
*

View File

@ -100,15 +100,10 @@ public interface IPointService extends IService<Point> {
/**
*
*
* @param itemId
* @param whCode
* @param projects
* @param taskNos
* @param propC1List
* @param propC3List
* @param areaCode
* @param itemKeyIds
* @param areaCode
* @return List<Point>
*/
List<Point> findClusterPoint(Long itemId, String whCode, List<String> projects, List<String> taskNos, List<String> propC1List, List<String> propC3List, String areaCode);
List<Point> findClusterPoint(List<Long> itemKeyIds, String areaCode);
}

View File

@ -1,6 +1,8 @@
package org.cpte.modules.base.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
@ -23,7 +25,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
@ -118,7 +119,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
}
@Override
public Item buildItem(ItemResponse.MaterialDTO material) {
public Item buildItem(String itemCode, String itemName, String unit, Integer izActive) {
LoginUser sysUser = null;
try {
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
@ -126,10 +127,10 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
log.error("获取登录用户信息失败");
}
return Item.builder()
.itemCode(material.getItmreF_0())
.itemName(material.getItmdeS1_0())
.unit(material.getStU_0())
.izActive(material.getItmstA_0() == 1 ? 1 : 0)
.itemCode(itemCode)
.itemName(itemName)
.unit(unit)
.izActive(izActive == 1 ? 1 : 0)
.delFlag(0)
.sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode())
.tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds()))
@ -154,10 +155,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
params.put("eDate", eDate.format(DATE_FORMATTER));
// 调用接口获取物料数据
ItemResponse materials = GetProductAddList(params);
if (materials == null || CollectionUtils.isEmpty(materials.getData().getResult().getItem1())) {
return Boolean.TRUE;
}
JSONObject materials = GetProductAddList(params);
// 处理物料数据
return processMaterials(materials);
@ -170,14 +168,10 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
* @param params
* @return ItemResponse
*/
private ItemResponse GetProductAddList(JSONObject params) {
private JSONObject GetProductAddList(JSONObject params) {
try {
String url = openApiMapper.getRequestUrl(GeneralConstant.SYNC_ITEM).getOriginUrl();
ResponseEntity<JSONObject> response = RestUtil.getNative(url, params, null);
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return response.getBody().toJavaObject(ItemResponse.class);
}
return null;
return RestUtil.get(url, params, null);
} catch (Exception e) {
throw new RuntimeException("获取物料数据失败", e);
}
@ -189,9 +183,29 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
* @param materials
* @return Boolean
*/
private Boolean processMaterials(ItemResponse materials) {
private Boolean processMaterials(JSONObject materials) {
try {
List<String> itemCodes = materials.getData().getResult().getItem1().stream().map(ItemResponse.MaterialDTO::getItmreF_0).distinct().toList();
JSONObject data = materials.getJSONObject("data");
if (data == null) {
return Boolean.TRUE;
}
JSONObject result = data.getJSONObject("result");
if (result == null) {
return Boolean.TRUE;
}
JSONArray item1array = result.getJSONArray("item1");
if (CollectionUtils.isEmpty(item1array)) {
return Boolean.TRUE;
}
List<String> itemCodes = new ArrayList<>();
for (int i = 0; i < item1array.size(); i++) {
// 获取每个 LinkedHashMap
JSONObject item = item1array.getJSONObject(i);
// 获取 itmreF_0 的值
String itemCode = item.getString("itmreF_0");
itemCodes.add(itemCode);
}
Map<String, Item> itemMap = queryByItemCodesToMap(itemCodes);
//批量处理
@ -199,9 +213,12 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
List<Item> updateItems = new ArrayList<>();
Set<String> processedItemCodes = new HashSet<>();
for (ItemResponse.MaterialDTO material : materials.getData().getResult().getItem1()) {
String itemCode = material.getItmreF_0();
for (int i = 0; i < item1array.size(); i++) {
JSONObject item = item1array.getJSONObject(i);
String itemCode = item.getString("itmreF_0");
String itemName = item.getString("itmdeS1_0");
String unit = item.getString("stU_0");
Integer izActive = item.getInteger("itmstA_0");
// 去重处理
if (processedItemCodes.contains(itemCode)) {
continue;
@ -211,18 +228,18 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
// 判断新增或更新
Item existingItem = itemMap.get(itemCode);
if (existingItem == null) {
Item newItem = buildItem(material);
Item newItem = buildItem(itemCode, itemName, unit, izActive);
insertItems.add(newItem);
} else {
// 只有字段变化时才更新
if (isItemChanged(existingItem, material)) {
updateItemFromMaterial(existingItem, material);
if (isItemChanged(existingItem, itemName, unit, izActive)) {
updateItemFromMaterial(existingItem, itemName, unit, izActive);
updateItems.add(existingItem);
}
}
log.info("处理物料: {}", itemCode);
}
// 批量保存
if (CollectionUtils.isNotEmpty(insertItems)) {
batchUtil.saveBatchItem(insertItems);
@ -241,19 +258,19 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
/**
*
*/
private boolean isItemChanged(Item item, ItemResponse.MaterialDTO material) {
return !Objects.equals(item.getItemName(), material.getItmdeS1_0()) ||
!Objects.equals(item.getUnit(), material.getStU_0()) ||
!Objects.equals(item.getIzActive(), material.getItmstA_0() == 1 ? 1 : 0);
private boolean isItemChanged(Item item, String itemName, String unit, Integer izActive) {
return !Objects.equals(item.getItemName(), itemName) ||
!Objects.equals(item.getUnit(), unit) ||
!Objects.equals(item.getIzActive(), izActive == 1 ? 1 : 0);
}
/**
*
*/
private void updateItemFromMaterial(Item item, ItemResponse.MaterialDTO material) {
item.setItemName(material.getItmdeS1_0());
item.setUnit(material.getStU_0());
item.setIzActive(material.getItmstA_0() == 1 ? 1 : 0);
private void updateItemFromMaterial(Item item, String itemName, String unit, Integer izActive) {
item.setItemName(itemName);
item.setUnit(unit);
item.setIzActive(izActive == 1 ? 1 : 0);
// 添加更新时间戳
item.setUpdateTime(new Date());
}

View File

@ -149,8 +149,11 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
}
@Override
public List<Point> findClusterPoint(Long itemId, String whCode, List<String> projects, List<String> taskNos, List<String> propC1List, List<String> propC3List, String areaCode) {
return this.baseMapper.findPointsWithSkuBatchPo(itemId, whCode,projects,taskNos, propC1List, propC3List, areaCode);
public List<Point> findClusterPoint(List<Long> itemKeyIds, String areaCode) {
if (CollectionUtils.isEmpty(itemKeyIds)) {
return Collections.emptyList();
}
return this.baseMapper.findPointsWithSkuBatchPo(itemKeyIds, areaCode);
}
}

View File

@ -12,12 +12,12 @@ public interface GeneralConstant {
/**
*
*/
final String SWMS_SUCCESS_CODE = "200";
final String SMOM_SUCCESS_CODE = "200";
/**
*
*/
final String SWMS_FAIL_CODE = "500";
final String SMOM_FAIL_CODE = "500";
/**
*

View File

@ -18,7 +18,9 @@ public enum TaskStatusEnum {
COMPLETED(4, "已完成"),
CANCELLED(5, "已取消"),
CLOSED(5, "已关闭"),
CANCELLED(6, "已取消"),
;
/**

View File

@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
@ -107,14 +108,15 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
}
//项目号、任务号、批次号、外部库存状态
List<String> projects = asnDetails.stream().map(AsnDetail::getProject).filter(StringUtils::isNotBlank).distinct().toList();
List<String> taskNos = asnDetails.stream().map(AsnDetail::getTaskNo).filter(StringUtils::isNotBlank).distinct().toList();
List<String> projectList = asnDetails.stream().map(AsnDetail::getProject).filter(StringUtils::isNotBlank).distinct().toList();
List<String> taskNoList = asnDetails.stream().map(AsnDetail::getTaskNo).filter(StringUtils::isNotBlank).distinct().toList();
List<String> propC1List = asnDetails.stream().map(AsnDetail::getPropC1).filter(StringUtils::isNotBlank).distinct().toList();
List<String> propC3List = asnDetails.stream().map(AsnDetail::getPropC3).filter(StringUtils::isNotBlank).distinct().toList();
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeys(Collections.singletonList(asnDetail.getItemId()), Collections.singletonList(asn.getWhCode()), projectList, taskNoList, propC1List, propC3List);
//通过算法获取目标点位
Point dstPoint = allocatePoint(asn.getOrderType(), asnDetail.getItemId(), asn.getWhCode(), projects, taskNos, propC1List, propC3List, station);
Point dstPoint = allocatePoint(asn.getOrderType(), itemKeys, station);
//锁定目标库位
pointService.bindPoint(dstPoint);
@ -126,33 +128,28 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
/**
*
*
* @param orderType
* @param itemId
* @param whCode
* @param projects
* @param taskNos
* @param propC1List
* @param propC3List
* @param station
* @param orderType
* @param itemKeys
* @param station
* @return
*/
private Point allocatePoint(Integer orderType, Long itemId, String whCode, List<String> projects, List<String> taskNos, List<String> propC1List, List<String> propC3List, Point station) {
private Point allocatePoint(Integer orderType, List<ItemKey> itemKeys, Point station) {
String areaCode = "";
if (Set.of(0, 1, 2, 3).contains(orderType)) {
areaCode = AreaTypeEnum.CPCCQ.getValue();
} else {
areaCode = AreaTypeEnum.MJCCQ.getValue();
}
//1.优先寻找同物料/同仓库/同项目号/同任务号/同批次/同外部库存状态
List<Point> availablePoints = pointService.findClusterPoint(itemId, whCode, projects, taskNos, propC1List, propC3List, areaCode);
List<Long> itemKeyIds = itemKeys.stream().map(ItemKey::getId).toList();
List<Point> availablePoints = pointService.findClusterPoint(itemKeyIds, areaCode);
if (CollectionUtils.isEmpty(availablePoints)) {
//2.获取所有可用库位
availablePoints = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), areaCode);
}
List<PointScore> scoredPoints = availablePoints.stream()
.map(point -> clusterPointScore(point, station, itemId, whCode, projects, taskNos, propC1List, propC3List))
.map(point -> clusterPointScore(point, station, itemKeys))
.sorted(Comparator.comparing(PointScore::getScore).reversed())
.toList();
@ -171,7 +168,7 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
/**
*
*/
private PointScore clusterPointScore(Point point, Point station, Long itemId, String whCode, List<String> projects, List<String> taskNos, List<String> propC1List, List<String> propC3List) {
private PointScore clusterPointScore(Point point, Point station, List<ItemKey> itemKeys) {
double totalScore;
// 1. 距离评分 - 考虑从入库口到库位的距离
@ -187,7 +184,7 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
double balanceScore = calculateBalanceScore(point) * 0.1; // 权重10%
// 5. 物料聚集潜力评分 - 新增
double clusterPotentialScore = calculateClusterPotentialScore(point, itemId, whCode, projects, taskNos, propC1List, propC3List) * 0.2; // 权重20%
double clusterPotentialScore = calculateClusterPotentialScore(point, itemKeys) * 0.2; // 权重20%
totalScore = distanceScore + channelDepthScore + channelScore + balanceScore + clusterPotentialScore;
log.info("【{}】库位总分:{} - 距离评分: {} - 通道深度策略评分: {} - 通道类型评分: {} - 均衡评分: {} - 物料聚集评分: {}", point.getPointCode(), totalScore, distanceScore, channelDepthScore, channelScore, balanceScore, clusterPotentialScore);
@ -258,10 +255,12 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
*
*
*/
private double calculateClusterPotentialScore(Point point, Long itemId, String whCode,
List<String> projects, List<String> taskNos,
List<String> propC1List,
List<String> propC3List) {
/**
*
*
*
*/
private double calculateClusterPotentialScore(Point point, List<ItemKey> itemKeys) {
double score = 0.0;
// 检查同一巷道相邻库位
@ -278,45 +277,56 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
List<Inventory> neighbors = inventoryMapper.findNeighborPoints(
point.getColNum(), point.getLayerNum(), String.valueOf(minDepth), String.valueOf(maxDepth));
if (CollectionUtils.isEmpty(neighbors)) {
return score;
}
List<Long> itemKeyIds = neighbors.stream().map(Inventory::getItemKeyId).distinct().toList();
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeyByIds(itemKeyIds);
List<ItemKey> exitItemKeys = itemKeyMapper.queryItemKeyByIds(itemKeyIds);
for (ItemKey neighbor : itemKeys) {
if (neighbor.getItemId() != null) {
// 为每个ItemKey计算匹配度并累加分数
for (ItemKey itemKey : itemKeys) {
Long itemId = itemKey.getItemId();
String whCode = itemKey.getWhCode();
String project = itemKey.getProject();
String taskNo = itemKey.getTaskNo();
String propC1 = itemKey.getPropC1();
String propC3 = itemKey.getPropC3();
for (ItemKey neighbor : exitItemKeys) {
// 同SKU加分
if (neighbor.getItemId().equals(itemId)) {
score += 20;
// 同仓库代码加分
if (whCode != null && whCode.equals(neighbor.getWhCode())) {
score += 10;
}
// 同批次号加分
if (CollectionUtils.isNotEmpty(propC1List) &&
StringUtils.isNotBlank(neighbor.getPropC1()) &&
propC1List.contains(neighbor.getPropC1())) {
score += 15;
}
// 同批次号加分
if (StringUtils.isNotBlank(propC1) &&
StringUtils.isNotBlank(neighbor.getPropC1()) &&
propC1.equals(neighbor.getPropC1())) {
score += 10;
}
// 同项目号加分
if (CollectionUtils.isNotEmpty(projects) &&
if (StringUtils.isNotBlank(project) &&
StringUtils.isNotBlank(neighbor.getProject()) &&
projects.contains(neighbor.getProject())) {
project.equals(neighbor.getProject())) {
score += 10;
}
// 同任务号加分
if (CollectionUtils.isNotEmpty(taskNos) &&
if (StringUtils.isNotBlank(taskNo) &&
StringUtils.isNotBlank(neighbor.getTaskNo()) &&
taskNos.contains(neighbor.getTaskNo())) {
taskNo.equals(neighbor.getTaskNo())) {
score += 10;
}
// 同外部库存状态加分
if (CollectionUtils.isNotEmpty(propC3List) &&
if (StringUtils.isNotBlank(propC3) &&
StringUtils.isNotBlank(neighbor.getPropC3()) &&
propC3List.contains(neighbor.getPropC3())) {
propC3.equals(neighbor.getPropC3())) {
score += 5;
}
}

View File

@ -3,7 +3,6 @@ package org.cpte.modules.receive.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@ -19,6 +18,7 @@ import org.cpte.modules.base.service.IPointService;
import org.cpte.modules.base.service.IStockService;
import org.cpte.modules.constant.GeneralConstant;
import org.cpte.modules.constant.enums.AsnStatusEnum;
import org.cpte.modules.constant.enums.PickStatusEnum;
import org.cpte.modules.inventory.entity.Inventory;
import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.inventory.service.IInventoryService;
@ -46,6 +46,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@ -340,7 +341,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
task.setName("");
task.setInfkey(asn.getNo());
task.setIsDelete(false);
task.setLastUpdateDate(DateUtils.format(new Date()));
task.setLastUpdateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
SaiWmsRequest.ParameterValue1 parameterValue1 = new SaiWmsRequest.ParameterValue1();
parameterValue1.setValue(List.of(task));
@ -366,7 +367,11 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
// 检查接口开关, 未开启则返回
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
updateAsnDetailResponse(asn, GeneralConstant.SWMS_FAIL_CODE, "接口未开启");
updateAsnDetailResponse(asn, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
return;
}
if (PickStatusEnum.CLOSED.getValue().equals(asn.getStatus())) {
return;
}
try {
@ -378,11 +383,11 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
String authorization = authInfo.get("authorization");
String json = receiveCallbackJson(asn, stock, ticket);
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK).getOriginUrl();
JSONObject jsonObject = swmsLoginUtil.sendSWMSResponse(json, url, authorization);
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
String code = validateResponse(jsonObject);
updateAsnDetailResponse(asn, code, jsonObject.toJSONString());
} catch (Exception e) {
updateAsnDetailResponse(asn, GeneralConstant.SWMS_FAIL_CODE, e.getMessage());
updateAsnDetailResponse(asn, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
}
}
@ -402,7 +407,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
throw new RuntimeException("数据格式错误缺少Result字段");
}
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
return jsonArray.isEmpty() ? GeneralConstant.SWMS_SUCCESS_CODE : GeneralConstant.SWMS_FAIL_CODE;
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
}
/**
@ -413,28 +418,21 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
* @param message
*/
private void updateAsnDetailResponse(Asn asn, String code, String message) {
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
if (asn != null) {
if (AsnStatusEnum.CLOSED.getValue().equals(asn.getStatus())) {
return;
}
if (GeneralConstant.SWMS_SUCCESS_CODE.equals(code)) {
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asn.getId());
for (AsnDetail asnDetail : asnDetails) {
asnDetail.setStatus(AsnStatusEnum.CLOSED.getValue());
updateToAsnDetail.add(asnDetail);
}
}
asn.setResMessage(message);
asn.setResTime(new Date());
this.baseMapper.updateById(asn);
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
asnDetailMapper.updateById(updateToAsnDetail);
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asn.getId());
for (AsnDetail asnDetail : asnDetails) {
asnDetail.setStatus(AsnStatusEnum.CLOSED.getValue());
updateToAsnDetail.add(asnDetail);
}
}
asn.setResMessage(message);
asn.setResTime(new Date());
this.baseMapper.updateById(asn);
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
asnDetailMapper.updateById(updateToAsnDetail);
}
}
/**

View File

@ -30,18 +30,23 @@ public class SaiWmsRequest {
@Data
public static class Task {
//任务号
@JsonProperty("No")
private String no;
//单号
@JsonProperty("OrderNo")
private String orderNo;
//任务状态
@JsonProperty("State")
private Integer state;
//托盘
@JsonProperty("LPN")
private String lpn;
//唯一值用于 错误日志
@JsonProperty("ErpKey")
private String erpKey;
@ -51,6 +56,7 @@ public class SaiWmsRequest {
@JsonProperty("Name")
private String name;
//唯一值用于 错误日志
@JsonProperty("Infkey")
private String infkey;
@ -60,6 +66,9 @@ public class SaiWmsRequest {
@JsonProperty("LastUpdateDate")
private String lastUpdateDate;
@JsonProperty("ShipmentFeedbackDetail")
private List<ShipmentFeedbackDetail> shipmentFeedbackDetails;
}
@Data
@ -83,4 +92,60 @@ public class SaiWmsRequest {
}
@Data
public static class ShipmentFeedbackDetail {
//行号
@JsonProperty("LineNo")
private String lineNo;
//托盘
@JsonProperty("Lpn")
private String lpn;
//数量
@JsonProperty("Qty")
private Integer qty;
//true整托false拆托
@JsonProperty("IsTakeDown")
private Boolean isTakeDown;
//项目号
@JsonProperty("Project")
private String project;
//任务号
@JsonProperty("TaskNo")
private String TaskNo;
//批次
@JsonProperty("LotAtt04")
private String lotAtt04;
//库存状态
@JsonProperty("LotAtt010")
private String lotAtt010;
//唯一值用于 错误日志
@JsonProperty("ErpKey")
private String erpKey;
//
@JsonProperty("Code")
private String code;
@JsonProperty("Name")
private String name;
@JsonProperty("Infkey")
private String infkey;
@JsonProperty("IsDelete")
private Boolean isDelete;
@JsonProperty("LastUpdateDate")
private String lastUpdateDate;
}
}

View File

@ -12,6 +12,7 @@ import org.cpte.modules.base.service.IPointService;
import org.cpte.modules.base.service.IStockService;
import org.cpte.modules.constant.GeneralConstant;
import org.cpte.modules.constant.enums.*;
import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.mapper.AsnMapper;
@ -42,6 +43,8 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
@Autowired
private PickMapper pickMapper;
private InventoryMapper inventoryMapper;
@Autowired
private IItemService itemService;
@ -63,7 +66,7 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
@Autowired
private BatchUtil batchUtil;
private void validateParams(InboundRequest inboundRequest) {
private Stock validateParams(InboundRequest inboundRequest) {
if (StringUtils.isBlank(inboundRequest.getNo())) {
throw new RuntimeException("任务号(No)必填");
}
@ -121,6 +124,13 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
throw new RuntimeException("明细中物料只能是同一种");
}
//获取明细托盘
String lpn = lpns.iterator().next();
Stock stock = iStockService.validateStock(lpn);
if (inventoryMapper.queryByStockId(stock.getId()) != null) {
throw new RuntimeException("【" + lpn + "】托盘已入库");
}
return stock;
}
@ -128,7 +138,7 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
@Transactional(rollbackFor = Exception.class)
public void inBoundTask(InboundRequest inboundRequest) {
//验证参数
validateParams(inboundRequest);
Stock stock = validateParams(inboundRequest);
//验证任务号
String no = inboundRequest.getNo();
@ -159,10 +169,6 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
srcPoint = iPointService.validatePoint(srcPointCode);
}
//托盘
String stockCode = detail.get(0).getLpn();
Stock stock = iStockService.validateStock(stockCode);
//获取输送线工作台点位,均衡分配点位任务-轮询方式
Point dstPoint = iPointService.getWorkStationPoint(null, AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX);

View File

@ -148,21 +148,6 @@ public class PickDetail implements Serializable {
@Excel(name = "备注", width = 15)
@Schema(description = "备注")
private java.lang.String description;
/**
*
*/
@Excel(name = "返回报文", width = 15)
@Schema(description = "返回报文")
private java.lang.String resMessage;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "回传时间")
private java.util.Date resTime;
/**
* ID

View File

@ -139,6 +139,7 @@ public class Task implements Serializable {
/**
* 0,1
* truefalse
*/
@Excel(name = "是否整托", width = 15)
@Schema(description = "是否整托")
@ -159,6 +160,22 @@ public class Task implements Serializable {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "完成时间")
private java.util.Date completeTime;
/**
*
*/
@Excel(name = "返回报文", width = 15)
@Schema(description = "返回报文")
private java.lang.String resMessage;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "回传时间")
private java.util.Date resTime;
/**
*
*/

View File

@ -1,6 +1,7 @@
package org.cpte.modules.shipping.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@ -21,6 +22,7 @@ import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.inventory.service.IInventoryService;
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
import org.cpte.modules.saiWms.request.OutboundRequest;
import org.cpte.modules.saiWms.request.SaiWmsRequest;
import org.cpte.modules.serialNumber.PickSerialNumberRule;
import org.cpte.modules.shipping.entity.Pick;
import org.cpte.modules.shipping.entity.PickDetail;
@ -34,6 +36,8 @@ import org.cpte.modules.shipping.vo.InventoryGroupKey;
import org.cpte.modules.shipping.vo.InventoryScore;
import org.cpte.modules.utils.BatchUtil;
import org.cpte.modules.utils.BigDecimalUtil;
import org.cpte.modules.utils.HttpPostUtil;
import org.cpte.modules.utils.SwmsLoginUtil;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.base.service.BaseCommonService;
@ -46,6 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@ -85,6 +90,8 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
@Autowired
private IInventoryLogService iInventoryLogService;
@Autowired
private SwmsLoginUtil swmsLoginUtil;
@Autowired
private BaseCommonService baseCommonService;
@Autowired
private BatchUtil batchUtils;
@ -425,7 +432,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
pickDetail.getPropC1(),
pickDetail.getPropC3()
);
ItemKey itemKey=inventoryGroupMap.get(groupKey);
ItemKey itemKey = inventoryGroupMap.get(groupKey);
List<Inventory> matchedInventories = inventoryMap.get(itemKey.getId());
if (CollectionUtils.isEmpty(matchedInventories)) {
errorMsgSet.add(String.format("物料【%s】无匹配库存物料ID:%s批次:%s库存状态:%s仓库:%s",
@ -835,84 +842,119 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
/**
* JSON
*/
private String pickTaskCallbackJson(Pick pick, PickDetail pickDetail, Task task, Integer state) {
JSONObject jsonObject = new JSONObject(true);
jsonObject.put("No", pick.getNo());
jsonObject.put("OrderNo", pick.getThirdOrderNo());
jsonObject.put("State", state);
jsonObject.put("LineNo", pickDetail.getLineNo());
jsonObject.put("Lpn", task.getStockCode());
jsonObject.put("Qty", task.getPlanQty());
jsonObject.put("IsTakeDown", task.getIzAll());
jsonObject.put("Project", pickDetail.getProject());
jsonObject.put("TaskNo", pickDetail.getTaskNo());
jsonObject.put("LotAtt04", pickDetail.getPropC1());
jsonObject.put("LotAtt010", pickDetail.getPropC3());
return jsonObject.toJSONString();
private String pickTaskCallbackJson(Pick pick, PickDetail pickDetail, Task task, Integer state, String ticket) {
SaiWmsRequest.Task taskReq = new SaiWmsRequest.Task();
taskReq.setNo(pick.getNo());
taskReq.setOrderNo(pick.getThirdOrderNo());
taskReq.setState(state);
SaiWmsRequest.ShipmentFeedbackDetail shipmentFeedbackDetail = new SaiWmsRequest.ShipmentFeedbackDetail();
shipmentFeedbackDetail.setLineNo(String.valueOf(pickDetail.getLineNo()));
shipmentFeedbackDetail.setLpn(task.getStockCode());
shipmentFeedbackDetail.setQty(task.getPlanQty().intValue());
shipmentFeedbackDetail.setIsTakeDown(task.getIzAll() == 0);
shipmentFeedbackDetail.setProject(pickDetail.getProject());
shipmentFeedbackDetail.setTaskNo(pickDetail.getTaskNo());
shipmentFeedbackDetail.setLotAtt04(pickDetail.getPropC1());
shipmentFeedbackDetail.setLotAtt010(pickDetail.getPropC3());
shipmentFeedbackDetail.setErpKey(pick.getNo());
shipmentFeedbackDetail.setIsDelete(false);
String lastUpdateDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
shipmentFeedbackDetail.setLastUpdateDate(lastUpdateDate);
taskReq.setShipmentFeedbackDetails(List.of(shipmentFeedbackDetail));
taskReq.setErpKey(pick.getNo());
taskReq.setInfkey(pick.getNo());
taskReq.setIsDelete(false);
taskReq.setLastUpdateDate(lastUpdateDate);
SaiWmsRequest.ParameterValue1 parameterValue1 = new SaiWmsRequest.ParameterValue1();
parameterValue1.setValue(List.of(taskReq));
SaiWmsRequest.ParameterValue2 parameterValue2 = new SaiWmsRequest.ParameterValue2();
parameterValue2.setValue(1);
SaiWmsRequest.Context context = new SaiWmsRequest.Context();
context.setInvOrgId(1);
context.setTicket(ticket);
SaiWmsRequest saiWmsRequest = new SaiWmsRequest();
saiWmsRequest.setApiType("SmomWebApiController");
saiWmsRequest.setParameters(List.of(parameterValue1, parameterValue2));
saiWmsRequest.setMethod("OutboundTaskCallbackInterface");
saiWmsRequest.setContext(context);
return JSON.toJSONString(saiWmsRequest);
}
@Override
public void pickTaskCallback(Pick pick, PickDetail pickDetail, Task task, Integer state) {
// 检查接口开关, 未开启则返回
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
updatePickDetailResponse(pickDetail, "接口未开启", Boolean.FALSE);
updatePickDetailResponse(pickDetail,task, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
return;
}
if (PickStatusEnum.CLOSED.getValue().equals(pickDetail.getStatus())) {
if (TaskStatusEnum.CLOSED.getValue().equals(task.getTaskStatus())) {
return;
}
String json = pickTaskCallbackJson(pick, pickDetail, task, state);
String url = openApiMapper.getRequestUrl(GeneralConstant.OUTBOUND_CALLBACK).getOriginUrl();
log.info("出库回传请求报文:{}", json);
Boolean Success = null;
String Message = null;
try {
//String result = HttpPostUtil.sendPostReq(url, json);
String result = "{\n" +
" \"Success\": true,\n" +
" \"Message\": \"出库回传成功\"\n" +
"}";
if (org.apache.commons.lang3.StringUtils.isEmpty(result)) {
Message = "出库回传返回信息:接口调用失败";
throw new RuntimeException(Message);
Map<String, String> authInfo = swmsLoginUtil.Login();
if (authInfo == null || authInfo.isEmpty()) {
throw new RuntimeException("登录认证信息为空");
}
JSONObject resulObject = JSON.parseObject(result);
if (resulObject == null) {
Message = "出库回传返回信息:接口返回为空";
throw new RuntimeException(Message);
}
Success = resulObject.getBoolean("Success");
Message = resulObject.getString("Message");
if (!Success) {
throw new RuntimeException("出库回传返回信息:" + Message);
}
updatePickDetailResponse(pickDetail, Message, Success);
String ticket = authInfo.get("Ticket");
String authorization = authInfo.get("authorization");
String json = pickTaskCallbackJson(pick, pickDetail, task, state, ticket);
String url = openApiMapper.getRequestUrl(GeneralConstant.OUTBOUND_CALLBACK).getOriginUrl();
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
String code = validateResponse(jsonObject);
updatePickDetailResponse(pickDetail,task, code, jsonObject.toJSONString());
} catch (Exception e) {
updatePickDetailResponse(pickDetail, e.getMessage(), Boolean.FALSE);
updatePickDetailResponse(pickDetail,task, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
}
}
/**
*
*
* @param jsonObject
* @return
*/
private String validateResponse(JSONObject jsonObject) {
JSONObject data = jsonObject.getJSONObject("data");
if (data == null) {
throw new RuntimeException("数据格式错误缺少data字段");
}
JSONObject Result = data.getJSONObject("Result");
if (Result == null) {
throw new RuntimeException("数据格式错误缺少Result字段");
}
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
}
/**
*
*
* @param pickDetail
* @param message
* @param task
* @param message
*/
private void updatePickDetailResponse(PickDetail pickDetail, String message, Boolean Success) {
if (pickDetail != null) {
if (Success) {
private void updatePickDetailResponse(PickDetail pickDetail,Task task, String code, String message) {
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
if(PickStatusEnum.PICKED.getValue().equals(pickDetail.getStatus())){
pickDetail.setStatus(PickStatusEnum.CLOSED.getValue());
pickDetailMapper.updateById(pickDetail);
}
pickDetail.setResMessage(message);
pickDetail.setResTime(new Date());
pickDetailMapper.updateById(pickDetail);
task.setTaskStatus(TaskStatusEnum.CLOSED.getValue());
}
task.setResMessage(message);
task.setResTime(new Date());
taskMapper.updateById(task);
}
}

View File

@ -62,7 +62,7 @@ public class SwmsLoginUtil {
String authorization = headerObj.getString("defaultValue");
String json = loginJson();
JSONObject resultObject = sendSWMSLoginResponse(json, url, authorization);
JSONObject resultObject = sendSMOMLoginResponse(json, url, authorization);
JSONObject data = resultObject.getJSONObject("data");
if (data == null) {
@ -83,7 +83,7 @@ public class SwmsLoginUtil {
return map;
}
public JSONObject sendSWMSLoginResponse(String json, String url, String authorization) {
public JSONObject sendSMOMLoginResponse(String json, String url, String authorization) {
// 发送请求
String result = HttpPostUtil.sendPostReq(url, json, authorization);
log.info("请求路径:{} - 请求参数:{} - 响应结果:{}", url, json, result);
@ -104,13 +104,13 @@ public class SwmsLoginUtil {
String code = data.getString("code");
String message = data.getString("message");
if (!GeneralConstant.SWMS_SUCCESS_CODE.equals(code)) {
if (!GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
throw new RuntimeException(message);
}
return resultObject;
}
public JSONObject sendSWMSResponse(String json, String url, String authorization) {
public JSONObject sendSMOMResponse(String json, String url, String authorization) {
// 发送请求
String result = HttpPostUtil.sendPostReq(url, json, authorization);
log.info("请求路径:{} - 请求参数:{} - 响应结果:{}", url, json, result);
@ -126,7 +126,7 @@ public class SwmsLoginUtil {
String code = resultObject.getString("code");
String message = resultObject.getString("message");
if (!GeneralConstant.SWMS_SUCCESS_CODE.equals(code)) {
if (!GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
throw new RuntimeException(message);
}