From dc4f084a89f735307b76a2e4222808d58e1a9043 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期六, 16 五月 2026 11:05:07 +0800
Subject: [PATCH] chore: 配置文件修改
---
src/main/java/com/ruoyi/account/service/impl/financial/FinFixedAssetServiceImpl.java | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 231 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/ruoyi/account/service/impl/financial/FinFixedAssetServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/financial/FinFixedAssetServiceImpl.java
new file mode 100644
index 0000000..cb7a476
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/impl/financial/FinFixedAssetServiceImpl.java
@@ -0,0 +1,231 @@
+package com.ruoyi.account.service.impl.financial;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.ruoyi.account.bean.dto.financial.FinFixedAssetDto;
+import com.ruoyi.account.mapper.financial.FinFixedAssetMapper;
+import com.ruoyi.account.pojo.financial.FinFixedAsset;
+import com.ruoyi.account.service.financial.FinFixedAssetService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * 鍥哄畾璧勪骇鏈嶅姟瀹炵幇銆�
+ */
+@Service
+@RequiredArgsConstructor
+public class FinFixedAssetServiceImpl extends ServiceImpl<FinFixedAssetMapper, FinFixedAsset> implements FinFixedAssetService {
+
+ private static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
+ private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+ private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+
+ @Override
+ public IPage<FinFixedAsset> pageList(Page<FinFixedAsset> page, FinFixedAssetDto queryDto) {
+ LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>();
+ if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetCode())) {
+ wrapper.like(FinFixedAsset::getAssetCode, queryDto.getAssetCode());
+ }
+ if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetName())) {
+ wrapper.like(FinFixedAsset::getAssetName, queryDto.getAssetName());
+ }
+ if (queryDto != null && StringUtils.isNotEmpty(queryDto.getCategory())) {
+ wrapper.eq(FinFixedAsset::getCategory, queryDto.getCategory());
+ }
+ if (queryDto != null && StringUtils.isNotEmpty(queryDto.getStatus())) {
+ wrapper.eq(FinFixedAsset::getStatus, queryDto.getStatus());
+ }
+ wrapper.orderByDesc(FinFixedAsset::getId);
+ return page(page, wrapper);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean add(FinFixedAssetDto dto) {
+ validateForSave(dto, false);
+ if (StringUtils.isEmpty(dto.getAssetCode())) {
+ dto.setAssetCode(generateAssetCode());
+ }
+ BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate());
+ dto.setResidualRate(residualRate);
+ BigDecimal accumulatedDepreciation = defaultMoney(dto.getAccumulatedDepreciation());
+ dto.setAccumulatedDepreciation(accumulatedDepreciation);
+ dto.setNetValue(calculateNetValue(dto.getOriginalValue(), accumulatedDepreciation));
+ if (StringUtils.isEmpty(dto.getStatus())) {
+ dto.setStatus("in_use");
+ }
+ return save(dto);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean update(FinFixedAssetDto dto) {
+ if (dto == null || dto.getId() == null) {
+ throw new ServiceException("淇敼澶辫触锛岃祫浜D涓嶈兘涓虹┖");
+ }
+ FinFixedAsset existed = getById(dto.getId());
+ if (existed == null) {
+ throw new ServiceException("淇敼澶辫触锛屽浐瀹氳祫浜т笉瀛樺湪");
+ }
+ if (StringUtils.isEmpty(dto.getAssetCode())) {
+ dto.setAssetCode(existed.getAssetCode());
+ }
+ if (StringUtils.isEmpty(dto.getStatus())) {
+ dto.setStatus(existed.getStatus());
+ }
+ validateForSave(dto, true);
+ BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate());
+ dto.setResidualRate(residualRate);
+ if (dto.getAccumulatedDepreciation() == null) {
+ dto.setAccumulatedDepreciation(defaultMoney(existed.getAccumulatedDepreciation()));
+ }
+ dto.setNetValue(calculateNetValue(dto.getOriginalValue(), dto.getAccumulatedDepreciation()));
+ return updateById(dto);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean deleteByIds(List<Long> ids) {
+ if (ids == null || ids.isEmpty()) {
+ throw new ServiceException("鍒犻櫎澶辫触锛岃閫夋嫨瑕佸垹闄ょ殑鏁版嵁");
+ }
+ return removeByIds(ids);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Map<String, Object> depreciate(List<Long> ids) {
+ LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>();
+ if (ids != null && !ids.isEmpty()) {
+ wrapper.in(FinFixedAsset::getId, ids);
+ } else {
+ wrapper.eq(FinFixedAsset::getStatus, "in_use");
+ }
+ List<FinFixedAsset> assets = list(wrapper);
+ BigDecimal totalMonthlyDepreciation = ZERO;
+ int processedCount = 0;
+ for (FinFixedAsset asset : assets) {
+ if (!"in_use".equals(asset.getStatus())) {
+ continue;
+ }
+ BigDecimal monthlyDepreciation = calculateMonthlyDepreciation(
+ asset.getOriginalValue(),
+ asset.getResidualRate(),
+ asset.getUsefulLife()
+ );
+ BigDecimal accumulatedDepreciation = defaultMoney(asset.getAccumulatedDepreciation()).add(monthlyDepreciation);
+ if (accumulatedDepreciation.compareTo(defaultMoney(asset.getOriginalValue())) > 0) {
+ accumulatedDepreciation = defaultMoney(asset.getOriginalValue());
+ }
+ asset.setAccumulatedDepreciation(roundMoney(accumulatedDepreciation));
+ asset.setNetValue(calculateNetValue(asset.getOriginalValue(), asset.getAccumulatedDepreciation()));
+ updateById(asset);
+ processedCount++;
+ totalMonthlyDepreciation = totalMonthlyDepreciation.add(monthlyDepreciation);
+ }
+ Map<String, Object> result = new HashMap<>(4);
+ result.put("processedCount", processedCount);
+ result.put("totalMonthlyDepreciation", roundMoney(totalMonthlyDepreciation));
+ result.put("executionTime", LocalDateTime.now());
+ return result;
+ }
+
+ /**
+ * 鎸夋枃妗h鍒欐牎楠屽浐瀹氳祫浜ф暟鎹��
+ */
+ private void validateForSave(FinFixedAssetDto dto, boolean isUpdate) {
+ if (dto == null) {
+ throw new ServiceException("鍥哄畾璧勪骇鏁版嵁涓嶈兘涓虹┖");
+ }
+ if (isUpdate && dto.getId() == null) {
+ throw new ServiceException("淇敼澶辫触锛岃祫浜D涓嶈兘涓虹┖");
+ }
+ if (StringUtils.isEmpty(dto.getAssetName())) {
+ throw new ServiceException("璧勪骇鍚嶇О涓嶈兘涓虹┖");
+ }
+ if (StringUtils.isEmpty(dto.getCategory())) {
+ throw new ServiceException("璧勪骇绫诲埆涓嶈兘涓虹┖");
+ }
+ if (dto.getPurchaseDate() == null) {
+ throw new ServiceException("璐疆鏃ユ湡涓嶈兘涓虹┖");
+ }
+ if (dto.getOriginalValue() == null || dto.getOriginalValue().compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("璧勪骇鍘熷�间笉鑳戒负绌轰笖涓嶈兘灏忎簬0");
+ }
+ if (dto.getUsefulLife() == null || dto.getUsefulLife() <= 0) {
+ throw new ServiceException("浣跨敤骞撮檺蹇呴』澶т簬0");
+ }
+ if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("娈嬪�肩巼涓嶈兘灏忎簬0");
+ }
+ if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(ONE_HUNDRED) > 0) {
+ throw new ServiceException("娈嬪�肩巼涓嶈兘澶т簬100%");
+ }
+ if (StringUtils.isNotEmpty(dto.getAssetCode())) {
+ LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>();
+ wrapper.eq(FinFixedAsset::getAssetCode, dto.getAssetCode());
+ if (isUpdate) {
+ wrapper.ne(FinFixedAsset::getId, dto.getId());
+ }
+ if (count(wrapper) > 0) {
+ throw new ServiceException("璧勪骇缂栧彿宸插瓨鍦紝璇峰嬁閲嶅鎻愪氦");
+ }
+ }
+ }
+
+ /**
+ * 鍥哄畾璧勪骇鎶樻棫鍏紡锛�
+ * monthlyDepreciation = originalValue * (1 - residualRate/100) / (usefulLife*12)
+ */
+ private BigDecimal calculateMonthlyDepreciation(BigDecimal originalValue, BigDecimal residualRate, Integer usefulLife) {
+ BigDecimal normalizedOriginalValue = defaultMoney(originalValue);
+ BigDecimal normalizedResidualRate = normalizeResidualRate(residualRate);
+ BigDecimal depreciableRatio = BigDecimal.ONE.subtract(normalizedResidualRate.divide(ONE_HUNDRED, 8, RoundingMode.HALF_UP));
+ BigDecimal months = BigDecimal.valueOf((long) usefulLife * 12L);
+ if (months.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("浣跨敤骞撮檺鏃犳晥锛屾棤娉曡鎻愭姌鏃�");
+ }
+ return roundMoney(normalizedOriginalValue.multiply(depreciableRatio).divide(months, 8, RoundingMode.HALF_UP));
+ }
+
+ /**
+ * 鍑�鍊� = 鍘熷�� - 绱鎶樻棫銆�
+ */
+ private BigDecimal calculateNetValue(BigDecimal originalValue, BigDecimal accumulatedDepreciation) {
+ BigDecimal value = defaultMoney(originalValue).subtract(defaultMoney(accumulatedDepreciation));
+ if (value.compareTo(BigDecimal.ZERO) < 0) {
+ value = BigDecimal.ZERO;
+ }
+ return roundMoney(value);
+ }
+
+ private BigDecimal normalizeResidualRate(BigDecimal residualRate) {
+ return residualRate == null ? BigDecimal.ZERO : residualRate;
+ }
+
+ private BigDecimal defaultMoney(BigDecimal value) {
+ return value == null ? ZERO : roundMoney(value);
+ }
+
+ private BigDecimal roundMoney(BigDecimal value) {
+ if (value == null) {
+ return ZERO;
+ }
+ return value.setScale(2, RoundingMode.HALF_UP);
+ }
+
+ private String generateAssetCode() {
+ return "GD" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
+ }
+}
--
Gitblit v1.9.3