feat(asset): 调整资产调拨功能范围(仅允许在库资产调拨),移除部门和使用人相关字段

- 移除调拨单中的部门和使用人相关字段,包括原部门、新部门、原使用人、新使用人
- 更新调拨单新增和编辑页面,删除部门和使用人的下拉选择组件
- 修改数据库查询逻辑,调拨单只支持在库资产的仓库和位置变更
- 更新服务层实现,移除部门和使用人的验证和处理逻辑
- 调整测试用例以匹配新的调拨单功能范围
- 优化调拨单查看页面,移除不再使用的部门和使用人显示列
- 更新资产选择弹窗,过滤掉在用状态的资产只显示在库资产
main
yangk 1 week ago
parent 42c5bfa275
commit 2a704304d2

@ -9,16 +9,11 @@ import com.ruoyi.asset.service.IAmsAssetLocationService;
import com.ruoyi.asset.service.IAmsTransferOrderService;
import com.ruoyi.asset.service.IAmsWarehouseService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
@ -53,12 +48,6 @@ public class AmsTransferOrderController extends BaseController
@Autowired
private IAmsAssetLocationService amsAssetLocationService;
@Autowired
private ISysDeptService sysDeptService;
@Autowired
private ISysUserService sysUserService;
@RequiresPermissions("asset:transfer:view")
@GetMapping()
public String transfer(ModelMap mmap)
@ -85,7 +74,7 @@ public class AmsTransferOrderController extends BaseController
return prefix + "/selectAsset";
}
/** 分页查询未被其他有效调拨单占用的在库/在用资产(仅返回可调拨资产) */
/** 分页查询未被其他有效调拨单占用的在库资产(仅返回可调拨资产) */
@RequiresPermissions(value = { "asset:transfer:add", "asset:transfer:edit" }, logical = Logical.OR)
@PostMapping("/availableAssetList")
@ResponseBody
@ -182,7 +171,7 @@ public class AmsTransferOrderController extends BaseController
return toAjax(amsTransferOrderService.deleteAmsTransferOrderByOrderIds(ids));
}
/** 调拨表单需要仓库、位置、部门、用户四组下拉选项 */
/** 调拨表单只需要仓库和位置选项。 */
private void putTransferOptions(ModelMap mmap)
{
mmap.put("warehouseList", selectEnabledWarehouseList());
@ -191,13 +180,6 @@ public class AmsTransferOrderController extends BaseController
location.setEnabled(ENABLED_YES);
mmap.put("locationList", amsAssetLocationService.selectAmsAssetLocationList(location));
SysDept dept = new SysDept();
dept.setStatus(UserConstants.DEPT_NORMAL);
mmap.put("deptList", sysDeptService.selectDeptList(dept));
SysUser user = new SysUser();
user.setStatus(UserConstants.NORMAL);
mmap.put("userList", sysUserService.selectUserList(user));
}
private List<AmsWarehouse> selectEnabledWarehouseList()

@ -61,36 +61,28 @@ public class AmsTransferOrderItem extends BaseEntity
/** 当前资产状态,仅用于调拨表单展示和校验,不写入调拨明细表(由 LEFT JOIN 实时查询) */
private String assetStatus;
/** 原部门ID */
@Excel(name = "原部门ID")
/** 原部门ID兼容保留一期调拨不使用 */
private Long oldDeptId;
/** 原部门名称快照 */
@Excel(name = "原部门名称快照")
/** 原部门名称快照(兼容保留,一期调拨不使用) */
private String oldDeptName;
/** 新部门ID */
@Excel(name = "新部门ID")
/** 新部门ID兼容保留一期调拨不使用 */
private Long newDeptId;
/** 新部门名称快照 */
@Excel(name = "新部门名称快照")
/** 新部门名称快照(兼容保留,一期调拨不使用) */
private String newDeptName;
/** 原使用人ID */
@Excel(name = "原使用人ID")
/** 原使用人ID兼容保留一期调拨不使用 */
private Long oldUserId;
/** 原使用人名称快照 */
@Excel(name = "原使用人名称快照")
/** 原使用人名称快照(兼容保留,一期调拨不使用) */
private String oldUserName;
/** 新使用人ID */
@Excel(name = "新使用人ID")
/** 新使用人ID兼容保留一期调拨不使用 */
private Long newUserId;
/** 新使用人名称快照 */
@Excel(name = "新使用人名称快照")
/** 新使用人名称快照(兼容保留,一期调拨不使用) */
private String newUserName;
/** 原仓库ID */

@ -36,13 +36,11 @@ public interface AmsTransferOrderMapper
public List<AmsTransferOrder> selectAmsTransferOrderList(AmsTransferOrder amsTransferOrder);
/**
* 使
* <p> IN_STOCK IN_USE 稿</p>
* 使
*/
public List<AmsAsset> selectAvailableTransferAssetList(@Param("asset") AmsAsset amsAsset,
@Param("currentOrderId") Long currentOrderId, @Param("stockStatus") String stockStatus,
@Param("inUseStatus") String inUseStatus, @Param("draftStatus") String draftStatus,
@Param("pendingStatus") String pendingStatus);
@Param("draftStatus") String draftStatus, @Param("pendingStatus") String pendingStatus);
/**
* 稿+

@ -29,8 +29,8 @@ public interface IAmsTransferOrderService
public List<AmsTransferOrder> selectAmsTransferOrderList(AmsTransferOrder amsTransferOrder);
/**
*
* <p> IN_STOCK IN_USE
*
* <p> IN_STOCK
* /使</p>
*
* @param amsAsset

@ -22,16 +22,11 @@ import com.ruoyi.asset.service.IAmsAssetLocationService;
import com.ruoyi.asset.service.IAmsTransferOrderService;
import com.ruoyi.asset.service.IAmsWarehouseService;
import com.ruoyi.asset.service.IAssetStatusTransitionService;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysCodeRuleService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -66,12 +61,6 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
@Autowired
private IAmsAssetLocationService amsAssetLocationService;
@Autowired
private ISysDeptService sysDeptService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private IAssetStatusTransitionService assetStatusTransitionService;
@ -92,8 +81,7 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
public List<AmsAsset> selectAvailableTransferAssetList(AmsAsset amsAsset, Long currentOrderId)
{
return amsTransferOrderMapper.selectAvailableTransferAssetList(amsAsset, currentOrderId,
AssetStatus.IN_STOCK, AssetStatus.IN_USE, TransferOrderStatus.DRAFT,
TransferOrderStatus.PENDING_CONFIRM);
AssetStatus.IN_STOCK, TransferOrderStatus.DRAFT, TransferOrderStatus.PENDING_CONFIRM);
}
/**
@ -211,7 +199,7 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
context.setChangeSummary("确认资产调拨");
context.setRemark(order.getRemark());
assetStatusTransitionService.confirmTransfer(item.getAssetId(), item.getNewWarehouseId(),
item.getNewLocationId(), item.getNewDeptId(), item.getNewUserId(), context);
item.getNewLocationId(), context);
}
Date now = DateUtils.getNowDate();
@ -328,7 +316,7 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
}
}
/** 加行锁并校验资产为可调拨状态(在库或在用),同时校验仓位和使用归属完整性。 */
/** 加行锁并校验资产为可调拨的在库状态,同时校验仓位和使用归属完整性。 */
private AmsAsset lockTransferableAsset(Long assetId)
{
if (StringUtils.isNull(assetId))
@ -340,7 +328,7 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
{
throw new ServiceException("调拨资产不存在或已删除");
}
if (!StringUtils.equalsAny(asset.getAssetStatus(), AssetStatus.IN_STOCK, AssetStatus.IN_USE))
if (!StringUtils.equals(asset.getAssetStatus(), AssetStatus.IN_STOCK))
{
throw new ServiceException(StringUtils.format("资产【{}】当前状态不允许调拨", asset.getAssetCode()));
}
@ -348,10 +336,10 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
{
throw new ServiceException(StringUtils.format("资产【{}】缺少当前仓库或位置", asset.getAssetCode()));
}
if (StringUtils.equals(AssetStatus.IN_USE, asset.getAssetStatus())
&& (StringUtils.isNull(asset.getUseDeptId()) || StringUtils.isNull(asset.getUseUserId())))
if (StringUtils.isNotNull(asset.getUseDeptId()) || StringUtils.isNotNull(asset.getUseUserId())
|| StringUtils.isNotEmpty(asset.getUseDeptName()) || StringUtils.isNotEmpty(asset.getUseUserName()))
{
throw new ServiceException(StringUtils.format("在用资产【{}】缺少当前使用部门或使用人", asset.getAssetCode()));
throw new ServiceException(StringUtils.format("在库资产【{}】仍存在使用归属,请先修正后再调拨", asset.getAssetCode()));
}
return asset;
}
@ -377,10 +365,10 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
item.setSpecModel(asset.getSpecModel());
item.setBrand(asset.getBrand());
item.setAssetStatus(asset.getAssetStatus());
item.setOldDeptId(asset.getUseDeptId());
item.setOldDeptName(asset.getUseDeptName());
item.setOldUserId(asset.getUseUserId());
item.setOldUserName(asset.getUseUserName());
item.setOldDeptId(null);
item.setOldDeptName(null);
item.setOldUserId(null);
item.setOldUserName(null);
item.setOldWarehouseId(asset.getWarehouseId());
item.setOldWarehouseCode(asset.getWarehouseCode());
item.setOldWarehouseName(asset.getWarehouseName());
@ -407,34 +395,17 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
item.setNewLocationCode(location.getLocationCode());
item.setNewLocationName(location.getLocationName());
if (StringUtils.equals(AssetStatus.IN_USE, asset.getAssetStatus()))
{
SysDept dept = requireNormalDept(item.getNewDeptId());
SysUser user = requireNormalUser(item.getNewUserId());
if (!Objects.equals(user.getDeptId(), dept.getDeptId()))
{
throw new ServiceException(StringUtils.format("资产【{}】的新使用人不属于所选新部门", asset.getAssetCode()));
}
item.setNewDeptName(dept.getDeptName());
item.setNewUserName(user.getUserName());
}
else
{
// 在库资产没有使用归属,前端即使伪造部门或人员也必须清空。
item.setNewDeptId(null);
item.setNewDeptName(null);
item.setNewUserId(null);
item.setNewUserName(null);
}
item.setNewDeptId(null);
item.setNewDeptName(null);
item.setNewUserId(null);
item.setNewUserName(null);
}
/** 陈旧归属校验:若草稿保存后资产台账的归属已被其他业务修改,阻断当前流转。 */
private void validateOldSnapshot(AmsTransferOrderItem item, AmsAsset asset)
{
if (!Objects.equals(item.getOldWarehouseId(), asset.getWarehouseId())
|| !Objects.equals(item.getOldLocationId(), asset.getLocationId())
|| !Objects.equals(item.getOldDeptId(), asset.getUseDeptId())
|| !Objects.equals(item.getOldUserId(), asset.getUseUserId()))
|| !Objects.equals(item.getOldLocationId(), asset.getLocationId()))
{
throw new ServiceException(StringUtils.format("资产【{}】当前归属已变化,请重新编辑并提交调拨单",
asset.getAssetCode()));
@ -445,9 +416,7 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
private void validateActualChange(AmsTransferOrderItem item, AmsAsset asset)
{
boolean changed = !Objects.equals(asset.getWarehouseId(), item.getNewWarehouseId())
|| !Objects.equals(asset.getLocationId(), item.getNewLocationId())
|| !Objects.equals(asset.getUseDeptId(), item.getNewDeptId())
|| !Objects.equals(asset.getUseUserId(), item.getNewUserId());
|| !Objects.equals(asset.getLocationId(), item.getNewLocationId());
if (!changed)
{
throw new ServiceException(StringUtils.format("资产【{}】的调拨前后归属不能完全相同", asset.getAssetCode()));
@ -482,38 +451,6 @@ public class AmsTransferOrderServiceImpl implements IAmsTransferOrderService
return location;
}
private SysDept requireNormalDept(Long deptId)
{
if (StringUtils.isNull(deptId))
{
throw new ServiceException("在用资产的新使用部门不能为空");
}
SysDept dept = sysDeptService.selectDeptById(deptId);
if (StringUtils.isNull(dept)
|| !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getStatus())
|| !StringUtils.equals(DEL_FLAG_NORMAL, dept.getDelFlag()))
{
throw new ServiceException("新使用部门不存在或已停用");
}
return dept;
}
private SysUser requireNormalUser(Long userId)
{
if (StringUtils.isNull(userId))
{
throw new ServiceException("在用资产的新使用人不能为空");
}
SysUser user = sysUserService.selectUserById(userId);
if (StringUtils.isNull(user)
|| !StringUtils.equals(UserConstants.NORMAL, user.getStatus())
|| !StringUtils.equals(DEL_FLAG_NORMAL, user.getDelFlag()))
{
throw new ServiceException("新使用人不存在或已停用");
}
return user;
}
private AmsTransferOrder requireOrderForUpdate(Long orderId, String requiredStatus, String message)
{
if (StringUtils.isNull(orderId))

@ -159,7 +159,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
for update
</select>
<!-- 查询可调拨资产候选列表:筛选在库/在用状态,通过 NOT EXISTS 排除已被其他有效调拨单占用的资产 -->
<!-- 查询可调拨资产候选列表:筛选在库状态,通过 NOT EXISTS 排除已被其他有效调拨单占用的资产 -->
<select id="selectAvailableTransferAssetList" resultMap="AvailableTransferAssetResult">
select asset.asset_id, asset.asset_code, asset.asset_name, asset.category_id,
asset.category_code, asset.category_name, asset.spec_model, asset.brand,
@ -168,7 +168,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
asset.use_dept_name, asset.use_user_id, asset.use_user_name, asset.tag_code
from ams_asset asset
where asset.del_flag = '0'
and asset.asset_status in (#{stockStatus}, #{inUseStatus})
and asset.asset_status = #{stockStatus}
and not exists (
select 1
from ams_transfer_order_item item

@ -53,8 +53,6 @@
var prefix = ctx + "asset/transfer";
var warehouseList = [[${warehouseList}]];
var locationList = [[${locationList}]];
var deptList = [[${deptList}]];
var userList = [[${userList}]];
var assetStatusDatas = [[${@dict.getType('ams_asset_status')}]];
$("#form-transfer-add").validate({ focusCleanup: true });
@ -121,20 +119,6 @@
return buildLocationSelect(value, row, index);
}
},
{
field: "newDeptId",
title: "新部门",
formatter: function(value, row, index) {
return buildDeptSelect(value, row, index);
}
},
{
field: "newUserId",
title: "新使用人",
formatter: function(value, row, index) {
return buildUserSelect(value, row, index);
}
},
{
field: "remark",
title: "明细备注",
@ -200,10 +184,6 @@
assetName: asset.assetName,
categoryName: asset.categoryName,
assetStatus: asset.assetStatus,
oldDeptId: asset.useDeptId,
oldDeptName: asset.useDeptName,
oldUserId: asset.useUserId,
oldUserName: asset.useUserName,
oldWarehouseId: asset.warehouseId,
oldWarehouseCode: asset.warehouseCode,
oldWarehouseName: asset.warehouseName,
@ -212,8 +192,6 @@
oldLocationName: asset.locationName,
newWarehouseId: "",
newLocationId: "",
newDeptId: "",
newUserId: "",
remark: ""
};
}
@ -245,15 +223,6 @@
$("#bootstrap-table").bootstrapTable("updateRow", { index: index, row: row });
}
/* 部门下拉变更时,清空已选使用人并重新渲染行的使用人下拉(仅显示属于新部门的用户) */
function changeDept(index, value) {
syncDetailRows();
var row = $("#bootstrap-table").bootstrapTable("getData")[index];
row.newDeptId = value;
row.newUserId = "";
$("#bootstrap-table").bootstrapTable("updateRow", { index: index, row: row });
}
/**
* 关键技巧:在任何行操作(增、删、级联切换)前,先从 DOM 的下拉/输入元素
* 同步用户编辑值回 bootstrapTable 的数据模型,因为
@ -265,8 +234,6 @@
var tr = $("#bootstrap-table tbody tr[data-index='" + index + "']");
row.newWarehouseId = tr.find("[name$='.newWarehouseId']").val() || "";
row.newLocationId = tr.find("[name$='.newLocationId']").val() || "";
row.newDeptId = tr.find("[name$='.newDeptId']").val() || "";
row.newUserId = tr.find("[name$='.newUserId']").val() || "";
row.remark = tr.find("[name$='.remark']").val() || "";
});
}
@ -281,11 +248,8 @@
}
function buildCurrentOwnership(row) {
var text = (row.oldWarehouseName || "-") + " / " + (row.oldLocationName || "-");
if (row.assetStatus === "IN_USE") {
text += " / " + (row.oldDeptName || "-") + " / " + (row.oldUserName || "-");
}
return $("<span>").text(text).prop("outerHTML");
return $("<span>").text((row.oldWarehouseName || "-") + " / "
+ (row.oldLocationName || "-")).prop("outerHTML");
}
function buildWarehouseSelect(value, index) {
@ -325,53 +289,6 @@
return select.prop("outerHTML");
}
/* 在库资产无需设置部门,隐藏字段提交空值,后端会强制清空以防伪造 */
function buildDeptSelect(value, row, index) {
if (row.assetStatus !== "IN_USE") {
return buildHidden("amsTransferOrderItemList[" + index + "].newDeptId", "") + "在库无需设置";
}
var select = $("<select>").addClass("form-control").attr({
name: "amsTransferOrderItemList[" + index + "].newDeptId",
required: true,
onchange: "changeDept(" + index + ", this.value)"
});
select.append($("<option>").val("").text("请选择新部门"));
$.each(deptList, function(i, dept) {
var option = $("<option>").val(dept.deptId).text(dept.deptName);
if (String(dept.deptId) === String(value)) {
option.attr("selected", "selected");
}
select.append(option);
});
return select.prop("outerHTML");
}
/* 在库资产无需设置使用人,同部门逻辑 */
function buildUserSelect(value, row, index) {
if (row.assetStatus !== "IN_USE") {
return buildHidden("amsTransferOrderItemList[" + index + "].newUserId", "") + "在库无需设置";
}
var select = $("<select>").addClass("form-control").attr({
name: "amsTransferOrderItemList[" + index + "].newUserId",
required: true
});
select.append($("<option>").val("").text("请选择新使用人"));
$.each(userList, function(i, user) {
if (String(user.deptId) === String(row.newDeptId)) {
var option = $("<option>").val(user.userId).text(user.userName + "" + user.loginName + "");
if (String(user.userId) === String(value)) {
option.attr("selected", "selected");
}
select.append(option);
}
});
return select.prop("outerHTML");
}
function buildHidden(name, value) {
return $("<input>").attr({ type: "hidden", name: name, value: value }).prop("outerHTML");
}
function buildInput(name, value, maxLength) {
return $("<input>").addClass("form-control").attr({
type: "text",

@ -75,8 +75,6 @@
var detailList = [[${amsTransferOrder.amsTransferOrderItemList}]];
var warehouseList = [[${warehouseList}]];
var locationList = [[${locationList}]];
var deptList = [[${deptList}]];
var userList = [[${userList}]];
var assetStatusDatas = [[${@dict.getType('ams_asset_status')}]];
$("#form-transfer-edit").validate({ focusCleanup: true });
@ -143,20 +141,6 @@
return buildLocationSelect(value, row, index);
}
},
{
field: "newDeptId",
title: "新部门",
formatter: function(value, row, index) {
return buildDeptSelect(value, row, index);
}
},
{
field: "newUserId",
title: "新使用人",
formatter: function(value, row, index) {
return buildUserSelect(value, row, index);
}
},
{
field: "remark",
title: "明细备注",
@ -221,10 +205,6 @@
assetName: asset.assetName,
categoryName: asset.categoryName,
assetStatus: asset.assetStatus,
oldDeptId: asset.useDeptId,
oldDeptName: asset.useDeptName,
oldUserId: asset.useUserId,
oldUserName: asset.useUserName,
oldWarehouseId: asset.warehouseId,
oldWarehouseCode: asset.warehouseCode,
oldWarehouseName: asset.warehouseName,
@ -233,8 +213,6 @@
oldLocationName: asset.locationName,
newWarehouseId: "",
newLocationId: "",
newDeptId: "",
newUserId: "",
remark: ""
};
}
@ -266,15 +244,6 @@
$("#bootstrap-table").bootstrapTable("updateRow", { index: index, row: row });
}
/* 部门下拉变更时清空使用人并重新渲染级联 */
function changeDept(index, value) {
syncDetailRows();
var row = $("#bootstrap-table").bootstrapTable("getData")[index];
row.newDeptId = value;
row.newUserId = "";
$("#bootstrap-table").bootstrapTable("updateRow", { index: index, row: row });
}
/**
* 关键技巧:在任何行操作前,从 DOM 同步表单元素的用户编辑值
* 回 bootstrapTable 的数据模型,避免增删行后丢失已填写数据。
@ -285,8 +254,6 @@
var tr = $("#bootstrap-table tbody tr[data-index='" + index + "']");
row.newWarehouseId = tr.find("[name$='.newWarehouseId']").val() || "";
row.newLocationId = tr.find("[name$='.newLocationId']").val() || "";
row.newDeptId = tr.find("[name$='.newDeptId']").val() || "";
row.newUserId = tr.find("[name$='.newUserId']").val() || "";
row.remark = tr.find("[name$='.remark']").val() || "";
});
}
@ -301,11 +268,8 @@
}
function buildCurrentOwnership(row) {
var text = (row.oldWarehouseName || "-") + " / " + (row.oldLocationName || "-");
if (row.assetStatus === "IN_USE") {
text += " / " + (row.oldDeptName || "-") + " / " + (row.oldUserName || "-");
}
return $("<span>").text(text).prop("outerHTML");
return $("<span>").text((row.oldWarehouseName || "-") + " / "
+ (row.oldLocationName || "-")).prop("outerHTML");
}
function buildWarehouseSelect(value, index) {
@ -345,53 +309,6 @@
return select.prop("outerHTML");
}
/* 在库资产无需设置部门,隐藏字段提交空值,后端强制清空以防伪造 */
function buildDeptSelect(value, row, index) {
if (row.assetStatus !== "IN_USE") {
return buildHidden("amsTransferOrderItemList[" + index + "].newDeptId", "") + "在库无需设置";
}
var select = $("<select>").addClass("form-control").attr({
name: "amsTransferOrderItemList[" + index + "].newDeptId",
required: true,
onchange: "changeDept(" + index + ", this.value)"
});
select.append($("<option>").val("").text("请选择新部门"));
$.each(deptList, function(i, dept) {
var option = $("<option>").val(dept.deptId).text(dept.deptName);
if (String(dept.deptId) === String(value)) {
option.attr("selected", "selected");
}
select.append(option);
});
return select.prop("outerHTML");
}
/* 在库资产无需设置使用人,同部门逻辑 */
function buildUserSelect(value, row, index) {
if (row.assetStatus !== "IN_USE") {
return buildHidden("amsTransferOrderItemList[" + index + "].newUserId", "") + "在库无需设置";
}
var select = $("<select>").addClass("form-control").attr({
name: "amsTransferOrderItemList[" + index + "].newUserId",
required: true
});
select.append($("<option>").val("").text("请选择新使用人"));
$.each(userList, function(i, user) {
if (String(user.deptId) === String(row.newDeptId)) {
var option = $("<option>").val(user.userId).text(user.userName + "" + user.loginName + "");
if (String(user.userId) === String(value)) {
option.attr("selected", "selected");
}
select.append(option);
}
});
return select.prop("outerHTML");
}
function buildHidden(name, value) {
return $("<input>").attr({ type: "hidden", name: name, value: value }).prop("outerHTML");
}
function buildInput(name, value, maxLength) {
return $("<input>").addClass("form-control").attr({
type: "text",

@ -27,7 +27,7 @@
<select name="assetStatus" th:with="type=${@dict.getType('ams_asset_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}"
th:if="${dict.dictValue == 'IN_STOCK' || dict.dictValue == 'IN_USE'}"
th:if="${dict.dictValue == 'IN_STOCK'}"
th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
@ -96,13 +96,6 @@
field: "locationName",
title: "当前位置"
},
{
field: "useDeptName",
title: "当前部门"
},
{
field: "useUserName",
title: "当前使用人"
}]
});
});

@ -86,8 +86,6 @@
<th>资产类别</th>
<th>原仓库/位置</th>
<th>新仓库/位置</th>
<th>原部门/使用人</th>
<th>新部门/使用人</th>
<th>备注</th>
</tr>
</thead>
@ -99,8 +97,6 @@
<td th:text="${item.categoryName}"></td>
<td th:text="${(item.oldWarehouseName ?: '-') + ' / ' + (item.oldLocationName ?: '-')}"></td>
<td th:text="${(item.newWarehouseName ?: '-') + ' / ' + (item.newLocationName ?: '-')}"></td>
<td th:text="${(item.oldDeptName ?: '-') + ' / ' + (item.oldUserName ?: '-')}"></td>
<td th:text="${(item.newDeptName ?: '-') + ' / ' + (item.newUserName ?: '-')}"></td>
<td th:text="${item.remark}"></td>
</tr>
</tbody>

@ -27,12 +27,8 @@ import com.ruoyi.asset.mapper.AmsTransferOrderMapper;
import com.ruoyi.asset.service.IAmsAssetLocationService;
import com.ruoyi.asset.service.IAmsWarehouseService;
import com.ruoyi.asset.service.IAssetStatusTransitionService;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.service.ISysCodeRuleService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@ -58,12 +54,6 @@ class AmsTransferOrderServiceImplTest
@Mock
private IAmsAssetLocationService amsAssetLocationService;
@Mock
private ISysDeptService sysDeptService;
@Mock
private ISysUserService sysUserService;
@Mock
private IAssetStatusTransitionService assetStatusTransitionService;
@ -102,27 +92,19 @@ class AmsTransferOrderServiceImplTest
assertNotNull(item.getCreateTime());
}
/** 在用资产调拨必须回填有效的新部门和新使用人快照。 */
/** 在用资产不能直接创建调拨单。 */
@Test
void insertInUseTransferShouldFillNewUseOwnership()
void insertInUseTransferShouldBeRejected()
{
AmsTransferOrder order = buildRequest(AssetStatus.IN_USE);
when(sysCodeRuleService.nextCode("TRANSFER_ORDER")).thenReturn("DB202606120001");
stubInUseAsset();
stubTargetWarehouseLocation();
stubTargetDeptUser();
doAnswer(invocation -> {
AmsTransferOrder inserted = invocation.getArgument(0);
inserted.setOrderId(100L);
return 1;
}).when(amsTransferOrderMapper).insertAmsTransferOrder(any(AmsTransferOrder.class));
when(amsTransferOrderMapper.batchAmsTransferOrderItem(anyList())).thenReturn(1);
service.insertAmsTransferOrder(order, 1L, "管理员");
ServiceException exception = assertThrows(ServiceException.class,
() -> service.insertAmsTransferOrder(order, 1L, "管理员"));
AmsTransferOrderItem item = order.getAmsTransferOrderItemList().get(0);
assertEquals("研发部门", item.getNewDeptName());
assertEquals("管理员", item.getNewUserName());
assertTrue(exception.getMessage().contains("不允许调拨"));
verify(amsTransferOrderMapper, never()).insertAmsTransferOrder(any(AmsTransferOrder.class));
}
/** 被其他草稿或待确认调拨单占用的资产不得再次加入调拨单。 */
@ -175,8 +157,6 @@ class AmsTransferOrderServiceImplTest
org.mockito.ArgumentMatchers.eq(1L),
org.mockito.ArgumentMatchers.eq(2L),
org.mockito.ArgumentMatchers.eq(20L),
org.mockito.ArgumentMatchers.isNull(),
org.mockito.ArgumentMatchers.isNull(),
contextCaptor.capture());
assertEquals(100L, contextCaptor.getValue().getSourceOrderId());
assertEquals(101L, contextCaptor.getValue().getSourceItemId());
@ -227,11 +207,6 @@ class AmsTransferOrderServiceImplTest
item.setAssetStatus(assetStatus);
item.setNewWarehouseId(2L);
item.setNewLocationId(20L);
if (AssetStatus.IN_USE.equals(assetStatus))
{
item.setNewDeptId(103L);
item.setNewUserId(1L);
}
order.setAmsTransferOrderItemList(Collections.singletonList(item));
return order;
}
@ -246,11 +221,6 @@ class AmsTransferOrderServiceImplTest
item.setItemId(101L);
item.setOldWarehouseId(1L);
item.setOldLocationId(10L);
if (AssetStatus.IN_USE.equals(assetStatus))
{
item.setOldDeptId(105L);
item.setOldUserId(2L);
}
return order;
}
@ -307,21 +277,4 @@ class AmsTransferOrderServiceImplTest
when(amsAssetLocationService.selectAmsAssetLocationByLocationId(20L)).thenReturn(location);
}
private void stubTargetDeptUser()
{
SysDept dept = new SysDept();
dept.setDeptId(103L);
dept.setDeptName("研发部门");
dept.setStatus("0");
dept.setDelFlag("0");
when(sysDeptService.selectDeptById(103L)).thenReturn(dept);
SysUser user = new SysUser();
user.setUserId(1L);
user.setUserName("管理员");
user.setDeptId(103L);
user.setStatus("0");
user.setDelFlag("0");
when(sysUserService.selectUserById(1L)).thenReturn(user);
}
}

Loading…
Cancel
Save