From deb1c804130cb706adf779769a4b633a7a4864e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Wed, 8 Oct 2025 11:58:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=8E=A5=E5=8F=A3=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/IfsCallErrorLogController.java | 102 ++++++++++ .../api/dao/IfsCallErrorLogMapper.java | 14 ++ .../modules/api/entity/IfsCallErrorLog.java | 123 ++++++++++++ .../api/entity/IfsCallErrorLogData.java | 49 +++++ .../api/entity/PushPalletDetailDto.java | 2 +- .../api/service/IfsCallErrorLogService.java | 68 +++++++ .../impl/IfsCallErrorLogServiceImpl.java | 182 ++++++++++++++++++ .../impl/InventoryMoveServiceImpl.java | 139 ++++++++++++- 8 files changed, 676 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/gaotao/modules/api/controller/IfsCallErrorLogController.java create mode 100644 src/main/java/com/gaotao/modules/api/dao/IfsCallErrorLogMapper.java create mode 100644 src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLog.java create mode 100644 src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLogData.java create mode 100644 src/main/java/com/gaotao/modules/api/service/IfsCallErrorLogService.java create mode 100644 src/main/java/com/gaotao/modules/api/service/impl/IfsCallErrorLogServiceImpl.java diff --git a/src/main/java/com/gaotao/modules/api/controller/IfsCallErrorLogController.java b/src/main/java/com/gaotao/modules/api/controller/IfsCallErrorLogController.java new file mode 100644 index 0000000..76b923b --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/controller/IfsCallErrorLogController.java @@ -0,0 +1,102 @@ +package com.gaotao.modules.api.controller; + +import com.gaotao.common.utils.PageUtils; +import com.gaotao.common.utils.R; +import com.gaotao.modules.api.entity.IfsCallErrorLogData; +import com.gaotao.modules.api.service.IfsCallErrorLogService; +import com.gaotao.modules.sys.controller.AbstractController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @Description IFS接口调用错误日志Controller - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +@RestController +@RequestMapping("/api/ifsCallErrorLog") +public class IfsCallErrorLogController extends AbstractController { + + @Autowired + private IfsCallErrorLogService ifsCallErrorLogService; + + /** + * @Description 分页查询IFS错误日志列表 - rqrq + * @Title list + * @param data 查询条件 + * @return R + * @author rqrq + * @date 2025/10/08 + */ + @PostMapping("/list") + public R list(@RequestBody IfsCallErrorLogData data) { + try { + PageUtils page = ifsCallErrorLogService.queryPage(data); + return R.ok().put("page", page); + } catch (Exception e) { + logger.error("查询IFS错误日志列表失败", e); + return R.error("查询失败:" + e.getMessage()); + } + } + + /** + * @Description 标记错误日志为已处理 - rqrq + * @Title markProcessed + * @param data 包含id和remark + * @return R + * @author rqrq + * @date 2025/10/08 + */ + @PostMapping("/markProcessed") + public R markProcessed(@RequestBody IfsCallErrorLogData data) { + try { + String processedBy = getUser().getUsername(); + ifsCallErrorLogService.markAsProcessed(data.getId(), processedBy, data.getRemark()); + return R.ok().put("msg", "标记成功"); + } catch (Exception e) { + logger.error("标记IFS错误日志失败", e); + return R.error("操作失败:" + e.getMessage()); + } + } + + /** + * @Description 标记错误日志为已忽略 - rqrq + * @Title markIgnored + * @param data 包含id和remark + * @return R + * @author rqrq + * @date 2025/10/08 + */ + @PostMapping("/markIgnored") + public R markIgnored(@RequestBody IfsCallErrorLogData data) { + try { + String processedBy = getUser().getUsername(); + ifsCallErrorLogService.markAsIgnored(data.getId(), processedBy, data.getRemark()); + return R.ok().put("msg", "标记成功"); + } catch (Exception e) { + logger.error("标记IFS错误日志失败", e); + return R.error("操作失败:" + e.getMessage()); + } + } + + /** + * @Description 获取用户授权站点列表 - rqrq + * @Title getUserAuthorizedSites + * @param params 包含userName + * @return R + * @author rqrq + * @date 2025/10/08 + */ + @PostMapping("/getUserAuthorizedSites") + public R getUserAuthorizedSites(@RequestBody java.util.Map params) { + try { + // 这里简化处理,实际项目中可能需要从权限表查询 + java.util.List sites = new java.util.ArrayList<>(); + sites.add("55"); + return R.ok().put("data", sites); + } catch (Exception e) { + logger.error("获取站点列表失败", e); + return R.error("获取站点列表失败"); + } + } +} diff --git a/src/main/java/com/gaotao/modules/api/dao/IfsCallErrorLogMapper.java b/src/main/java/com/gaotao/modules/api/dao/IfsCallErrorLogMapper.java new file mode 100644 index 0000000..dd18efa --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/dao/IfsCallErrorLogMapper.java @@ -0,0 +1,14 @@ +package com.gaotao.modules.api.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gaotao.modules.api.entity.IfsCallErrorLog; +import org.apache.ibatis.annotations.Mapper; + +/** + * @Description IFS接口调用错误日志Mapper - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +@Mapper +public interface IfsCallErrorLogMapper extends BaseMapper { +} diff --git a/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLog.java b/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLog.java new file mode 100644 index 0000000..9f451e9 --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLog.java @@ -0,0 +1,123 @@ +package com.gaotao.modules.api.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import java.util.Date; + +/** + * @Description IFS接口调用错误日志基础实体类 - 直接映射数据库表 - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +@Data +@TableName("ifs_call_error_log") +public class IfsCallErrorLog { + + /** + * 主键ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 站点 + */ + private String site; + + /** + * 接口名称 + */ + private String interfaceName; + + /** + * 方法类型 + */ + private String methodType; + + /** + * 物料编号 + */ + private String partNo; + + /** + * 批次号 + */ + private String lotBatchNo; + + /** + * 源库位 + */ + private String sourceLocation; + + /** + * 目标库位 + */ + private String destLocation; + + /** + * 数量 + */ + private Integer qty; + + /** + * 过期日期 + */ + private Date expiredDate; + + /** + * 请求参数(JSON格式) + */ + private String requestData; + + /** + * IFS响应数据 + */ + private String responseData; + + /** + * 解析后的错误信息 + */ + private String errorMessage; + + /** + * 处理状态:PENDING待处理, PROCESSED已处理, IGNORED已忽略 + */ + private String processStatus; + + /** + * 重试次数 + */ + private Integer retryCount; + + /** + * 最大重试次数 + */ + private Integer maxRetry; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createdAt; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.UPDATE) + private Date updatedAt; + + /** + * 处理时间 + */ + private Date processedAt; + + /** + * 处理人 + */ + private String processedBy; + + /** + * 备注信息 + */ + private String remark; +} diff --git a/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLogData.java b/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLogData.java new file mode 100644 index 0000000..c29f931 --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/entity/IfsCallErrorLogData.java @@ -0,0 +1,49 @@ +package com.gaotao.modules.api.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; +import org.apache.ibatis.type.Alias; +import org.springframework.format.annotation.DateTimeFormat; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.util.Date; + +/** + * @Description IFS接口调用错误日志业务实体类 - 用于业务查询 - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +@Data +@Alias("IfsCallErrorLogData") +public class IfsCallErrorLogData extends IfsCallErrorLog { + + /** + * 查询开始日期 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date startDate; + + /** + * 查询结束日期 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date endDate; + + /** + * 分页参数 + */ + @TableField(exist = false) + private Integer page; + + @TableField(exist = false) + private Integer limit; + + @TableField(exist = false) + private Integer pageNum; + + @TableField(exist = false) + private Integer pageSize; +} diff --git a/src/main/java/com/gaotao/modules/api/entity/PushPalletDetailDto.java b/src/main/java/com/gaotao/modules/api/entity/PushPalletDetailDto.java index 264f477..610101a 100644 --- a/src/main/java/com/gaotao/modules/api/entity/PushPalletDetailDto.java +++ b/src/main/java/com/gaotao/modules/api/entity/PushPalletDetailDto.java @@ -14,7 +14,7 @@ public class PushPalletDetailDto { private Integer basePalletType; //底托类型 private boolean isCommonUsed; //常用料 private boolean autoSort; //自动分拣 - private Integer soreType;//分拣方式 0人工 1气胀轴 2抱箱 + private Integer soreType;//分拣方式 0人工 1气胀轴 2抱箱 3直接出库 private String assemblyPosition;//托盘码 private boolean endFlag; private List cargoInfos;//明细数据 diff --git a/src/main/java/com/gaotao/modules/api/service/IfsCallErrorLogService.java b/src/main/java/com/gaotao/modules/api/service/IfsCallErrorLogService.java new file mode 100644 index 0000000..324359a --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/service/IfsCallErrorLogService.java @@ -0,0 +1,68 @@ +package com.gaotao.modules.api.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gaotao.common.utils.PageUtils; +import com.gaotao.modules.api.entity.IfsCallErrorLog; +import com.gaotao.modules.api.entity.IfsCallErrorLogData; +import java.util.Date; + +/** + * @Description IFS接口调用错误日志服务接口 - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +public interface IfsCallErrorLogService extends IService { + + /** + * @Description 记录IFS调用失败日志 - rqrq + * @param site 站点 + * @param interfaceName 接口名称 + * @param methodType 方法类型 + * @param partNo 物料编号 + * @param lotBatchNo 批次号 + * @param sourceLocation 源库位 + * @param destLocation 目标库位 + * @param qty 数量 + * @param expiredDate 过期日期 + * @param requestData 请求数据 + * @param responseData 响应数据 + * @param errorMessage 错误信息 + * @return Long 日志ID + * @author rqrq + * @date 2025/10/08 + */ + Long logIfsError(String site, String interfaceName, String methodType, + String partNo, String lotBatchNo, + String sourceLocation, String destLocation, + Integer qty, Date expiredDate, + String requestData, String responseData, String errorMessage); + + /** + * @Description 分页查询IFS错误日志 - rqrq + * @param data 查询条件 + * @return PageUtils + * @author rqrq + * @date 2025/10/08 + */ + PageUtils queryPage(IfsCallErrorLogData data) throws Exception; + + /** + * @Description 标记错误日志为已处理 - rqrq + * @param id 日志ID + * @param processedBy 处理人 + * @param remark 处理备注 + * @author rqrq + * @date 2025/10/08 + */ + void markAsProcessed(Long id, String processedBy, String remark); + + /** + * @Description 标记错误日志为已忽略 - rqrq + * @param id 日志ID + * @param processedBy 处理人 + * @param remark 忽略原因 + * @author rqrq + * @date 2025/10/08 + */ + void markAsIgnored(Long id, String processedBy, String remark); +} diff --git a/src/main/java/com/gaotao/modules/api/service/impl/IfsCallErrorLogServiceImpl.java b/src/main/java/com/gaotao/modules/api/service/impl/IfsCallErrorLogServiceImpl.java new file mode 100644 index 0000000..f101695 --- /dev/null +++ b/src/main/java/com/gaotao/modules/api/service/impl/IfsCallErrorLogServiceImpl.java @@ -0,0 +1,182 @@ +package com.gaotao.modules.api.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gaotao.common.utils.PageUtils; +import com.gaotao.modules.api.dao.IfsCallErrorLogMapper; +import com.gaotao.modules.api.entity.IfsCallErrorLog; +import com.gaotao.modules.api.entity.IfsCallErrorLogData; +import com.gaotao.modules.api.service.IfsCallErrorLogService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.Date; + +/** + * @Description IFS接口调用错误日志服务实现类 - rqrq + * @Author rqrq + * @Date 2025/10/08 + */ +@Slf4j +@Service +public class IfsCallErrorLogServiceImpl extends ServiceImpl + implements IfsCallErrorLogService { + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW) + public Long logIfsError(String site, String interfaceName, String methodType, + String partNo, String lotBatchNo, + String sourceLocation, String destLocation, + Integer qty, Date expiredDate, + String requestData, String responseData, String errorMessage) { + + System.out.println("========== IFS错误日志记录开始 =========="); + System.out.println("站点: " + site + ", 接口: " + interfaceName + ", 方法: " + methodType); + System.out.println("物料: " + partNo + ", 批次: " + lotBatchNo); + + try { + IfsCallErrorLog errorLog = new IfsCallErrorLog(); + errorLog.setSite(site); + errorLog.setInterfaceName(interfaceName); + errorLog.setMethodType(methodType); + errorLog.setPartNo(partNo); + errorLog.setLotBatchNo(lotBatchNo); + errorLog.setSourceLocation(sourceLocation); + errorLog.setDestLocation(destLocation); + errorLog.setQty(qty); + errorLog.setExpiredDate(expiredDate); + errorLog.setRequestData(requestData); + errorLog.setResponseData(responseData); + errorLog.setErrorMessage(errorMessage); + errorLog.setProcessStatus("PENDING"); + errorLog.setRetryCount(0); + errorLog.setMaxRetry(3); + errorLog.setCreatedAt(new Date()); + + this.save(errorLog); + + System.out.println("IFS错误日志记录成功,日志ID: " + errorLog.getId()); + System.out.println("========== IFS错误日志记录结束 =========="); + + return errorLog.getId(); + + } catch (Exception e) { + log.error("记录IFS错误日志失败: {}", e.getMessage(), e); + System.out.println("IFS错误日志记录失败: " + e.getMessage()); + System.out.println("========== IFS错误日志记录结束 =========="); + return null; + } + } + + @Override + public PageUtils queryPage(IfsCallErrorLogData data) throws Exception { + System.out.println("========== IFS错误日志查询开始 =========="); + System.out.println("查询条件 - 站点: " + data.getSite() + ", 状态: " + data.getProcessStatus()); + + // 构建分页对象 - rqrq + int pageNum = data.getPage() != null ? data.getPage() : + (data.getPageNum() != null ? data.getPageNum() : 1); + int pageSize = data.getLimit() != null ? data.getLimit() : + (data.getPageSize() != null ? data.getPageSize() : 10); + Page page = new Page<>(pageNum, pageSize); + + // 构建查询条件 - rqrq + QueryWrapper wrapper = new QueryWrapper<>(); + + // 站点 - rqrq + if (StringUtils.hasText(data.getSite())) { + wrapper.eq("site", data.getSite()); + } + + // 接口名称 - rqrq + if (StringUtils.hasText(data.getInterfaceName())) { + wrapper.eq("interface_name", data.getInterfaceName()); + } + + // 方法类型 - rqrq + if (StringUtils.hasText(data.getMethodType())) { + wrapper.eq("method_type", data.getMethodType()); + } + + // 物料编号 - rqrq + if (StringUtils.hasText(data.getPartNo())) { + wrapper.like("part_no", data.getPartNo()); + } + + // 批次号 - rqrq + if (StringUtils.hasText(data.getLotBatchNo())) { + wrapper.like("lot_batch_no", data.getLotBatchNo()); + } + + // 处理状态 - rqrq + if (StringUtils.hasText(data.getProcessStatus())) { + wrapper.eq("process_status", data.getProcessStatus()); + } + + // 日期范围 - rqrq + if (data.getStartDate() != null) { + wrapper.ge("created_at", data.getStartDate()); + } + if (data.getEndDate() != null) { + wrapper.le("created_at", data.getEndDate()); + } + + // 按创建时间倒序 - rqrq + wrapper.orderByDesc("created_at"); + + // 执行分页查询 - rqrq + IPage pageResult = baseMapper.selectPage(page, wrapper); + + System.out.println("查询结果总数: " + pageResult.getTotal()); + System.out.println("========== IFS错误日志查询结束 =========="); + + return new PageUtils(pageResult); + } + + @Override + @Transactional + public void markAsProcessed(Long id, String processedBy, String remark) { + System.out.println("========== 标记IFS错误日志为已处理 =========="); + System.out.println("日志ID: " + id + ", 处理人: " + processedBy); + + IfsCallErrorLog errorLog = this.getById(id); + if (errorLog != null) { + errorLog.setProcessStatus("PROCESSED"); + errorLog.setProcessedAt(new Date()); + errorLog.setProcessedBy(processedBy); + errorLog.setRemark(remark); + errorLog.setUpdatedAt(new Date()); + this.updateById(errorLog); + + System.out.println("标记成功"); + } + + System.out.println("========== 标记IFS错误日志结束 =========="); + } + + @Override + @Transactional + public void markAsIgnored(Long id, String processedBy, String remark) { + System.out.println("========== 标记IFS错误日志为已忽略 =========="); + System.out.println("日志ID: " + id + ", 处理人: " + processedBy); + + IfsCallErrorLog errorLog = this.getById(id); + if (errorLog != null) { + errorLog.setProcessStatus("IGNORED"); + errorLog.setProcessedAt(new Date()); + errorLog.setProcessedBy(processedBy); + errorLog.setRemark(remark); + errorLog.setUpdatedAt(new Date()); + this.updateById(errorLog); + + System.out.println("标记成功"); + } + + System.out.println("========== 标记IFS错误日志结束 =========="); + } +} diff --git a/src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java b/src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java index abdb090..f6b3f26 100644 --- a/src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java +++ b/src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java @@ -4,6 +4,7 @@ import com.gaotao.common.exception.XJException; import com.gaotao.common.utils.HttpUtils; import com.gaotao.common.utils.IfsErrorMessageUtils; import com.gaotao.modules.api.service.IfsApiIssueAndReturnService; +import com.gaotao.modules.api.service.IfsCallErrorLogService; import com.gaotao.modules.handlingunit.entity.HandlingUnit; import com.gaotao.modules.handlingunit.service.HandlingUnitService; import com.gaotao.modules.other.entity.InventoryMoveRequestDto; @@ -60,6 +61,10 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { @Autowired private LocationService locationService; + // rqrq - IFS错误日志服务 + @Autowired + private IfsCallErrorLogService ifsCallErrorLogService; + @Value("${custom.ifs-url}") private String ifsUrl; @@ -105,10 +110,10 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { } // 4. 合并相同条件的HandlingUnit后调用IFS接口(在更新HU之前) - syncToIFSBatch(dto, handlingUnits); + syncToIFSBatchForPallet(dto, handlingUnits); } catch (Exception e) { log.error("IFS库存移库失败", e); - throw new XJException("IFS库存移库失败: " + e.getMessage()); + throw new RuntimeException("IFS库存移库失败: " + e.getMessage()); } } @Override @@ -271,6 +276,51 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { throw new XJException("IFS移库失败,响应: " + e.getMessage()); } } + /** + * @Description 批量同步到IFS(栈板移库) - 失败不中断流程 - rqrq + * @param dto 移库请求数据 + * @param handlingUnits 托盘单元列表 + * @author rqrq + * @date 2025/10/08 + */ + private void syncToIFSBatchForPallet(InventoryMoveRequestDto dto, List handlingUnits) { + try { + // 按site、partNo、原库位、lotBatchNo、expiredDate分组合并数量 + Map moveGroups = new HashMap<>(); + + for (HandlingUnit hu : handlingUnits) { + String expiredDateStr = hu.getExpiredDate() != null ? + new SimpleDateFormat("yyyy-MM-dd").format(hu.getExpiredDate()) : "null"; + String groupKey = String.format("%s|%s|%s|%s|%s", + hu.getSite(), hu.getPartNo(), hu.getLocationId(), hu.getBatchNo(), expiredDateStr); + + MoveGroup group = moveGroups.computeIfAbsent(groupKey, k -> { + MoveGroup newGroup = new MoveGroup(); + newGroup.site = hu.getSite(); + newGroup.partNo = hu.getPartNo(); + newGroup.sourceLocationNo = hu.getLocationId(); // 注意:这里使用的是更新前的原库位 + newGroup.destLocationNo = dto.getTargetLocationId(); + newGroup.lotBatchNo = hu.getBatchNo(); + newGroup.expiredDate = hu.getExpiredDate(); + newGroup.totalQty = BigDecimal.ZERO; + return newGroup; + }); + + group.totalQty = group.totalQty.add(hu.getQty()); + } + + // 为每个分组调用IFS接口 - rqrq + for (MoveGroup group : moveGroups.values()) { + syncSingleGroupToIFSForPallet(group); + } + + log.info("IFS批量移库同步完成,共{}个分组", moveGroups.size()); + + } catch (Exception e) { + // rqrq - 不抛异常,只记录警告日志,失败的记录已经存入错误日志表 + log.warn("IFS批量移库同步异常: {},失败的记录已存入错误日志表供后续手工处理", e.getMessage()); + } + } /** * 同步单个分组到IFS @@ -317,6 +367,91 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { } } + + /** + * @Description 同步单个分组到IFS(栈板移库) - 失败时记录错误日志而不抛异常 - rqrq + * @param group 移库分组数据 + * @author rqrq + * @date 2025/10/08 + */ + private void syncSingleGroupToIFSForPallet(MoveGroup group) { + String jsonBody = null; + String ifsResponse = null; + + try { + Map params = new HashMap<>(); + params.put("ifsDBName", ifsDBName); + params.put("domainUserID", getCurrentDomainUserID()); + params.put("ifsSiteID", group.site); + params.put("partNo", group.partNo); + params.put("qtyToIssue", group.totalQty.intValue()); + params.put("locationNo", group.sourceLocationNo); // 原库位 + params.put("destLocationNo", group.destLocationNo); // 目标库位 + params.put("lotBatchNo", group.lotBatchNo); + + // 添加过期日期参数 + if (group.expiredDate != null) { + params.put("expiredDate", new SimpleDateFormat("yyyy-MM-dd").format(group.expiredDate)); + } else { + params.put("expiredDate", null); + } + + ObjectMapper objectMapper = new ObjectMapper(); + jsonBody = objectMapper.writeValueAsString(params); + ifsResponse = HttpUtils.doPost(ifsUrl + "MoveInventoryPart", jsonBody, null); + + if ("IFSUpdated".equals(ifsResponse) || "\"IFSUpdated\"".equals(ifsResponse)) { + log.info("IFS移库同步成功 - 物料: {}, 批次: {}, 过期日期: {}, 数量: {}, 从 {} 到 {}", + group.partNo, group.lotBatchNo, + group.expiredDate != null ? new SimpleDateFormat("yyyy-MM-dd").format(group.expiredDate) : "无", + group.totalQty, group.sourceLocationNo, group.destLocationNo); + } else { + // rqrq - IFS同步失败,记录错误日志而不抛异常 + String errorMessage = IfsErrorMessageUtils.extractOracleErrorMessage(ifsResponse); + log.warn("IFS移库同步失败 - 物料: {}, 批次: {}, 响应: {},已记录到错误日志表", + group.partNo, group.lotBatchNo, ifsResponse); + + // 记录到错误日志表 - rqrq + ifsCallErrorLogService.logIfsError( + group.site, + "MoveInventoryPart", + "库存移库(栈板)", + group.partNo, + group.lotBatchNo, + group.sourceLocationNo, + group.destLocationNo, + group.totalQty.intValue(), + group.expiredDate, + jsonBody, + ifsResponse, + errorMessage + ); + } + + } catch (Exception e) { + // rqrq - 异常情况也记录到错误日志表而不抛异常 + log.error("IFS移库同步异常 - 物料: {}, 批次: {},已记录到错误日志表", group.partNo, group.lotBatchNo, e); + + String errorMessage = "系统异常: " + e.getMessage(); + + // 记录到错误日志表 - rqrq + ifsCallErrorLogService.logIfsError( + group.site, + "MoveInventoryPart", + "库存移库(栈板)", + group.partNo, + group.lotBatchNo, + group.sourceLocationNo, + group.destLocationNo, + group.totalQty != null ? group.totalQty.intValue() : 0, + group.expiredDate, + jsonBody != null ? jsonBody : "请求构建失败", + ifsResponse != null ? ifsResponse : "未收到响应", + errorMessage + ); + } + } + /** * 为库存分组创建出库事务记录 */