6 changed files with 943 additions and 0 deletions
-
107src/main/java/com/gaotao/modules/production/controller/ProductionWithdrawalController.java
-
114src/main/java/com/gaotao/modules/production/entity/dto/ProductionWithdrawalHuDto.java
-
104src/main/java/com/gaotao/modules/production/entity/dto/ShopOrderReceiveHistDto.java
-
129src/main/java/com/gaotao/modules/production/entity/dto/ShopOrderWithdrawalDto.java
-
47src/main/java/com/gaotao/modules/production/service/ProductionWithdrawalService.java
-
442src/main/java/com/gaotao/modules/production/service/impl/ProductionWithdrawalServiceImpl.java
@ -0,0 +1,107 @@ |
|||
package com.gaotao.modules.production.controller; |
|||
|
|||
import com.gaotao.common.utils.R; |
|||
import com.gaotao.common.validator.ValidatorUtils; |
|||
import com.gaotao.modules.production.entity.dto.*; |
|||
import com.gaotao.modules.production.service.ProductionWithdrawalService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 生产退库控制器 |
|||
* |
|||
* <p><b>主要功能:</b></p> |
|||
* <ul> |
|||
* <li>从IFS获取工单接收历史</li> |
|||
* <li>扫描HU验证合法性</li> |
|||
* <li>提交生产退库</li> |
|||
* </ul> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
@Slf4j |
|||
@RestController |
|||
@RequestMapping("production/withdrawal") |
|||
public class ProductionWithdrawalController { |
|||
|
|||
@Autowired |
|||
private ProductionWithdrawalService productionWithdrawalService; |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 从IFS获取工单接收历史 |
|||
* @Date 2025/01/21 |
|||
* @Param [queryDto] |
|||
* @return com.gaotao.common.utils.R |
|||
**/ |
|||
@PostMapping("/getShopOrderReceiveHist") |
|||
public R getShopOrderReceiveHist(@RequestBody ShopOrderQueryDto queryDto) { |
|||
try { |
|||
log.info("收到获取工单接收历史请求: {}", queryDto.getIfsOrderNo()); |
|||
List<ShopOrderReceiveHistDto> histList = productionWithdrawalService.getShopOrderReceiveHist(queryDto); |
|||
return R.ok().put("data", histList); |
|||
} catch (Exception e) { |
|||
log.error("获取工单接收历史失败: {}", e.getMessage(), e); |
|||
return R.error(e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 扫描HU验证是否可退库 |
|||
* @Date 2025/01/21 |
|||
* @Param [params] |
|||
* @return com.gaotao.common.utils.R |
|||
**/ |
|||
@PostMapping("/scanHuForWithdrawal") |
|||
public R scanHuForWithdrawal(@RequestBody Map<String, String> params) { |
|||
try { |
|||
String unitId = params.get("unitId"); |
|||
String site = params.get("site"); |
|||
|
|||
log.info("收到扫描HU请求: unitId={}, site={}", unitId, site); |
|||
|
|||
if (unitId == null || unitId.trim().isEmpty()) { |
|||
return R.error("HU编码不能为空"); |
|||
} |
|||
|
|||
if (site == null || site.trim().isEmpty()) { |
|||
return R.error("工厂编码不能为空"); |
|||
} |
|||
|
|||
ProductionWithdrawalHuDto huDto = productionWithdrawalService.validateHuForWithdrawal(unitId, site); |
|||
return R.ok().put("data", huDto); |
|||
} catch (Exception e) { |
|||
log.error("扫描HU失败: {}", e.getMessage(), e); |
|||
return R.error(e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 提交生产退库 |
|||
* @Date 2025/01/21 |
|||
* @Param [dto] |
|||
* @return com.gaotao.common.utils.R |
|||
**/ |
|||
@PostMapping("/submitWithdrawal") |
|||
public R submitWithdrawal(@RequestBody ShopOrderWithdrawalDto dto) { |
|||
ValidatorUtils.validateEntity(dto); |
|||
try { |
|||
log.info("收到提交生产退库请求: 工单号={}, 料号={}, HU数量={}", |
|||
dto.getOrderNo(), dto.getPartNo(), dto.getUnitIds().size()); |
|||
|
|||
String transNo = productionWithdrawalService.submitShopOrderWithdrawal(dto); |
|||
return R.ok("退库成功").put("data", transNo); |
|||
} catch (Exception e) { |
|||
log.error("提交生产退库失败: {}", e.getMessage(), e); |
|||
return R.error(e.getMessage()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,114 @@ |
|||
package com.gaotao.modules.production.entity.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* 生产退库HU信息DTO |
|||
* |
|||
* <p><b>用途:</b>扫描HU后返回的HU信息和验证结果</p> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
@Data |
|||
public class ProductionWithdrawalHuDto { |
|||
|
|||
/** |
|||
* HU编码 |
|||
*/ |
|||
private String unitId; |
|||
|
|||
/** |
|||
* 工厂编码 |
|||
*/ |
|||
private String site; |
|||
|
|||
/** |
|||
* 单元类型 |
|||
*/ |
|||
private String unitType; |
|||
|
|||
/** |
|||
* 料号 |
|||
*/ |
|||
private String partNo; |
|||
|
|||
/** |
|||
* 料号描述 |
|||
*/ |
|||
private String partDesc; |
|||
|
|||
/** |
|||
* 数量 |
|||
*/ |
|||
private BigDecimal qty; |
|||
|
|||
/** |
|||
* 批次号 |
|||
*/ |
|||
private String batchNo; |
|||
|
|||
/** |
|||
* 仓库编码 |
|||
*/ |
|||
private String warehouseId; |
|||
|
|||
/** |
|||
* 库位编码 |
|||
*/ |
|||
private String locationId; |
|||
|
|||
/** |
|||
* 状态 |
|||
*/ |
|||
private String status; |
|||
|
|||
/** |
|||
* 在库标记(Y=在库,N=不在库) |
|||
*/ |
|||
private String inStockFlag; |
|||
|
|||
/** |
|||
* 工单号 |
|||
*/ |
|||
private String orderNo; |
|||
|
|||
/** |
|||
* 下达号 |
|||
*/ |
|||
private String lineNo; |
|||
|
|||
/** |
|||
* 序列号 |
|||
*/ |
|||
private String releaseNo; |
|||
|
|||
/** |
|||
* WDR号 |
|||
*/ |
|||
private String wdr; |
|||
|
|||
/** |
|||
* 创建日期 |
|||
*/ |
|||
private Date createdDate; |
|||
|
|||
/** |
|||
* 创建人 |
|||
*/ |
|||
private String createdBy; |
|||
|
|||
/** |
|||
* 是否可退库(Y=可以,N=不可以) |
|||
*/ |
|||
private String canWithdraw; |
|||
|
|||
/** |
|||
* 不可退库原因 |
|||
*/ |
|||
private String cannotWithdrawReason; |
|||
} |
|||
|
|||
@ -0,0 +1,104 @@ |
|||
package com.gaotao.modules.production.entity.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.math.BigDecimal; |
|||
|
|||
/** |
|||
* 工单接收历史DTO |
|||
* |
|||
* <p><b>用途:</b>从IFS获取的工单接收历史记录</p> |
|||
* <p><b>数据源:</b>IFS ShopOrderReceiveHist接口</p> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
@Data |
|||
public class ShopOrderReceiveHistDto { |
|||
|
|||
/** |
|||
* 工单号 |
|||
*/ |
|||
private String sourceRef1; |
|||
|
|||
/** |
|||
* 下达号 |
|||
*/ |
|||
private String sourceRef2; |
|||
|
|||
/** |
|||
* 序列号 |
|||
*/ |
|||
private String sourceRef3; |
|||
|
|||
/** |
|||
* 行号 |
|||
*/ |
|||
private String sourceRef4; |
|||
|
|||
/** |
|||
* 事务ID |
|||
*/ |
|||
private Long transactionId; |
|||
|
|||
/** |
|||
* 会计ID |
|||
*/ |
|||
private Long accountingId; |
|||
|
|||
/** |
|||
* 工厂编码 |
|||
*/ |
|||
private String contract; |
|||
|
|||
/** |
|||
* 料号 |
|||
*/ |
|||
private String partNo; |
|||
|
|||
/** |
|||
* 库位编码 |
|||
*/ |
|||
private String locationNo; |
|||
|
|||
/** |
|||
* 批次号 |
|||
*/ |
|||
private String lotBatchNo; |
|||
|
|||
/** |
|||
* 序列号(物料) |
|||
*/ |
|||
private String serialNo; |
|||
|
|||
/** |
|||
* WDR号 |
|||
*/ |
|||
private String waivDevRejNo; |
|||
|
|||
/** |
|||
* 活动序列号 |
|||
*/ |
|||
private Integer activitySeq; |
|||
|
|||
/** |
|||
* 工程变更级别 |
|||
*/ |
|||
private String engChgLevel; |
|||
|
|||
/** |
|||
* 接收数量 |
|||
*/ |
|||
private BigDecimal quantity; |
|||
|
|||
/** |
|||
* 已退数量 |
|||
*/ |
|||
private BigDecimal qtyReversed; |
|||
|
|||
/** |
|||
* 处理单元ID |
|||
*/ |
|||
private Integer handlingUnitId; |
|||
} |
|||
|
|||
@ -0,0 +1,129 @@ |
|||
package com.gaotao.modules.production.entity.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 生产退库提交DTO |
|||
* |
|||
* <p><b>用途:</b>提交生产退库的请求参数</p> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
@Data |
|||
public class ShopOrderWithdrawalDto { |
|||
|
|||
/** |
|||
* 工厂编码 |
|||
*/ |
|||
|
|||
private String site; |
|||
|
|||
/** |
|||
* 工单号 |
|||
*/ |
|||
|
|||
private String orderNo; |
|||
|
|||
/** |
|||
* 下达号 |
|||
*/ |
|||
|
|||
private String releaseNo; |
|||
|
|||
/** |
|||
* 序列号 |
|||
*/ |
|||
|
|||
private String sequenceNo; |
|||
|
|||
/** |
|||
* 料号 |
|||
*/ |
|||
|
|||
private String partNo; |
|||
|
|||
/** |
|||
* 料号描述 |
|||
*/ |
|||
private String partDesc; |
|||
|
|||
/** |
|||
* 库位编码 |
|||
*/ |
|||
|
|||
private String locationNo; |
|||
|
|||
/** |
|||
* 批次号 |
|||
*/ |
|||
|
|||
private String batchNo; |
|||
|
|||
/** |
|||
* 序列号(物料) |
|||
*/ |
|||
private String serialNo; |
|||
|
|||
/** |
|||
* 工程变更级别 |
|||
*/ |
|||
private String engChgLevel; |
|||
|
|||
/** |
|||
* WDR号 |
|||
*/ |
|||
private String wdr; |
|||
|
|||
/** |
|||
* 退库数量 |
|||
*/ |
|||
|
|||
private BigDecimal transQty; |
|||
|
|||
/** |
|||
* 已接收数量(从IFS获取) |
|||
*/ |
|||
|
|||
private BigDecimal qtyReceived; |
|||
|
|||
/** |
|||
* 会计ID(从IFS获取) |
|||
*/ |
|||
|
|||
private Long accountingId; |
|||
|
|||
/** |
|||
* 事务ID(从IFS获取) |
|||
*/ |
|||
|
|||
private Long transactionId; |
|||
|
|||
/** |
|||
* 行号 |
|||
*/ |
|||
|
|||
private String lineItemNo; |
|||
|
|||
/** |
|||
* 仓库编码 |
|||
*/ |
|||
|
|||
private String warehouseId; |
|||
|
|||
/** |
|||
* HU单元列表 |
|||
*/ |
|||
|
|||
private List<String> unitIds; |
|||
|
|||
/** |
|||
* 退库原因 |
|||
*/ |
|||
private String withdrawalReason; |
|||
} |
|||
|
|||
@ -0,0 +1,47 @@ |
|||
package com.gaotao.modules.production.service; |
|||
|
|||
import com.gaotao.modules.production.entity.dto.*; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 生产退库服务接口 |
|||
* |
|||
* <p><b>主要功能:</b></p> |
|||
* <ul> |
|||
* <li>从IFS获取工单接收历史记录</li> |
|||
* <li>扫描HU验证合法性</li> |
|||
* <li>执行退库操作并同步IFS</li> |
|||
* </ul> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
public interface ProductionWithdrawalService { |
|||
|
|||
/** |
|||
* 从IFS获取工单接收历史记录 |
|||
* |
|||
* @param queryDto 查询参数(包含工单号、下达号、序列号) |
|||
* @return 工单接收历史记录列表 |
|||
*/ |
|||
List<ShopOrderReceiveHistDto> getShopOrderReceiveHist(ShopOrderQueryDto queryDto); |
|||
|
|||
/** |
|||
* 扫描HU验证合法性 |
|||
* |
|||
* @param unitId HU编码 |
|||
* @param site 工厂编码 |
|||
* @return HU信息和验证结果 |
|||
*/ |
|||
ProductionWithdrawalHuDto validateHuForWithdrawal(String unitId, String site); |
|||
|
|||
/** |
|||
* 提交生产退库 |
|||
* |
|||
* @param dto 退库参数 |
|||
* @return 事务号 |
|||
*/ |
|||
String submitShopOrderWithdrawal(ShopOrderWithdrawalDto dto); |
|||
} |
|||
|
|||
@ -0,0 +1,442 @@ |
|||
package com.gaotao.modules.production.service.impl; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import com.gaotao.common.exception.XJException; |
|||
import com.gaotao.common.utils.HttpUtils; |
|||
import com.gaotao.common.utils.IfsErrorMessageUtils; |
|||
import com.gaotao.modules.handlingunit.entity.HandlingUnit; |
|||
import com.gaotao.modules.handlingunit.service.HandlingUnitService; |
|||
import com.gaotao.modules.production.entity.dto.*; |
|||
import com.gaotao.modules.production.service.ProductionWithdrawalService; |
|||
import com.gaotao.modules.sys.entity.SysUserEntity; |
|||
import com.gaotao.modules.trans.entity.*; |
|||
import com.gaotao.modules.trans.service.TransDetailService; |
|||
import com.gaotao.modules.trans.service.TransDetailSubService; |
|||
import com.gaotao.modules.trans.service.TransHeaderService; |
|||
import com.gaotao.modules.trans.service.TransNoControlService; |
|||
import com.gaotao.modules.warehouse.service.InventoryStockService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.shiro.SecurityUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* 生产退库服务实现类 |
|||
* |
|||
* <p><b>主要功能:</b></p> |
|||
* <ul> |
|||
* <li>从IFS获取工单接收历史记录</li> |
|||
* <li>扫描HU验证合法性</li> |
|||
* <li>执行退库操作并同步IFS</li> |
|||
* </ul> |
|||
* |
|||
* <p><b>关键业务规则:</b></p> |
|||
* <ul> |
|||
* <li>只能退库inStockFlag='Y'的HU</li> |
|||
* <li>HU必须是生产入库创建的(sourceType='SHOP_ORDER_RECEIVE')</li> |
|||
* <li>退库后需要同步更新IFS系统</li> |
|||
* <li>退库后HU状态变更为N,库存扣减</li> |
|||
* </ul> |
|||
* |
|||
* @author System |
|||
* @since 2025-01-21 |
|||
*/ |
|||
@Slf4j |
|||
@Service("productionWithdrawalService") |
|||
public class ProductionWithdrawalServiceImpl implements ProductionWithdrawalService { |
|||
|
|||
@Autowired |
|||
private HandlingUnitService handlingUnitService; |
|||
|
|||
@Autowired |
|||
private TransHeaderService transHeaderService; |
|||
|
|||
@Autowired |
|||
private TransDetailService transDetailService; |
|||
|
|||
@Autowired |
|||
private TransDetailSubService transDetailSubService; |
|||
|
|||
@Autowired |
|||
private InventoryStockService inventoryStockService; |
|||
|
|||
@Autowired |
|||
private TransNoControlService transNoService; |
|||
|
|||
@Value("${custom.ifs-url}") |
|||
private String ifsUrl; |
|||
|
|||
@Value("${custom.ifs-ifsDBName}") |
|||
private String ifsDBName; |
|||
|
|||
@Value("${custom.ifs-domainUserID}") |
|||
private String domainUserID; |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 从IFS获取工单接收历史记录 |
|||
* @Date 2025/01/21 |
|||
* @Param [queryDto] |
|||
* @return List<ShopOrderReceiveHistDto> |
|||
**/ |
|||
@Override |
|||
public List<ShopOrderReceiveHistDto> getShopOrderReceiveHist(ShopOrderQueryDto queryDto) { |
|||
try { |
|||
log.info("=== 开始从IFS获取工单接收历史 ==="); |
|||
log.info("工单号: {}, 下达号: {}, 序列号: {}", |
|||
queryDto.getIfsOrderNo(), queryDto.getIfsReleaseNo(), queryDto.getIfsSequenceNo()); |
|||
|
|||
// 构建IFS接口参数 |
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("ifsDBName", queryDto.getIfsDBName() != null ? queryDto.getIfsDBName() : ifsDBName); |
|||
params.put("domainUserID", queryDto.getDomainUserID() != null ? queryDto.getDomainUserID() : domainUserID); |
|||
params.put("ifsSiteID", queryDto.getIfsSiteID()); |
|||
params.put("ifsOrderNo", queryDto.getIfsOrderNo()); |
|||
params.put("ifsReleaseNo", queryDto.getIfsReleaseNo()); |
|||
params.put("ifsSequenceNo", queryDto.getIfsSequenceNo()); |
|||
|
|||
ObjectMapper objectMapper = new ObjectMapper(); |
|||
String jsonBody = objectMapper.writeValueAsString(params); |
|||
log.info("IFS请求参数: {}", jsonBody); |
|||
|
|||
// 调用IFS接口 |
|||
String ifsResponse = HttpUtils.doGetWithBody(ifsUrl + "ShopOrderReceiveHist", jsonBody, null); |
|||
log.info("IFS响应: {}", ifsResponse); |
|||
|
|||
// 解析响应数据 |
|||
List<Map<String, Object>> responseList = objectMapper.readValue(ifsResponse, |
|||
new TypeReference<List<Map<String, Object>>>() {}); |
|||
|
|||
// 转换为DTO对象 |
|||
List<ShopOrderReceiveHistDto> resultList = responseList.stream().map(map -> { |
|||
ShopOrderReceiveHistDto dto = new ShopOrderReceiveHistDto(); |
|||
dto.setSourceRef1((String) map.get("SOURCE_REF1")); |
|||
dto.setSourceRef2((String) map.get("SOURCE_REF2")); |
|||
dto.setSourceRef3((String) map.get("SOURCE_REF3")); |
|||
dto.setSourceRef4((String) map.get("SOURCE_REF4")); |
|||
dto.setTransactionId(((Number) map.get("TRANSACTION_ID")).longValue()); |
|||
dto.setAccountingId(((Number) map.get("ACCOUNTING_ID")).longValue()); |
|||
dto.setContract((String) map.get("CONTRACT")); |
|||
dto.setPartNo((String) map.get("PART_NO")); |
|||
dto.setLocationNo((String) map.get("LOCATION_NO")); |
|||
dto.setLotBatchNo((String) map.get("LOT_BATCH_NO")); |
|||
dto.setSerialNo((String) map.get("SERIAL_NO")); |
|||
dto.setWaivDevRejNo((String) map.get("WAIV_DEV_REJ_NO")); |
|||
dto.setActivitySeq(((Number) map.get("ACTIVITY_SEQ")).intValue()); |
|||
dto.setEngChgLevel((String) map.get("ENG_CHG_LEVEL")); |
|||
dto.setQuantity(new BigDecimal(map.get("QUANTITY").toString())); |
|||
dto.setQtyReversed(new BigDecimal(map.get("QTY_REVERSED").toString())); |
|||
dto.setHandlingUnitId(((Number) map.get("HANDLING_UNIT_ID")).intValue()); |
|||
return dto; |
|||
}).collect(Collectors.toList()); |
|||
|
|||
log.info("=== 从IFS获取工单接收历史成功 === 返回记录数: {}", resultList.size()); |
|||
return resultList; |
|||
|
|||
} catch (Exception e) { |
|||
log.error("=== 从IFS获取工单接收历史失败 === 错误信息: {}", e.getMessage(), e); |
|||
throw new XJException("获取工单接收历史失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 扫描HU验证合法性 |
|||
* @Date 2025/01/21 |
|||
* @Param [unitId, site] |
|||
* @return ProductionWithdrawalHuDto |
|||
**/ |
|||
@Override |
|||
public ProductionWithdrawalHuDto validateHuForWithdrawal(String unitId, String site) { |
|||
log.info("=== 开始验证HU退库合法性 ==="); |
|||
log.info("HU编码: {}, 工厂: {}", unitId, site); |
|||
|
|||
try { |
|||
// 查询HU信息 |
|||
HandlingUnit hu = handlingUnitService.lambdaQuery() |
|||
.eq(HandlingUnit::getUnitId, unitId) |
|||
.eq(HandlingUnit::getSite, site) |
|||
.one(); |
|||
|
|||
if (hu == null) { |
|||
throw new XJException("HU不存在:" + unitId); |
|||
} |
|||
|
|||
// 构建返回DTO |
|||
ProductionWithdrawalHuDto dto = new ProductionWithdrawalHuDto(); |
|||
dto.setUnitId(hu.getUnitId()); |
|||
dto.setSite(hu.getSite()); |
|||
dto.setUnitType(hu.getUnitType()); |
|||
dto.setPartNo(hu.getPartNo()); |
|||
dto.setPartDesc(hu.getPartDesc()); |
|||
dto.setQty(hu.getQty()); |
|||
dto.setBatchNo(hu.getBatchNo()); |
|||
dto.setWarehouseId(hu.getWarehouseId()); |
|||
dto.setLocationId(hu.getLocationId()); |
|||
dto.setStatus(hu.getStatus()); |
|||
dto.setInStockFlag(hu.getInStockFlag()); |
|||
dto.setOrderNo(hu.getOrderNo()); |
|||
dto.setLineNo(hu.getLineNo()); |
|||
dto.setReleaseNo(hu.getReleaseNo()); |
|||
dto.setWdr(hu.getWdr()); |
|||
dto.setCreatedDate(hu.getCreatedDate()); |
|||
dto.setCreatedBy(hu.getCreatedBy()); |
|||
|
|||
// 验证HU是否可退库 |
|||
StringBuilder reason = new StringBuilder(); |
|||
boolean canWithdraw = true; |
|||
|
|||
// 1. 检查HU是否在库 |
|||
if (!"Y".equals(hu.getInStockFlag())) { |
|||
reason.append("HU未入库或已出库;"); |
|||
canWithdraw = false; |
|||
} |
|||
|
|||
// 2. 检查HU来源类型 |
|||
if (!"SHOP_ORDER_RECEIVE".equals(hu.getSourceType())) { |
|||
reason.append("HU不是生产入库创建的;"); |
|||
canWithdraw = false; |
|||
} |
|||
|
|||
// 3. 检查HU状态 |
|||
if (!"ACTIVE".equals(hu.getStatusDb())) { |
|||
reason.append("HU状态不是活动状态;"); |
|||
canWithdraw = false; |
|||
} |
|||
|
|||
// 4. 检查是否已预留 |
|||
if ("Y".equals(hu.getReserveFlag())) { |
|||
reason.append("HU已被预留;"); |
|||
canWithdraw = false; |
|||
} |
|||
|
|||
// 5. 检查是否已冻结 |
|||
if ("Y".equals(hu.getFreezeFlag())) { |
|||
reason.append("HU已被冻结;"); |
|||
canWithdraw = false; |
|||
} |
|||
|
|||
dto.setCanWithdraw(canWithdraw ? "Y" : "N"); |
|||
dto.setCannotWithdrawReason(reason.length() > 0 ? reason.toString() : null); |
|||
|
|||
if (canWithdraw) { |
|||
log.info("=== HU退库验证通过 ==="); |
|||
} else { |
|||
log.warn("=== HU退库验证失败 === 原因: {}", dto.getCannotWithdrawReason()); |
|||
} |
|||
|
|||
return dto; |
|||
|
|||
} catch (XJException e) { |
|||
throw e; |
|||
} catch (Exception e) { |
|||
log.error("=== 验证HU退库合法性失败 === 错误信息: {}", e.getMessage(), e); |
|||
throw new XJException("验证HU失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 提交生产退库 |
|||
* @Date 2025/01/21 |
|||
* @Param [dto] |
|||
* @return String 事务号 |
|||
**/ |
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public String submitShopOrderWithdrawal(ShopOrderWithdrawalDto dto) { |
|||
log.info("=== 开始生产退库 ==="); |
|||
log.info("工单号: {}, 料号: {}, 退库数量: {}", dto.getOrderNo(), dto.getPartNo(), dto.getTransQty()); |
|||
|
|||
try { |
|||
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal(); |
|||
|
|||
// 1. 验证所有HU |
|||
BigDecimal totalQty = BigDecimal.ZERO; |
|||
List<HandlingUnit> huList = new ArrayList<>(); |
|||
|
|||
for (String unitId : dto.getUnitIds()) { |
|||
ProductionWithdrawalHuDto huDto = validateHuForWithdrawal(unitId, dto.getSite()); |
|||
|
|||
if (!"Y".equals(huDto.getCanWithdraw())) { |
|||
throw new XJException("HU不可退库:" + unitId + ",原因:" + huDto.getCannotWithdrawReason()); |
|||
} |
|||
|
|||
// 验证HU的料号、批次等信息是否匹配 |
|||
if (!dto.getPartNo().equals(huDto.getPartNo())) { |
|||
throw new XJException("HU料号不匹配:期望" + dto.getPartNo() + ",实际" + huDto.getPartNo()); |
|||
} |
|||
|
|||
if (!dto.getBatchNo().equals(huDto.getBatchNo())) { |
|||
throw new XJException("HU批次号不匹配:期望" + dto.getBatchNo() + ",实际" + huDto.getBatchNo()); |
|||
} |
|||
|
|||
totalQty = totalQty.add(huDto.getQty()); |
|||
|
|||
HandlingUnit hu = handlingUnitService.lambdaQuery() |
|||
.eq(HandlingUnit::getUnitId, unitId) |
|||
.one(); |
|||
huList.add(hu); |
|||
} |
|||
|
|||
// 验证总数量 |
|||
if (totalQty.compareTo(dto.getTransQty()) != 0) { |
|||
throw new XJException("HU总数量不匹配:期望" + dto.getTransQty() + ",实际" + totalQty); |
|||
} |
|||
|
|||
log.info("HU验证通过,总数量: {}", totalQty); |
|||
|
|||
// 2. 生成事务号 |
|||
TransNoControl transTrans = transNoService.getTransNo(dto.getSite(), "SRR", 10); |
|||
String transNo = transTrans.getNewTransNo(); |
|||
log.info("生成事务号: {}", transNo); |
|||
|
|||
// 3. 创建TransHeader |
|||
TransHeader transHeader = new TransHeader(); |
|||
transHeader.setSite(dto.getSite()); |
|||
transHeader.setTransNo(transNo); |
|||
transHeader.setTransDate(new Date()); |
|||
transHeader.setTransTypeDb("SRR"); // Shop Order Issue Reversal (生产退库) |
|||
transHeader.setWarehouseId(dto.getWarehouseId()); |
|||
transHeader.setUserId(currentUser.getUserId().toString()); |
|||
transHeader.setUserName(currentUser.getUserDisplay()); |
|||
transHeader.setRemark(dto.getWithdrawalReason() != null ? dto.getWithdrawalReason() : "生产退库"); |
|||
transHeader.setOrderRef1(dto.getOrderNo()); |
|||
transHeader.setOrderRef2(dto.getReleaseNo()); |
|||
transHeader.setOrderRef3(dto.getSequenceNo()); |
|||
transHeader.setStatus("COMPLETED"); |
|||
transHeader.setEnterDate(new Date()); |
|||
transHeader.setIfsFlag("Y"); // 待同步IFS |
|||
transHeaderService.save(transHeader); |
|||
log.info("创建TransHeader成功"); |
|||
|
|||
// 4. 创建TransDetail |
|||
TransDetailDto transDetail = new TransDetailDto(); |
|||
transDetail.setTransNo(transNo); |
|||
transDetail.setSite(dto.getSite()); |
|||
transDetail.setItemNo(1d); |
|||
transDetail.setWarehouseId(dto.getWarehouseId()); |
|||
transDetail.setPartNo(dto.getPartNo()); |
|||
transDetail.setPartDesc(dto.getPartDesc()); |
|||
transDetail.setTransQty(dto.getTransQty()); |
|||
transDetail.setBatchNo(dto.getBatchNo()); |
|||
transDetail.setLocationId(dto.getLocationNo()); |
|||
transDetail.setDirection("-"); // 出库 |
|||
transDetail.setOrderRef1(dto.getOrderNo()); |
|||
transDetail.setOrderRef2(dto.getReleaseNo()); |
|||
transDetail.setOrderRef3(dto.getSequenceNo()); |
|||
transDetail.setWdr(dto.getWdr() != null ? dto.getWdr() : "*"); |
|||
transDetail.setRemark(dto.getWithdrawalReason() != null ? dto.getWithdrawalReason() : "生产退库"); |
|||
transDetail.setNeedHandlingUnit("Y"); |
|||
transDetailService.save(transDetail); |
|||
log.info("创建TransDetail成功"); |
|||
|
|||
// 5. 创建TransDetailSub并更新HU状态 |
|||
for (int i = 0; i < huList.size(); i++) { |
|||
HandlingUnit hu = huList.get(i); |
|||
|
|||
// 创建TransDetailSub记录 |
|||
TransDetailSub transDetailSub = new TransDetailSub(); |
|||
transDetailSub.setSite(dto.getSite()); |
|||
transDetailSub.setTransNo(transNo); |
|||
transDetailSub.setItemNo((double) i + 1); |
|||
transDetailSub.setSeqNo(1d); |
|||
transDetailSub.setSubQty(hu.getQty().doubleValue()); |
|||
transDetailSub.setOrderRef1(dto.getOrderNo()); |
|||
transDetailSub.setOrderRef2(hu.getUnitId()); |
|||
transDetailSub.setLocationId(dto.getLocationNo()); |
|||
transDetailSub.setBatchNo(dto.getBatchNo()); |
|||
transDetailSub.setPartNo(dto.getPartNo()); |
|||
transDetailSub.setSubNo(hu.getUnitId()); |
|||
transDetailSub.setOrderRef3(dto.getSequenceNo()); |
|||
transDetailSub.setDirection("-"); // 出库 |
|||
transDetailSubService.save(transDetailSub); |
|||
|
|||
// 更新HU状态 |
|||
hu.setInStockFlag("N"); // 退库后不在库 |
|||
hu.setStatus("WITHDRAWN"); |
|||
hu.setStatusDb("WITHDRAWN"); |
|||
hu.setModifiedDate(new Date()); |
|||
hu.setModifiedBy(currentUser.getUserDisplay()); |
|||
hu.setRemark("生产退库:" + transNo); |
|||
handlingUnitService.updateById(hu); |
|||
} |
|||
log.info("创建TransDetailSub成功,数量: {}", huList.size()); |
|||
|
|||
// 6. 扣减库存 |
|||
inventoryStockService.reduceStockWithLock( |
|||
dto.getSite(), |
|||
dto.getWarehouseId(), |
|||
dto.getPartNo(), |
|||
dto.getBatchNo(), |
|||
dto.getLocationNo(), |
|||
dto.getTransQty(), |
|||
"*" |
|||
); |
|||
log.info("扣减库存成功"); |
|||
|
|||
// 7. 调用IFS接口ManualUnreceiveShopOrder |
|||
callIfsManualUnreceiveShopOrder(dto, transNo); |
|||
log.info("=== 生产退库完成 === 事务号: {}", transNo); |
|||
|
|||
return transNo; |
|||
|
|||
} catch (Exception e) { |
|||
log.error("=== 生产退库失败 === 错误信息: {}", e.getMessage(), e); |
|||
throw new XJException("生产退库失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @Author System |
|||
* @Description 调用IFS接口ManualUnreceiveShopOrder |
|||
* @Date 2025/01/21 |
|||
* @Param [dto, transNo] |
|||
**/ |
|||
private void callIfsManualUnreceiveShopOrder(ShopOrderWithdrawalDto dto, String transNo) throws Exception { |
|||
log.info("=== 开始调用IFS ManualUnreceiveShopOrder接口 ==="); |
|||
|
|||
// 构建IFS接口参数 |
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("ifsDBName", ifsDBName); |
|||
params.put("domainUserID", domainUserID); |
|||
params.put("ifsContract", dto.getSite()); |
|||
params.put("ifsOrderNo", dto.getOrderNo()); |
|||
params.put("ifsReleaseNo", dto.getReleaseNo()); |
|||
params.put("ifsSequenceNo", dto.getSequenceNo()); |
|||
params.put("ifsPartNo", dto.getPartNo()); |
|||
params.put("ifsLocationNo", dto.getLocationNo()); |
|||
params.put("ifsLotBatchNo", dto.getBatchNo()); |
|||
params.put("ifsSerialNo", dto.getSerialNo() != null ? dto.getSerialNo() : "*"); |
|||
params.put("ifsEngChgLevel", dto.getEngChgLevel() != null ? dto.getEngChgLevel() : "1"); |
|||
params.put("ifsWDRNo", dto.getWdr() != null ? dto.getWdr() : "*"); |
|||
params.put("ifsTransactionQty", dto.getTransQty().doubleValue()); |
|||
params.put("ifsQtyReceived", dto.getQtyReceived().doubleValue()); |
|||
params.put("ifsAccountingID", dto.getAccountingId()); |
|||
params.put("ifsTransactionID", dto.getTransactionId()); |
|||
params.put("ifsLineItemNo", dto.getLineItemNo()); |
|||
|
|||
ObjectMapper objectMapper = new ObjectMapper(); |
|||
String jsonBody = objectMapper.writeValueAsString(params); |
|||
log.info("IFS请求参数: {}", jsonBody); |
|||
|
|||
String ifsResponse = HttpUtils.doPost(ifsUrl + "ManualUnreceiveShopOrder", jsonBody, null); |
|||
log.info("IFS响应: {}", ifsResponse); |
|||
|
|||
if ("IFSUpdated".equals(ifsResponse) || "\"IFSUpdated\"".equals(ifsResponse)) { |
|||
log.info("IFS生产退库成功"); |
|||
} else { |
|||
log.error("IFS生产退库失败: {}", ifsResponse); |
|||
String errorMessage = IfsErrorMessageUtils.extractOracleErrorMessage(ifsResponse); |
|||
throw new Exception(errorMessage); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue