package com.ruoyi.system.service.impl;
|
|
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.collection.CollUtil;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.basic.PageInfo;
|
import com.ruoyi.common.core.domain.entity.TDept;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.system.dto.asset.AssetTypeDTO;
|
import com.ruoyi.system.mapper.AssetTypeMapper;
|
import com.ruoyi.system.model.AssetInventoryRecord;
|
import com.ruoyi.system.model.AssetMain;
|
import com.ruoyi.system.model.AssetType;
|
import com.ruoyi.system.query.AssetInventoryListQuery;
|
import com.ruoyi.system.query.AssetStatisticsListDetailQuery;
|
import com.ruoyi.system.query.AssetStatisticsListQuery;
|
import com.ruoyi.system.service.AssetInventoryRecordService;
|
import com.ruoyi.system.service.AssetMainService;
|
import com.ruoyi.system.service.AssetTypeService;
|
import com.ruoyi.system.vo.AssetInventoryVO;
|
import com.ruoyi.system.vo.AssetStatisticsDetailVO;
|
import com.ruoyi.system.vo.AssetStatisticsVO;
|
import com.ruoyi.system.vo.asset.AssetTypeTreeVO;
|
import com.ruoyi.system.vo.system.NotificationVO;
|
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.models.auth.In;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.context.annotation.Lazy;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 资产类型表 服务实现类
|
* </p>
|
*
|
* @author WuGuanFengYue
|
* @since 2025-09-15
|
*/
|
@Service
|
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
|
public class AssetTypeServiceImpl extends ServiceImpl<AssetTypeMapper, AssetType> implements AssetTypeService {
|
|
private final AssetMainService assetMainService;
|
private final AssetTypeService assetTypeService;
|
private final AssetInventoryRecordService assetInventoryRecordService;
|
|
@Override
|
public List<AssetTypeTreeVO> getAssetTypeTree() {
|
// 查询所有未删除的资产类型数据
|
LambdaQueryWrapper<AssetType> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.orderByAsc(AssetType::getLevel)
|
.orderByAsc(AssetType::getId);
|
|
List<AssetType> allAssetTypes = this.list(queryWrapper);
|
|
if (CollUtil.isEmpty(allAssetTypes)) {
|
return new ArrayList<>();
|
}
|
|
// 转换为VO对象
|
List<AssetTypeTreeVO> assetTypeVOs = BeanUtil.copyToList(allAssetTypes, AssetTypeTreeVO.class);
|
|
// 预查询:找出存在资产关联的资产类型ID集合(去重)
|
List<Integer> allTypeIds = allAssetTypes.stream().map(AssetType::getId).collect(Collectors.toList());
|
QueryWrapper<AssetMain> usedTypeQuery = new QueryWrapper<>();
|
usedTypeQuery.select("distinct asset_type_id").in("asset_type_id", allTypeIds);
|
List<AssetMain> usedTypeRows = assetMainService.list(usedTypeQuery);
|
Set<Integer> usedTypeIdSet = usedTypeRows.stream()
|
.map(AssetMain::getAssetTypeId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
|
// 按父级ID分组
|
Map<Integer, List<AssetTypeTreeVO>> parentIdMap = assetTypeVOs.stream()
|
.collect(Collectors.groupingBy(AssetTypeTreeVO::getParentId));
|
|
// 计算可删除标记:一级仅判断是否有子分类;二级仅判断是否有关联资产
|
for (AssetTypeTreeVO vo : assetTypeVOs) {
|
if (Objects.equals(vo.getLevel(), 1)) {
|
boolean hasChildren = parentIdMap.containsKey(vo.getId()) && CollUtil.isNotEmpty(parentIdMap.get(vo.getId()));
|
vo.setCanDelete(!hasChildren);
|
} else {
|
boolean hasAssets = usedTypeIdSet.contains(vo.getId());
|
vo.setCanDelete(!hasAssets);
|
}
|
}
|
|
// 构建树形结构
|
List<AssetTypeTreeVO> rootNodes = parentIdMap.get(0);
|
if (CollUtil.isEmpty(rootNodes)) {
|
return new ArrayList<>();
|
}
|
|
// 为每个根节点设置子节点
|
for (AssetTypeTreeVO rootNode : rootNodes) {
|
List<AssetTypeTreeVO> children = parentIdMap.get(rootNode.getId());
|
rootNode.setChildren(children != null ? children : new ArrayList<>());
|
}
|
|
return rootNodes;
|
}
|
|
@Override
|
public void addAssetType(AssetTypeDTO dto) {
|
// 校验资产类型名称是否重复
|
LambdaQueryWrapper<AssetType> nameQueryWrapper = new LambdaQueryWrapper<>();
|
nameQueryWrapper.eq(AssetType::getTypeName, dto.getTypeName());
|
AssetType existingByName = this.getOne(nameQueryWrapper);
|
if (Objects.nonNull(existingByName)) {
|
throw new ServiceException("资产类型名称已存在");
|
}
|
|
// 校验资产简写是否重复
|
LambdaQueryWrapper<AssetType> codeQueryWrapper = new LambdaQueryWrapper<>();
|
codeQueryWrapper.eq(AssetType::getTypeCode, dto.getTypeCode());
|
AssetType existingByCode = this.getOne(codeQueryWrapper);
|
if (Objects.nonNull(existingByCode)) {
|
throw new ServiceException("资产类型简写已存在");
|
}
|
|
// 创建资产类型对象
|
AssetType assetType = new AssetType();
|
assetType.setTypeName(dto.getTypeName());
|
assetType.setTypeCode(dto.getTypeCode());
|
|
// 处理层级逻辑
|
if (Objects.isNull(dto.getParentId()) || dto.getParentId().equals(0)) {
|
// 添加一级资产类型
|
assetType.setParentId(0);
|
assetType.setLevel(1);
|
} else {
|
// 添加二级资产类型,先校验父级是否存在
|
AssetType parentAssetType = this.getById(dto.getParentId());
|
if (Objects.isNull(parentAssetType)) {
|
throw new ServiceException("父级资产类型不存在");
|
}
|
if (!parentAssetType.getLevel().equals(1)) {
|
throw new ServiceException("只能在一级资产类型下添加二级资产类型");
|
}
|
assetType.setParentId(dto.getParentId());
|
assetType.setLevel(2);
|
}
|
|
// 设置创建信息
|
String username = SecurityUtils.getUsername();
|
assetType.setCreateBy(username);
|
|
// 保存资产类型
|
this.save(assetType);
|
}
|
|
@Override
|
public void editAssetType(AssetTypeDTO dto) {
|
// 校验资产类型ID是否为空
|
if (Objects.isNull(dto.getId())) {
|
throw new ServiceException("资产类型ID不能为空");
|
}
|
|
// 校验资产类型是否存在
|
AssetType existingAssetType = this.getById(dto.getId());
|
if (Objects.isNull(existingAssetType)) {
|
throw new ServiceException("资产类型不存在");
|
}
|
|
// 校验是否有关联的资产记录
|
LambdaQueryWrapper<AssetMain> assetMainQueryWrapper = new LambdaQueryWrapper<>();
|
assetMainQueryWrapper.eq(AssetMain::getAssetTypeId, dto.getId());
|
long assetMainCount = assetMainService.count(assetMainQueryWrapper);
|
if (assetMainCount > 0) {
|
throw new ServiceException("该资产类型已关联资产记录,不能编辑");
|
}
|
|
// 校验资产类型名称是否重复(排除自身)
|
LambdaQueryWrapper<AssetType> nameQueryWrapper = new LambdaQueryWrapper<>();
|
nameQueryWrapper.eq(AssetType::getTypeName, dto.getTypeName())
|
.ne(AssetType::getId, dto.getId());
|
AssetType existingByName = this.getOne(nameQueryWrapper);
|
if (Objects.nonNull(existingByName)) {
|
throw new ServiceException("资产类型名称已存在");
|
}
|
|
// 校验资产简写是否重复(排除自身)
|
LambdaQueryWrapper<AssetType> codeQueryWrapper = new LambdaQueryWrapper<>();
|
codeQueryWrapper.eq(AssetType::getTypeCode, dto.getTypeCode())
|
.ne(AssetType::getId, dto.getId());
|
AssetType existingByCode = this.getOne(codeQueryWrapper);
|
if (Objects.nonNull(existingByCode)) {
|
throw new ServiceException("资产简写已存在");
|
}
|
|
// 更新资产类型信息
|
AssetType assetType = new AssetType();
|
assetType.setId(dto.getId());
|
assetType.setTypeName(dto.getTypeName());
|
assetType.setTypeCode(dto.getTypeCode());
|
|
// 设置更新信息
|
String username = SecurityUtils.getUsername();
|
assetType.setUpdateBy(username);
|
|
// 更新资产类型
|
this.updateById(assetType);
|
}
|
|
@Override
|
public void deleteAssetType(Integer id) {
|
// 校验资产类型ID是否为空
|
if (Objects.isNull(id)) {
|
throw new ServiceException("资产类型ID不能为空");
|
}
|
|
// 校验资产类型是否存在
|
AssetType existingAssetType = this.getById(id);
|
if (Objects.isNull(existingAssetType)) {
|
throw new ServiceException("资产类型不存在");
|
}
|
|
// 校验是否有子类型
|
LambdaQueryWrapper<AssetType> childQueryWrapper = new LambdaQueryWrapper<>();
|
childQueryWrapper.eq(AssetType::getParentId, id);
|
long childCount = this.count(childQueryWrapper);
|
if (childCount > 0) {
|
throw new ServiceException(String.format("【%s】存在子类型,不能删除", existingAssetType.getTypeName()));
|
}
|
|
// 校验是否有关联的资产记录
|
LambdaQueryWrapper<AssetMain> assetMainQueryWrapper = new LambdaQueryWrapper<>();
|
assetMainQueryWrapper.eq(AssetMain::getAssetTypeId, id);
|
long assetMainCount = assetMainService.count(assetMainQueryWrapper);
|
if (assetMainCount > 0) {
|
throw new ServiceException(String.format("【%s】已关联资产记录,不能删除", existingAssetType.getTypeName()));
|
}
|
|
// 删除资产类型
|
this.removeById(id);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void batchDeleteAssetType(List<Integer> ids) {
|
// 校验ID列表是否为空
|
if (CollUtil.isEmpty(ids)) {
|
throw new ServiceException("删除的资产类型ID列表不能为空");
|
}
|
|
// 收集删除失败的信息
|
List<String> failedMessages = new ArrayList<>();
|
|
// 逐个删除资产类型
|
for (Integer id : ids) {
|
try {
|
this.deleteAssetType(id);
|
} catch (ServiceException e) {
|
failedMessages.add(e.getMessage());
|
}
|
}
|
|
// 如果有删除失败的情况,抛出异常
|
if (CollUtil.isNotEmpty(failedMessages)) {
|
throw new ServiceException("批量删除失败:" + String.join(";", failedMessages));
|
}
|
}
|
|
@Override
|
public String getAssetCodePrefix(Integer assetTypeId) {
|
if (assetTypeId == null) {
|
throw new ServiceException("资产类型ID不能为空");
|
}
|
|
// 查询当前资产类型
|
AssetType currentAssetType = this.getById(assetTypeId);
|
if (currentAssetType == null) {
|
throw new ServiceException("资产类型不存在");
|
}
|
|
String parentTypeCode = "";
|
String subTypeCode = currentAssetType.getTypeCode();
|
|
// 如果是二级分类,需要获取父级分类的简写
|
if (currentAssetType.getLevel() == 2 && currentAssetType.getParentId() != null && currentAssetType.getParentId() != 0) {
|
AssetType parentAssetType = this.getById(currentAssetType.getParentId());
|
if (parentAssetType != null) {
|
parentTypeCode = parentAssetType.getTypeCode();
|
}
|
} else if (currentAssetType.getLevel() == 1) {
|
// 如果是一级分类,父级简写为空,子类简写就是当前类型简写
|
parentTypeCode = currentAssetType.getTypeCode();
|
subTypeCode = "";
|
}
|
|
return parentTypeCode + subTypeCode;
|
}
|
|
@Override
|
public PageInfo<AssetStatisticsVO> pageList(AssetStatisticsListQuery query) {
|
if (StringUtils.hasLength(query.getNameOrCode())){
|
// 查询出资产名称或者资产编号符合条件的code
|
List<Integer> assetTypeIds = assetMainService.lambdaQuery().like(AssetMain::getAssetName, query.getNameOrCode())
|
.or()
|
.like(AssetMain::getAssetCode, query.getNameOrCode())
|
.list()
|
.stream()
|
.map(AssetMain::getAssetTypeId)
|
.collect(Collectors.toList());
|
query.setAssetMainIds(assetTypeIds);
|
if (assetTypeIds.isEmpty()){
|
return new PageInfo<>();
|
}
|
}
|
PageInfo<AssetStatisticsVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
List<AssetStatisticsVO> list = this.baseMapper.pageList(query,pageInfo);
|
List<AssetStatisticsVO> listNoLimit = this.baseMapper.pageListNoLimit(query);
|
List<Integer> assetTypeIds = listNoLimit.stream().map(AssetStatisticsVO::getAssetTypeIdSecond).collect(Collectors.toList());
|
if (assetTypeIds.isEmpty()){
|
return new PageInfo<>();
|
}
|
Map<Integer, List<AssetMain>> assetMainMap = assetMainService.lambdaQuery()
|
.in(!query.getDeptIds().isEmpty(),AssetMain::getOwnershipDeptId, query.getDeptIds())
|
.in(AssetMain::getAssetTypeId, assetTypeIds).list()
|
.stream()
|
.collect(Collectors.groupingBy(AssetMain::getAssetTypeId));
|
for (AssetStatisticsVO asset : list) {
|
Integer totalCount= 0;
|
Integer idleCount= 0;
|
Integer useCount= 0;
|
Integer disposeCount= 0;
|
Integer otherCount= 0;
|
BigDecimal totalValue = new BigDecimal("0");
|
List<AssetMain> assetMains = assetMainMap.get(asset.getAssetTypeIdSecond());
|
if (!assetMains.isEmpty()){
|
for (AssetMain assetMain : assetMains) {
|
if (assetMain.getAssetStatus().contains("闲置")){
|
idleCount += assetMain.getQuantity();
|
}else if (assetMain.getAssetStatus().contains("使用中")){
|
useCount += assetMain.getQuantity();
|
}else if (assetMain.getAssetStatus().contains("损坏") || assetMain.getAssetStatus().contains("报废")){
|
disposeCount += assetMain.getQuantity();
|
}else{
|
otherCount += assetMain.getQuantity();
|
}
|
totalCount+= assetMain.getQuantity();
|
totalValue = totalValue.add(new BigDecimal(assetMain.getQuantity())
|
.multiply(assetMain.getUnitPrice()).setScale(2, RoundingMode.HALF_DOWN));
|
}
|
}
|
asset.setIdleCount(idleCount);
|
asset.setUseCount(useCount);
|
asset.setDisposeCount(disposeCount);
|
asset.setOtherCount(otherCount);
|
asset.setTotalCount(totalCount);
|
asset.setTotalValue(totalValue);
|
}
|
pageInfo.setRecords(list);
|
return pageInfo;
|
}
|
|
@Override
|
public PageInfo<AssetStatisticsDetailVO> pageListDetail(AssetStatisticsListDetailQuery query) {
|
String assetTypeName = null;
|
AssetType assetType = assetTypeService.getById(query.getAssetTypeIdSecond());
|
if (assetType!=null){
|
AssetType assetTypeParent = assetTypeService.getById(assetType.getParentId());
|
if (assetTypeParent!=null){
|
assetTypeName = assetTypeParent.getTypeName()+">"+assetType.getTypeName();
|
}
|
}
|
|
if (StringUtils.hasLength(query.getNameOrCode())){
|
// 查询出资产名称或者资产编号符合条件的code
|
List<Integer> assetTypeIds = assetMainService.lambdaQuery().like(AssetMain::getAssetName, query.getNameOrCode())
|
.or()
|
.like(AssetMain::getAssetCode, query.getNameOrCode())
|
.list()
|
.stream()
|
.map(AssetMain::getAssetTypeId)
|
.collect(Collectors.toList());
|
query.setAssetMainIds(assetTypeIds);
|
if (assetTypeIds.isEmpty()){
|
return new PageInfo<>();
|
}
|
}
|
PageInfo<AssetStatisticsDetailVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
List<AssetStatisticsDetailVO> list = this.baseMapper.pageListDetail(query,pageInfo);
|
for (AssetStatisticsDetailVO assetStatisticsDetailVO : list) {
|
assetStatisticsDetailVO.setAssetTypeName(assetTypeName);
|
}
|
pageInfo.setRecords(list);
|
return pageInfo;
|
}
|
|
@Override
|
public PageInfo<AssetInventoryVO> pageListInventory(AssetInventoryListQuery query) {
|
AssetType assetType = this.baseMapper.selectById(query.getAssetTypeId());
|
if (assetType.getParentId()==0){
|
List<Integer> assetTypeChild = this.baseMapper.selectList(new LambdaQueryWrapper<AssetType>()
|
.eq(AssetType::getParentId, assetType.getId())).stream().map(AssetType::getId)
|
.collect(Collectors.toList());
|
List<Integer> list = new ArrayList<>(assetTypeChild);
|
list.add(assetType.getId());
|
query.setAssetTypeIds( list);
|
}else{
|
query.setAssetTypeIds(Collections.singletonList(assetType.getId()));
|
}
|
PageInfo<AssetInventoryVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
List<AssetInventoryVO> list = this.baseMapper.pageListInventory(query,pageInfo);
|
Map<Integer, List<AssetMain>> assetMainMap = assetMainService.lambdaQuery().in(AssetMain::getId, query.getAssetMainIds()).list()
|
.stream().collect(Collectors.groupingBy(AssetMain::getAssetTypeId));
|
List<AssetInventoryRecord> assetInventoryRecords = assetInventoryRecordService.lambdaQuery().in(AssetInventoryRecord::getAssetMainId, query.getAssetMainIds()).list();
|
for (AssetInventoryVO assetInventoryVO : list) {
|
int inCount = 0;
|
int outCount = 0;
|
int inStockCount = 0;
|
|
BigDecimal inStockMoney = new BigDecimal("0");
|
BigDecimal inMoney = new BigDecimal("0");
|
BigDecimal outMoney = new BigDecimal("0");
|
List<AssetMain> assetMains = assetMainMap.get(assetInventoryVO.getAssetTypeIdSecond());
|
for (AssetInventoryRecord assetInventoryRecord : assetInventoryRecords) {
|
if (assetInventoryRecord.getType()==0){
|
AssetMain assetMain = assetMains.stream().filter(e -> e.getId().equals(assetInventoryRecord.getAssetMainId()))
|
.findFirst().orElse(null);
|
if (assetMain!=null){
|
inCount+=assetMain.getQuantity();
|
inMoney = inMoney.add(new BigDecimal(assetMain.getQuantity())
|
.multiply(assetMain.getUnitPrice()).setScale(2, RoundingMode.HALF_DOWN));
|
}
|
}else{
|
AssetMain assetMain = assetMains.stream().filter(e -> e.getId().equals(assetInventoryRecord.getAssetMainId()))
|
.findFirst().orElse(null);
|
if (assetMain!=null){
|
outCount+=assetMain.getQuantity();
|
outMoney = outMoney.add(new BigDecimal(assetMain.getQuantity())
|
.multiply(assetMain.getUnitPrice()).setScale(2, RoundingMode.HALF_DOWN));
|
}
|
}
|
}
|
assetInventoryVO.setInCount(inCount);
|
assetInventoryVO.setOutCount(outCount);
|
assetInventoryVO.setInMoney(inMoney);
|
assetInventoryVO.setOutMoney(outMoney);
|
List<AssetMain> inStorage = assetMains.stream().filter(e -> e.getDisposed() == 0 && e.getInUse() == 0 && e.getBorrowed() == 0).collect(Collectors.toList());
|
for (AssetMain assetMain : inStorage) {
|
inStockCount+=assetMain.getQuantity();
|
inStockMoney = inStockMoney.add(new BigDecimal(assetMain.getQuantity())
|
.multiply(assetMain.getUnitPrice()).setScale(2, RoundingMode.HALF_DOWN));
|
}
|
assetInventoryVO.setInStockCount(inStockCount);
|
assetInventoryVO.setInStockMoney(inStockMoney);
|
}
|
pageInfo.setRecords(list);
|
return pageInfo;
|
}
|
|
@Override
|
public PageInfo<AssetStatisticsDetailVO> pageListInventoryDetail(AssetStatisticsListDetailQuery query) {
|
PageInfo<AssetStatisticsDetailVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
List<AssetStatisticsDetailVO> list = this.baseMapper.pageListInventoryDetail(query,pageInfo);
|
List<AssetType> assetTypes = assetTypeService.list();
|
for (AssetStatisticsDetailVO assetStatisticsDetailVO : list) {
|
Integer type = assetStatisticsDetailVO.getType();
|
if (type==0){
|
String typeName = "入库";
|
|
AssetType assetType = assetTypes.stream().filter(e -> e.getId().equals(assetStatisticsDetailVO.getAssetTypeId()))
|
.findFirst().orElse(null);
|
if (assetType!=null){
|
typeName =typeName+"("+assetType.getTypeName()+")";
|
}
|
assetStatisticsDetailVO.setTypeName(typeName);
|
}else{
|
String typeName = "出库";
|
AssetType assetType = assetTypes.stream().filter(e -> e.getId().equals(assetStatisticsDetailVO.getAssetTypeId()))
|
.findFirst().orElse(null);
|
if (assetType!=null){
|
typeName =typeName+"("+assetType.getTypeName()+")";
|
}
|
assetStatisticsDetailVO.setTypeName(typeName);
|
}
|
}
|
pageInfo.setRecords(list);
|
return pageInfo;
|
}
|
|
}
|