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