7 changed files with 788 additions and 27 deletions
-
1.gitignore
-
27src/main/java/com/gaotao/modules/inboundNotification/config/AsyncConfig.java
-
210src/main/java/com/gaotao/modules/otherOutbound/controller/OtherOutboundController.java
-
101src/main/java/com/gaotao/modules/otherOutbound/dao/OtherOutboundMapper.java
-
71src/main/java/com/gaotao/modules/otherOutbound/service/OtherOutboundService.java
-
265src/main/java/com/gaotao/modules/otherOutbound/service/impl/OtherOutboundServiceImpl.java
-
140src/main/resources/mapper/otherOutbound/OtherOutboundMapper.xml
@ -1,27 +0,0 @@ |
|||||
package com.gaotao.modules.inboundNotification.config; |
|
||||
|
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.context.annotation.Configuration; |
|
||||
import org.springframework.scheduling.annotation.EnableAsync; |
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
|
||||
|
|
||||
import java.util.concurrent.Executor; |
|
||||
|
|
||||
/** |
|
||||
* 异步任务配置 |
|
||||
*/ |
|
||||
@Configuration |
|
||||
@EnableAsync |
|
||||
public class AsyncConfig { |
|
||||
|
|
||||
@Bean("taskExecutor") |
|
||||
public Executor taskExecutor() { |
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
|
||||
executor.setCorePoolSize(5); |
|
||||
executor.setMaxPoolSize(10); |
|
||||
executor.setQueueCapacity(100); |
|
||||
executor.setThreadNamePrefix("InboundAsync-"); |
|
||||
executor.initialize(); |
|
||||
return executor; |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,210 @@ |
|||||
|
package com.gaotao.modules.otherOutbound.controller; |
||||
|
|
||||
|
import com.gaotao.common.utils.R; |
||||
|
import com.gaotao.modules.otherOutbound.service.OtherOutboundService; |
||||
|
import com.gaotao.modules.sys.controller.AbstractController; |
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 其他出库控制器 |
||||
|
* 数据来源:return_notification_head/detail表(类型为其他出库) |
||||
|
*/ |
||||
|
@RestController |
||||
|
@RequestMapping("/otherOutbound") |
||||
|
@Api(tags = "其他出库管理") |
||||
|
public class OtherOutboundController extends AbstractController { |
||||
|
|
||||
|
@Autowired |
||||
|
private OtherOutboundService otherOutboundService; |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单列表 |
||||
|
* 数据来源:return_notification_head表,类型为其他出库 |
||||
|
*/ |
||||
|
@PostMapping("/getOutboundList") |
||||
|
@ApiOperation("获取其他出库单列表") |
||||
|
public R getOutboundList(@RequestBody Map<String, Object> params) { |
||||
|
try { |
||||
|
String site = (String) params.get("site"); |
||||
|
String warehouseId = (String) params.get("warehouseId"); |
||||
|
String searchCode = (String) params.get("searchCode"); |
||||
|
String status = (String) params.get("status"); |
||||
|
|
||||
|
if (warehouseId == null || warehouseId.trim().isEmpty()) { |
||||
|
return R.error("仓库ID不能为空"); |
||||
|
} |
||||
|
|
||||
|
// 默认状态为待出库 |
||||
|
if (status == null || status.trim().isEmpty()) { |
||||
|
status = "待出库"; |
||||
|
} |
||||
|
|
||||
|
logger.info("获取其他出库单列表,站点: {}, 仓库: {}, 搜索码: {}, 状态: {}", |
||||
|
site, warehouseId, searchCode, status); |
||||
|
|
||||
|
List<Map<String, Object>> list = otherOutboundService.getOutboundList( |
||||
|
site, warehouseId, searchCode, status); |
||||
|
|
||||
|
return R.ok().put("data", list); |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库单列表失败", e); |
||||
|
return R.error("获取数据失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单详情 |
||||
|
*/ |
||||
|
@PostMapping("/getOutboundDetails") |
||||
|
@ApiOperation("获取其他出库单详情") |
||||
|
public R getOutboundDetails(@RequestBody Map<String, Object> params) { |
||||
|
try { |
||||
|
String outboundNo = (String) params.get("outboundNo"); |
||||
|
String buNo = (String) params.get("buNo"); |
||||
|
String warehouseId = (String) params.get("warehouseId"); |
||||
|
String site = (String) params.get("site"); |
||||
|
|
||||
|
if (outboundNo == null || outboundNo.trim().isEmpty()) { |
||||
|
return R.error("出库单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (warehouseId == null || warehouseId.trim().isEmpty()) { |
||||
|
return R.error("仓库ID不能为空"); |
||||
|
} |
||||
|
|
||||
|
Map<String, Object> result = otherOutboundService.getOutboundDetails( |
||||
|
outboundNo, buNo, warehouseId, site); |
||||
|
|
||||
|
if (result == null || result.isEmpty()) { |
||||
|
return R.error("未找到出库单详情"); |
||||
|
} |
||||
|
|
||||
|
return R.ok().put("data", result); |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库单详情失败", e); |
||||
|
return R.error("获取详情失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 验证标签与其他出库单是否匹配,并检查库存 |
||||
|
*/ |
||||
|
@PostMapping("/validateLabelWithOutbound") |
||||
|
@ApiOperation("验证标签与出库单匹配") |
||||
|
public R validateLabelWithOutbound(@RequestBody Map<String, Object> params) { |
||||
|
try { |
||||
|
String labelCode = (String) params.get("labelCode"); |
||||
|
String outboundNo = (String) params.get("outboundNo"); |
||||
|
String warehouseId = (String) params.get("warehouseId"); |
||||
|
String site = (String) params.get("site"); |
||||
|
String buNo = (String) params.get("buNo"); |
||||
|
|
||||
|
if (labelCode == null || labelCode.trim().isEmpty()) { |
||||
|
return R.error("标签条码不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (outboundNo == null || outboundNo.trim().isEmpty()) { |
||||
|
return R.error("出库单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
Map<String, Object> result = otherOutboundService.validateLabelWithOutbound( |
||||
|
labelCode, outboundNo, warehouseId, site, buNo); |
||||
|
|
||||
|
return R.ok().put("data", result); |
||||
|
} catch (Exception e) { |
||||
|
logger.error("其他出库标签验证失败", e); |
||||
|
return R.error(e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 确认其他出库 |
||||
|
* 系统逻辑: |
||||
|
* 1. 更新库存表中的标签状态 |
||||
|
* 2. 更改return_notification_head表中的单据状态为"已出库" |
||||
|
* 3. 生成WMS出库记录:Transheader... |
||||
|
* 4. 异步调用ERP接口回传数据 |
||||
|
*/ |
||||
|
@PostMapping("/confirmOtherOutbound") |
||||
|
@ApiOperation("确认其他出库") |
||||
|
public R confirmOtherOutbound(@RequestBody Map<String, Object> params) { |
||||
|
try { |
||||
|
String site = (String) params.get("site"); |
||||
|
String buNo = (String) params.get("buNo"); |
||||
|
String outboundNo = (String) params.get("outboundNo"); |
||||
|
String warehouseId = (String) params.get("warehouseId"); |
||||
|
List<Map<String, Object>> labels = (List<Map<String, Object>>) params.get("labels"); |
||||
|
|
||||
|
if (outboundNo == null || outboundNo.trim().isEmpty()) { |
||||
|
return R.error("出库单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (warehouseId == null || warehouseId.trim().isEmpty()) { |
||||
|
return R.error("仓库ID不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (labels == null || labels.isEmpty()) { |
||||
|
return R.error("标签列表不能为空"); |
||||
|
} |
||||
|
|
||||
|
// 验证标签数据完整性 |
||||
|
for (Map<String, Object> label : labels) { |
||||
|
String labelCode = (String) label.get("labelCode"); |
||||
|
if (labelCode == null || labelCode.trim().isEmpty()) { |
||||
|
return R.error("标签条码不能为空"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
boolean success = otherOutboundService.confirmOtherOutbound( |
||||
|
site, buNo, outboundNo, warehouseId, labels); |
||||
|
|
||||
|
if (success) { |
||||
|
return R.ok("出库成功"); |
||||
|
} else { |
||||
|
return R.error("出库失败"); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
logger.error("其他出库失败", e); |
||||
|
return R.error("出库失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单物料清单 |
||||
|
* 根据site、buNo、outboundNo从return_notification_detail表获取物料信息 |
||||
|
*/ |
||||
|
@PostMapping("/getMaterialList") |
||||
|
@ApiOperation("获取物料清单") |
||||
|
public R getMaterialList(@RequestBody Map<String, Object> params) { |
||||
|
try { |
||||
|
String site = (String) params.get("site"); |
||||
|
String buNo = (String) params.get("buNo"); |
||||
|
String outboundNo = (String) params.get("outboundNo"); |
||||
|
|
||||
|
if (site == null || site.trim().isEmpty()) { |
||||
|
return R.error("站点不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (buNo == null || buNo.trim().isEmpty()) { |
||||
|
return R.error("业务单元不能为空"); |
||||
|
} |
||||
|
|
||||
|
if (outboundNo == null || outboundNo.trim().isEmpty()) { |
||||
|
return R.error("出库单号不能为空"); |
||||
|
} |
||||
|
|
||||
|
List<Map<String, Object>> materialList = otherOutboundService.getMaterialList(site, buNo, outboundNo); |
||||
|
|
||||
|
return R.ok().put("data", materialList); |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库物料清单失败", e); |
||||
|
return R.error("获取物料清单失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
package com.gaotao.modules.otherOutbound.dao; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
import org.apache.ibatis.annotations.Mapper; |
||||
|
import org.apache.ibatis.annotations.Param; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Mapper |
||||
|
public interface OtherOutboundMapper extends BaseMapper { |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单列表 |
||||
|
* @param site 站点 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param searchCode 搜索条件 |
||||
|
* @param status 状态 |
||||
|
* @return 出库单列表 |
||||
|
*/ |
||||
|
List<Map<String, Object>> getOutboundList(@Param("site") String site, |
||||
|
@Param("warehouseId") String warehouseId, |
||||
|
@Param("searchCode") String searchCode, |
||||
|
@Param("status") String status); |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单详情 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param buNo 业务单元 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param site 站点 |
||||
|
* @return 出库单详情 |
||||
|
*/ |
||||
|
Map<String, Object> getOutboundDetails(@Param("outboundNo") String outboundNo, |
||||
|
@Param("buNo") String buNo, |
||||
|
@Param("warehouseId") String warehouseId, |
||||
|
@Param("site") String site); |
||||
|
|
||||
|
/** |
||||
|
* 验证标签与其他出库单是否匹配 |
||||
|
* @param labelCode 标签条码 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @return 标签信息 |
||||
|
*/ |
||||
|
Map<String, Object> validateLabelWithOutbound(@Param("labelCode") String labelCode, |
||||
|
@Param("outboundNo") String outboundNo, |
||||
|
@Param("warehouseId") String warehouseId, |
||||
|
@Param("site") String site, |
||||
|
@Param("buNo") String buNo); |
||||
|
|
||||
|
/** |
||||
|
* 更新库存表中的标签状态 |
||||
|
* @param labelCodes 标签条码列表 |
||||
|
* @param status 状态 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @return 更新行数 |
||||
|
*/ |
||||
|
int updateInventoryStatus(@Param("labelCodes") List<String> labelCodes, |
||||
|
@Param("status") String status, |
||||
|
@Param("site") String site, |
||||
|
@Param("buNo") String buNo); |
||||
|
|
||||
|
/** |
||||
|
* 更新出库单状态 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param status 状态 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @return 更新行数 |
||||
|
*/ |
||||
|
int updateOutboundStatus(@Param("outboundNo") String outboundNo, |
||||
|
@Param("status") String status, |
||||
|
@Param("site") String site, |
||||
|
@Param("buNo") String buNo); |
||||
|
|
||||
|
/** |
||||
|
* 检查出库单的所有标签是否都已出库 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @return 统计信息:totalLabels总标签数,outboundLabels已出库标签数 |
||||
|
*/ |
||||
|
Map<String, Object> checkAllLabelsOutbound(@Param("outboundNo") String outboundNo, |
||||
|
@Param("site") String site, |
||||
|
@Param("buNo") String buNo); |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单物料清单 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @return 物料清单 |
||||
|
*/ |
||||
|
List<Map<String, Object>> getMaterialList(@Param("site") String site, |
||||
|
@Param("buNo") String buNo, |
||||
|
@Param("outboundNo") String outboundNo); |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
package com.gaotao.modules.otherOutbound.service; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 其他出库服务接口 |
||||
|
* 数据来源:return_notification_head/detail表(类型为其他出库) |
||||
|
*/ |
||||
|
public interface OtherOutboundService { |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单列表 |
||||
|
* 数据来源:return_notification_head表,类型为其他出库 |
||||
|
* @param site 站点 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param searchCode 搜索条件 |
||||
|
* @param status 状态 |
||||
|
* @return 出库单列表 |
||||
|
*/ |
||||
|
List<Map<String, Object>> getOutboundList(String site, String warehouseId, String searchCode, String status); |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单详情 |
||||
|
* 数据来源:return_notification_head表,关联库存表统计 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param buNo 业务单元 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param site 站点 |
||||
|
* @return 出库单详情 |
||||
|
*/ |
||||
|
Map<String, Object> getOutboundDetails(String outboundNo, String buNo, String warehouseId, String site); |
||||
|
|
||||
|
/** |
||||
|
* 验证标签与其他出库单是否匹配,并检查库存 |
||||
|
* 从库存表验证标签信息 |
||||
|
* @param labelCode 标签条码 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @return 标签信息 |
||||
|
*/ |
||||
|
Map<String, Object> validateLabelWithOutbound(String labelCode, String outboundNo, |
||||
|
String warehouseId, String site, String buNo); |
||||
|
|
||||
|
/** |
||||
|
* 确认其他出库 |
||||
|
* 1. 更新库存表中的标签状态 |
||||
|
* 2. 更新return_notification_head表状态 |
||||
|
* 3. 生成出库事务记录 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @param warehouseId 仓库ID |
||||
|
* @param labels 标签列表 |
||||
|
* @return 处理结果 |
||||
|
*/ |
||||
|
boolean confirmOtherOutbound(String site, String buNo, String outboundNo, |
||||
|
String warehouseId, List<Map<String, Object>> labels); |
||||
|
|
||||
|
/** |
||||
|
* 获取其他出库单物料清单 |
||||
|
* 数据来源:return_notification_detail表,关联库存表 |
||||
|
* @param site 站点 |
||||
|
* @param buNo 业务单元 |
||||
|
* @param outboundNo 出库单号 |
||||
|
* @return 物料清单 |
||||
|
*/ |
||||
|
List<Map<String, Object>> getMaterialList(String site, String buNo, String outboundNo); |
||||
|
} |
||||
@ -0,0 +1,265 @@ |
|||||
|
package com.gaotao.modules.otherOutbound.service.impl; |
||||
|
|
||||
|
import com.gaotao.modules.otherOutbound.dao.OtherOutboundMapper; |
||||
|
import com.gaotao.modules.otherOutbound.service.OtherOutboundService; |
||||
|
import com.gaotao.modules.inventoryStock.service.InventoryStockService; |
||||
|
import com.gaotao.modules.trans.entity.TransDetail; |
||||
|
import com.gaotao.modules.trans.entity.TransDetailDto; |
||||
|
import com.gaotao.modules.trans.entity.TransHeader; |
||||
|
import com.gaotao.modules.trans.service.TransDetailService; |
||||
|
import com.gaotao.modules.trans.service.TransHeaderService; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 其他出库服务实现类 |
||||
|
*/ |
||||
|
@Service |
||||
|
public class OtherOutboundServiceImpl implements OtherOutboundService { |
||||
|
|
||||
|
private static final Logger logger = LoggerFactory.getLogger(OtherOutboundServiceImpl.class); |
||||
|
|
||||
|
@Autowired |
||||
|
private OtherOutboundMapper otherOutboundMapper; |
||||
|
|
||||
|
@Autowired |
||||
|
private InventoryStockService inventoryStockService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TransHeaderService transHeaderService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TransDetailService transDetailService; |
||||
|
|
||||
|
@Override |
||||
|
public List<Map<String, Object>> getOutboundList(String site, String warehouseId, String searchCode, String status) { |
||||
|
try { |
||||
|
logger.info("获取其他出库单列表,站点: {}, 仓库: {}, 搜索码: {}, 状态: {}", |
||||
|
site, warehouseId, searchCode, status); |
||||
|
|
||||
|
List<Map<String, Object>> list = otherOutboundMapper.getOutboundList(site, warehouseId, searchCode, status); |
||||
|
|
||||
|
logger.info("获取其他出库单列表成功,共{}条记录", list != null ? list.size() : 0); |
||||
|
return list != null ? list : new ArrayList<>(); |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库单列表失败", e); |
||||
|
throw new RuntimeException("获取出库单列表失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Object> getOutboundDetails(String outboundNo, String buNo, String warehouseId, String site) { |
||||
|
try { |
||||
|
logger.info("获取其他出库单详情,出库单号: {}, 业务单元: {}, 仓库: {}, 站点: {}", |
||||
|
outboundNo, buNo, warehouseId, site); |
||||
|
|
||||
|
Map<String, Object> details = otherOutboundMapper.getOutboundDetails(outboundNo, buNo, warehouseId, site); |
||||
|
|
||||
|
if (details != null) { |
||||
|
logger.info("获取其他出库单详情成功"); |
||||
|
} else { |
||||
|
logger.warn("未找到出库单详情"); |
||||
|
} |
||||
|
|
||||
|
return details; |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库单详情失败", e); |
||||
|
throw new RuntimeException("获取出库单详情失败: " + e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Object> validateLabelWithOutbound(String labelCode, String outboundNo, |
||||
|
String warehouseId, String site, String buNo) { |
||||
|
try { |
||||
|
logger.info("验证标签与其他出库单匹配,标签: {}, 出库单: {}, 仓库: {}, 站点: {}, 业务单元: {}", |
||||
|
labelCode, outboundNo, warehouseId, site, buNo); |
||||
|
|
||||
|
Map<String, Object> result = otherOutboundMapper.validateLabelWithOutbound( |
||||
|
labelCode, outboundNo, warehouseId, site, buNo); |
||||
|
|
||||
|
if (result == null || result.isEmpty()) { |
||||
|
throw new RuntimeException("该标签与出库单不匹配或标签状态不正确"); |
||||
|
} |
||||
|
|
||||
|
// 检查标签状态,只有"在库"状态的标签才能出库 |
||||
|
String labelStatus = (String) result.get("status"); |
||||
|
if (!"在库".equals(labelStatus)) { |
||||
|
throw new RuntimeException("标签状态为:" + labelStatus + ",无法出库"); |
||||
|
} |
||||
|
|
||||
|
logger.info("标签验证成功,物料编码: {}, 数量: {}", |
||||
|
result.get("partNo"), result.get("quantity")); |
||||
|
|
||||
|
return result; |
||||
|
} catch (Exception e) { |
||||
|
logger.error("验证标签与其他出库单匹配失败", e); |
||||
|
throw new RuntimeException(e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
@Transactional(rollbackFor = Exception.class) |
||||
|
public boolean confirmOtherOutbound(String site, String buNo, String outboundNo, |
||||
|
String warehouseId, List<Map<String, Object>> labels) { |
||||
|
logger.info("开始确认其他出库,出库单号: {}, 仓库ID: {}, 标签数量: {}", |
||||
|
outboundNo, warehouseId, labels.size()); |
||||
|
try { |
||||
|
// 1. 更新库存表中的标签状态为"已出库" |
||||
|
List<String> labelCodes = new ArrayList<>(); |
||||
|
for (Map<String, Object> label : labels) { |
||||
|
labelCodes.add((String) label.get("labelCode")); |
||||
|
} |
||||
|
|
||||
|
int updatedLabels = otherOutboundMapper.updateInventoryStatus(labelCodes, "已出库", site, buNo); |
||||
|
if (updatedLabels != labelCodes.size()) { |
||||
|
throw new RuntimeException("部分标签状态更新失败"); |
||||
|
} |
||||
|
|
||||
|
// 2. 检查是否所有标签都已出库,决定是否更新出库单状态 |
||||
|
Map<String, Object> labelStats = otherOutboundMapper.checkAllLabelsOutbound(outboundNo, site, buNo); |
||||
|
if (labelStats != null) { |
||||
|
Integer totalLabels = (Integer) labelStats.get("totalLabels"); |
||||
|
Integer outboundLabels = (Integer) labelStats.get("outboundLabels"); |
||||
|
|
||||
|
logger.info("出库单 {} 标签统计: 总标签数={}, 已出库标签数={}", outboundNo, totalLabels, outboundLabels); |
||||
|
|
||||
|
// 只有当所有标签都已出库时,才更新出库单状态为"已完成" |
||||
|
if (totalLabels != null && outboundLabels != null && totalLabels.equals(outboundLabels) && totalLabels > 0) { |
||||
|
int updatedHead = otherOutboundMapper.updateOutboundStatus(outboundNo, "已完成", site, buNo); |
||||
|
if (updatedHead > 0) { |
||||
|
logger.info("出库单 {} 所有标签已出库,状态更新为已完成", outboundNo); |
||||
|
} |
||||
|
} else { |
||||
|
logger.info("出库单 {} 还有标签未出库,保持待出库状态", outboundNo); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 3. 生成出库事务记录 |
||||
|
generateOutboundTransaction(outboundNo, warehouseId, labels, site); |
||||
|
|
||||
|
// 4. 异步调用ERP接口(这里可以发送消息到队列) |
||||
|
//asyncCallErpInterface(outboundNo, labels); |
||||
|
|
||||
|
logger.info("其他出库确认完成,出库单号: {}", outboundNo); |
||||
|
return true; |
||||
|
} catch (Exception e) { |
||||
|
logger.error("其他出库确认失败,出库单号: {}, 错误信息: {}", outboundNo, e.getMessage(), e); |
||||
|
throw new RuntimeException("出库确认失败: " + e.getMessage(), e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Map<String, Object>> getMaterialList(String site, String buNo, String outboundNo) { |
||||
|
logger.info("获取其他出库物料清单,站点: {}, 业务单元: {}, 出库单号: {}", site, buNo, outboundNo); |
||||
|
|
||||
|
try { |
||||
|
List<Map<String, Object>> materialList = otherOutboundMapper.getMaterialList(site, buNo, outboundNo); |
||||
|
|
||||
|
if (materialList == null) { |
||||
|
materialList = new ArrayList<>(); |
||||
|
} |
||||
|
|
||||
|
logger.info("获取其他出库物料清单成功,站点: {}, 业务单元: {}, 出库单号: {}, 记录数: {}", |
||||
|
site, buNo, outboundNo, materialList.size()); |
||||
|
|
||||
|
return materialList; |
||||
|
} catch (Exception e) { |
||||
|
logger.error("获取其他出库物料清单失败,站点: {}, 业务单元: {}, 出库单号: {}, 错误信息: {}", |
||||
|
site, buNo, outboundNo, e.getMessage(), e); |
||||
|
throw new RuntimeException("获取物料清单失败: " + e.getMessage(), e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成出库事务记录 |
||||
|
*/ |
||||
|
private void generateOutboundTransaction(String outboundNo, String warehouseId, List<Map<String, Object>> labels, String site) { |
||||
|
logger.info("开始生成出库事务记录,出库单号: {}", outboundNo); |
||||
|
|
||||
|
// 构建TransDetailDto对象 |
||||
|
TransDetailDto transDetailDto = new TransDetailDto(); |
||||
|
transDetailDto.setSite(site); // 站点 |
||||
|
transDetailDto.setRemark("其他出库 - " + outboundNo); |
||||
|
transDetailDto.setOrderref1(outboundNo); // 出库单号 |
||||
|
transDetailDto.setOrderref3(warehouseId); // 仓库ID |
||||
|
|
||||
|
// 使用TransHeaderService的genTrans方法生成事务头 |
||||
|
TransHeader transHeader = transHeaderService.genTrans(transDetailDto, "OUT", warehouseId); |
||||
|
|
||||
|
if (transHeader == null) { |
||||
|
throw new RuntimeException("生成事务头记录失败"); |
||||
|
} |
||||
|
|
||||
|
logger.info("事务头记录生成成功,事务单号: {}", transHeader.getTransno()); |
||||
|
|
||||
|
// 生成事务明细记录 |
||||
|
generateTransactionDetails(transHeader.getTransno(), labels, site); |
||||
|
|
||||
|
logger.info("出库事务记录生成完成,事务单号: {}, 出库单号: {}, 明细记录数: {}", |
||||
|
transHeader.getTransno(), outboundNo, labels.size()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成事务明细记录 |
||||
|
*/ |
||||
|
private void generateTransactionDetails(String transNo, List<Map<String, Object>> labels, String site) { |
||||
|
logger.info("开始生成事务明细记录,事务单号: {}, 明细数量: {}", transNo, labels.size()); |
||||
|
|
||||
|
List<TransDetail> transDetailList = new ArrayList<>(); |
||||
|
double itemNo = 1.0; // 行号从1开始 |
||||
|
|
||||
|
for (Map<String, Object> label : labels) { |
||||
|
String labelCode = (String) label.get("labelCode"); |
||||
|
Object quantityObj = label.get("quantity"); |
||||
|
String batchNo = (String) label.get("batchNo"); |
||||
|
String partNo = (String) label.get("partNo"); |
||||
|
|
||||
|
// 转换数量 |
||||
|
BigDecimal quantity = BigDecimal.ZERO; |
||||
|
if (quantityObj != null) { |
||||
|
if (quantityObj instanceof BigDecimal) { |
||||
|
quantity = (BigDecimal) quantityObj; |
||||
|
} else if (quantityObj instanceof Number) { |
||||
|
quantity = new BigDecimal(quantityObj.toString()); |
||||
|
} else { |
||||
|
quantity = new BigDecimal(quantityObj.toString()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 构建事务明细记录 |
||||
|
TransDetail transDetail = new TransDetail(); |
||||
|
transDetail.setSite(site); // 站点 |
||||
|
transDetail.setTransno(transNo); |
||||
|
transDetail.setItemno(itemNo); |
||||
|
transDetail.setPartno(partNo); |
||||
|
transDetail.setTransqty(quantity); |
||||
|
transDetail.setBatchno(batchNo); |
||||
|
transDetail.setDirection("-"); // 出库方向 |
||||
|
transDetail.setOrderref1(labelCode); // 标签条码 |
||||
|
transDetail.setOrderref2(partNo); // 物料编码 |
||||
|
transDetail.setOrderref3(batchNo); // 批次号 |
||||
|
transDetail.setRemark("其他出库 - 标签: " + labelCode); |
||||
|
|
||||
|
transDetailList.add(transDetail); |
||||
|
itemNo += 1.0; // 行号递增 |
||||
|
} |
||||
|
|
||||
|
// 批量保存事务明细记录 |
||||
|
if (!transDetailList.isEmpty()) { |
||||
|
boolean success = transDetailService.saveBatch(transDetailList); |
||||
|
if (!success) { |
||||
|
throw new RuntimeException("事务明细记录保存失败"); |
||||
|
} |
||||
|
logger.info("事务明细记录生成成功,共生成 {} 条明细记录", transDetailList.size()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,140 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
|
||||
|
<mapper namespace="com.gaotao.modules.otherOutbound.dao.OtherOutboundMapper"> |
||||
|
|
||||
|
<!-- 获取其他出库单列表 --> |
||||
|
<select id="getOutboundList" resultType="java.util.Map"> |
||||
|
SELECT |
||||
|
h.order_no AS outboundNo, |
||||
|
h.bu_no AS buNo, |
||||
|
h.related_order_no AS relatedNo, |
||||
|
h.related_order_line_no AS relatedLineNo, |
||||
|
0 as totalLabels, |
||||
|
0 as availableLabels, |
||||
|
SUM(CAST(d.required_qty AS float)) as totalQty, |
||||
|
0 as availableQty |
||||
|
FROM outbound_notification_head h |
||||
|
INNER JOIN outbound_notification_detail d ON h.order_no = d.order_no AND h.site = d.site |
||||
|
WHERE h.site = #{site} |
||||
|
AND h.order_type = '其他出库' |
||||
|
AND h.close_flag = 'N' |
||||
|
AND h.order_status = #{status} |
||||
|
AND h.out_warehouse = #{warehouseId} |
||||
|
<if test="searchCode != null and searchCode != ''"> |
||||
|
AND ( |
||||
|
h.order_no LIKE CONCAT('%', #{searchCode}, '%') |
||||
|
OR h.related_order_no LIKE CONCAT('%', #{searchCode}, '%') |
||||
|
) |
||||
|
</if> |
||||
|
<if test="searchCode == null or searchCode == ''"> |
||||
|
AND CONVERT(DATE, h.required_outbound_date) = CONVERT(DATE, GETDATE()) |
||||
|
</if> |
||||
|
GROUP BY h.order_no, h.bu_no, h.related_order_no, h.related_order_line_no, h.required_outbound_date |
||||
|
ORDER BY h.required_outbound_date DESC |
||||
|
</select> |
||||
|
|
||||
|
<!-- 获取其他出库单详情 --> |
||||
|
<select id="getOutboundDetails" resultType="java.util.Map"> |
||||
|
SELECT |
||||
|
h.order_no AS outboundNo, |
||||
|
h.site AS site, |
||||
|
h.bu_no AS buNo, |
||||
|
h.related_order_no AS relatedNo, |
||||
|
h.related_order_line_no AS relatedLineNo, |
||||
|
0 as totalLabels, |
||||
|
0 as availableLabels, |
||||
|
SUM(CAST(d.required_qty AS float)) as totalQty, |
||||
|
0 as availableQty |
||||
|
FROM outbound_notification_head h |
||||
|
INNER JOIN outbound_notification_detail d ON h.order_no = d.order_no AND h.site = d.site |
||||
|
WHERE h.order_no = #{outboundNo} |
||||
|
AND h.site = #{site} |
||||
|
AND h.bu_no = #{buNo} |
||||
|
AND h.out_warehouse = #{warehouseId} |
||||
|
AND h.order_type = '其他出库' |
||||
|
GROUP BY h.order_no, h.site, h.bu_no, h.related_order_no, h.related_order_line_no, h.required_outbound_date |
||||
|
</select> |
||||
|
|
||||
|
<!-- 验证标签与其他出库单是否匹配 --> |
||||
|
<select id="validateLabelWithOutbound" resultType="java.util.Map"> |
||||
|
SELECT |
||||
|
inv.roll_no AS labelCode, |
||||
|
inv.part_no AS partNo, |
||||
|
inv.qty_on_hand AS quantity, |
||||
|
inv.batch_no AS batchNo, |
||||
|
inv.status AS status, |
||||
|
inv.warehouse_id AS warehouseId, |
||||
|
inv.location_id AS locationId |
||||
|
FROM inventory_stock inv |
||||
|
INNER JOIN outbound_notification_detail d ON inv.part_no = d.part_no |
||||
|
INNER JOIN outbound_notification_head h ON d.order_no = h.order_no AND d.site = h.site |
||||
|
WHERE inv.roll_no = #{labelCode} |
||||
|
AND h.order_no = #{outboundNo} |
||||
|
AND inv.warehouse_id = #{warehouseId} |
||||
|
AND inv.site = #{site} |
||||
|
AND inv.bu_no = #{buNo} |
||||
|
AND h.order_type = '其他出库' |
||||
|
AND inv.status = '在库' |
||||
|
AND inv.qty_on_hand > 0 |
||||
|
</select> |
||||
|
|
||||
|
<!-- 更新库存表中的标签状态 --> |
||||
|
<update id="updateInventoryStatus"> |
||||
|
UPDATE inventory_stock |
||||
|
SET status = #{status}, |
||||
|
updated_date = GETDATE(), |
||||
|
updated_by = 'SYSTEM' |
||||
|
WHERE roll_no IN |
||||
|
<foreach collection="labelCodes" item="labelCode" open="(" separator="," close=")"> |
||||
|
#{labelCode} |
||||
|
</foreach> |
||||
|
AND site = #{site} |
||||
|
AND bu_no = #{buNo} |
||||
|
</update> |
||||
|
|
||||
|
<!-- 更新出库单状态 --> |
||||
|
<update id="updateOutboundStatus"> |
||||
|
UPDATE outbound_notification_head |
||||
|
SET order_status = #{status}, |
||||
|
updated_date = GETDATE(), |
||||
|
updated_by = 'SYSTEM' |
||||
|
WHERE order_no = #{outboundNo} |
||||
|
AND site = #{site} |
||||
|
AND bu_no = #{buNo} |
||||
|
AND order_type = '其他出库' |
||||
|
</update> |
||||
|
|
||||
|
<!-- 检查出库单的所有标签是否都已出库 --> |
||||
|
<select id="checkAllLabelsOutbound" resultType="java.util.Map"> |
||||
|
SELECT |
||||
|
COUNT(DISTINCT inv.roll_no) AS totalLabels, |
||||
|
SUM(CASE WHEN inv.status = '已出库' THEN 1 ELSE 0 END) AS outboundLabels |
||||
|
FROM outbound_notification_head h |
||||
|
INNER JOIN outbound_notification_detail d ON h.order_no = d.order_no AND h.site = d.site |
||||
|
LEFT JOIN inventory_stock inv ON d.part_no = inv.part_no |
||||
|
AND h.out_warehouse = inv.warehouse_id |
||||
|
AND h.site = inv.site |
||||
|
WHERE h.order_no = #{outboundNo} |
||||
|
AND h.site = #{site} |
||||
|
AND h.bu_no = #{buNo} |
||||
|
AND h.order_type = '其他出库' |
||||
|
</select> |
||||
|
|
||||
|
<!-- 获取其他出库单物料清单 --> |
||||
|
<select id="getMaterialList" resultType="java.util.Map"> |
||||
|
SELECT |
||||
|
d.part_no AS materialCode, |
||||
|
d.part_desc AS partDesc, |
||||
|
d.required_qty AS requiredQty, |
||||
|
SUM(CASE WHEN inv.status = '在库' THEN inv.qty_on_hand ELSE 0 END) AS availableQty |
||||
|
FROM outbound_notification_detail d |
||||
|
LEFT JOIN inventory_stock inv ON d.part_no = inv.part_no |
||||
|
AND d.site = inv.site |
||||
|
WHERE d.site = #{site} |
||||
|
AND d.bu_no = #{buNo} |
||||
|
AND d.order_no = #{outboundNo} |
||||
|
GROUP BY d.part_no, d.part_desc, d.required_qty |
||||
|
</select> |
||||
|
|
||||
|
</mapper> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue