From b1f026a5d987a68cfc5ebdbfc08496bb0121d744 Mon Sep 17 00:00:00 2001 From: yangk Date: Mon, 6 Jul 2026 11:24:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(asset):=20=E5=9C=A8=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E6=8A=A5=E5=BA=9F=E7=A1=AE=E8=AE=A4=E6=97=B6=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E4=BD=9C=E5=BA=9F=E5=BD=93=E5=89=8D=E7=BB=91=E5=AE=9A=E7=9A=84?= =?UTF-8?q?RFID=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 保留RFID标签与报废资产的绑定快照用于后续追溯 - 新增lockBoundRfidTags方法锁定待作废的RFID标签 - 新增voidBoundRfidTagByAssetId数据库操作防止并发冲突 - 更新前端提示信息明确报废操作对RFID标签的影响 - 修改资产流转服务职责,将标签作废处理移至报废单服务 --- .../ruoyi/asset/mapper/AmsRfidTagMapper.java | 30 +++++++ .../IAssetStatusTransitionService.java | 2 +- .../impl/AmsDisposalOrderServiceImpl.java | 61 +++++++++++++- .../mapper/asset/AmsRfidTagMapper.xml | 30 +++++++ .../templates/asset/disposal/disposal.html | 2 +- .../impl/AmsDisposalOrderServiceImplTest.java | 84 ++++++++++++++++++- .../AssetStatusTransitionServiceImplTest.java | 2 +- 7 files changed, 205 insertions(+), 6 deletions(-) diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsRfidTagMapper.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsRfidTagMapper.java index b1a6d6c..4f13527 100644 --- a/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsRfidTagMapper.java +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/mapper/AmsRfidTagMapper.java @@ -37,6 +37,14 @@ public interface AmsRfidTagMapper */ public AmsRfidTag selectAmsRfidTagByEpcForUpdate(String epcCode); + /** + * 按EPC查询RFID标签 + * + * @param epcCode EPC编码 + * @return RFID标签 + */ + public AmsRfidTag selectAmsRfidTagByEpc(String epcCode); + /** * 查询RFID标签列表 * @@ -53,6 +61,14 @@ public interface AmsRfidTagMapper */ public List selectAmsRfidTagByEpcCodes(@Param("epcCodes") List epcCodes); + /** + * 按资产ID批量锁定当前已绑定的RFID标签 + * + * @param assetIds 资产ID集合 + * @return RFID标签集合 + */ + public List selectBoundAmsRfidTagsByAssetIdsForUpdate(@Param("assetIds") List assetIds); + /** * 校验标签编码是否唯一 * @@ -105,6 +121,20 @@ public interface AmsRfidTagMapper @Param("updateBy") String updateBy, @Param("updateTime") Date updateTime); + /** + * 报废资产时作废当前绑定的RFID标签,保留绑定快照 + * + * @param tagId RFID标签主键 + * @param assetId 当前绑定资产ID + * @param updateBy 更新人 + * @param updateTime 更新时间 + * @return 结果 + */ + public int voidBoundAmsRfidTagByAssetId(@Param("tagId") Long tagId, + @Param("assetId") Long assetId, + @Param("updateBy") String updateBy, + @Param("updateTime") Date updateTime); + /** * 清空RFID标签当前绑定资产 * diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAssetStatusTransitionService.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAssetStatusTransitionService.java index 918d8b0..3649be7 100644 --- a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAssetStatusTransitionService.java +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/IAssetStatusTransitionService.java @@ -106,7 +106,7 @@ public interface IAssetStatusTransitionService /** * 确认资产报废:IN_STOCK/IN_USE → DISPOSED - *

报废不清除 RFID 绑定关系,保留标签溯源能力。

+ *

本服务只负责资产状态流转并保留 RFID 绑定快照;绑定标签作废由报废单服务统一处理。

* * @param assetId 资产ID * @param context 流转操作上下文 diff --git a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalOrderServiceImpl.java b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalOrderServiceImpl.java index 713621a..6425b9f 100644 --- a/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalOrderServiceImpl.java +++ b/ruoyi-asset/src/main/java/com/ruoyi/asset/service/impl/AmsDisposalOrderServiceImpl.java @@ -2,8 +2,10 @@ package com.ruoyi.asset.service.impl; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,9 +15,11 @@ import com.ruoyi.asset.domain.AmsAsset; import com.ruoyi.asset.domain.AmsDisposalOperateContext; import com.ruoyi.asset.domain.AmsDisposalOrder; import com.ruoyi.asset.domain.AmsDisposalOrderItem; +import com.ruoyi.asset.domain.AmsRfidTag; import com.ruoyi.asset.domain.AssetTransitionContext; import com.ruoyi.asset.mapper.AmsAssetMapper; import com.ruoyi.asset.mapper.AmsDisposalOrderMapper; +import com.ruoyi.asset.mapper.AmsRfidTagMapper; import com.ruoyi.asset.service.IAmsDisposalOrderService; import com.ruoyi.asset.service.IAssetStatusTransitionService; import com.ruoyi.common.core.text.Convert; @@ -48,6 +52,9 @@ public class AmsDisposalOrderServiceImpl implements IAmsDisposalOrderService @Autowired private AmsAssetMapper amsAssetMapper; + @Autowired + private AmsRfidTagMapper amsRfidTagMapper; + @Autowired private ISysCodeRuleService sysCodeRuleService; @@ -264,6 +271,7 @@ public class AmsDisposalOrderServiceImpl implements IAmsDisposalOrderService AmsDisposalOrder order = requireOrderForUpdate(orderId, DisposalOrderStatus.PENDING_CONFIRM, "仅待确认状态的报废单允许确认报废"); // 2. 升序加锁校验资产状态及跨单占用 + List boundTags = lockBoundRfidTags(order); validateOrderAssetsReady(order); Date now = DateUtils.getNowDate(); @@ -281,11 +289,14 @@ public class AmsDisposalOrderServiceImpl implements IAmsDisposalOrderService context.setChangeSummary("确认资产报废"); context.setRemark(item.getDisposalRemark()); - // 变更资产状态为 DISPOSED 写入资产履历,报废不清除 RFID 绑定 + // 报废只终止标签继续流转,不清空绑定快照,便于后续追溯报废资产原 RFID 标签。 assetStatusTransitionService.confirmDisposal(item.getAssetId(), context); } - // 4. 回填确认属性,变更为已报废状态 + // 4. 同步作废当前绑定标签,保留标签与报废资产的绑定快照用于追溯。 + voidBoundRfidTags(boundTags, operateContext, now); + + // 5. 回填确认属性,变更为已报废状态 order.setConfirmUserId(operateContext.getOperateUserId()); order.setConfirmUserName(StringUtils.trim(operateContext.getOperateUserName())); order.setConfirmTime(now); @@ -385,6 +396,52 @@ public class AmsDisposalOrderServiceImpl implements IAmsDisposalOrderService return 1; } + private List lockBoundRfidTags(AmsDisposalOrder order) + { + List assetIds = collectSortedAssetIds(order); + if (assetIds.isEmpty()) + { + return Collections.emptyList(); + } + List tags = amsRfidTagMapper.selectBoundAmsRfidTagsByAssetIdsForUpdate(assetIds); + return tags == null ? Collections.emptyList() : tags; + } + + private List collectSortedAssetIds(AmsDisposalOrder order) + { + if (order == null || order.getAmsDisposalOrderItemList() == null) + { + return Collections.emptyList(); + } + return order.getAmsDisposalOrderItemList().stream() + .filter(item -> item != null && item.getAssetId() != null) + .map(AmsDisposalOrderItem::getAssetId) + .distinct() + .sorted() + .collect(Collectors.toList()); + } + + private void voidBoundRfidTags(List boundTags, + AmsDisposalOperateContext operateContext, Date operateTime) + { + if (boundTags == null || boundTags.isEmpty()) + { + return; + } + for (AmsRfidTag tag : boundTags) + { + if (tag == null || tag.getTagId() == null || tag.getAssetId() == null) + { + throw new ServiceException("RFID标签绑定信息不完整,报废确认失败"); + } + if (amsRfidTagMapper.voidBoundAmsRfidTagByAssetId(tag.getTagId(), tag.getAssetId(), + operateContext.getOperateLoginName(), operateTime) != 1) + { + throw new ServiceException(StringUtils.format("RFID标签【{}】状态已变化,报废确认失败", tag.getTagCode())); + } + } + } + private void validateOrderRequest(AmsDisposalOrder order) { if (order == null) diff --git a/ruoyi-asset/src/main/resources/mapper/asset/AmsRfidTagMapper.xml b/ruoyi-asset/src/main/resources/mapper/asset/AmsRfidTagMapper.xml index 68df626..41744d5 100644 --- a/ruoyi-asset/src/main/resources/mapper/asset/AmsRfidTagMapper.xml +++ b/ruoyi-asset/src/main/resources/mapper/asset/AmsRfidTagMapper.xml @@ -62,6 +62,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" for update + + + +