package com.ruoyi.account.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.account.dto.DeviceTypeDetail; import com.ruoyi.account.dto.DeviceTypeDistributionVO; import com.ruoyi.account.mapper.BorrowInfoMapper; import com.ruoyi.account.pojo.BorrowInfo; import com.ruoyi.device.mapper.DeviceLedgerMapper; import com.ruoyi.device.pojo.DeviceLedger; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.procurementrecord.mapper.CustomStorageMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; import com.ruoyi.procurementrecord.pojo.CustomStorage; import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; import com.ruoyi.procurementrecord.service.impl.ProcurementRecordOutServiceImpl; import com.ruoyi.procurementrecord.service.impl.ProcurementRecordServiceImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.Year; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; /** * @author :yys * @date : 2026/1/17 10:41 */ @Service @Slf4j public class AccountingServiceImpl { @Autowired private DeviceLedgerMapper deviceLedgerMapper; @Autowired private BorrowInfoMapper borrowInfoMapper; @Autowired private CustomStorageMapper customStorageMapper; @Autowired private ProcurementRecordMapper procurementRecordMapper; @Autowired private ProcurementRecordOutMapper procurementRecordOutMapper; public AjaxResult total(Integer year) { Map map = new HashMap<>(); map.put("deprAmount",0); // 折旧金额 map.put("deviceTotal",0); // 设备总数 map.put("deviceAmount",0); // 设备资产原值 map.put("netValue",0); // 净值 map.put("debt",0); // 负债 map.put("inventoryValue",0); // 库存资产 LambdaQueryWrapper deviceLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>(); deviceLedgerLambdaQueryWrapper.like(DeviceLedger::getCreateTime,year); List deviceLedgers = deviceLedgerMapper.selectList(deviceLedgerLambdaQueryWrapper); if(CollectionUtils.isNotEmpty(deviceLedgers)){ map.put("deviceTotal",deviceLedgers.size()); BigDecimal reduce = deviceLedgers.stream() .map(DeviceLedger::getTaxIncludingPriceTotal) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); map.put("deviceAmount",reduce); List collect = deviceLedgers.stream().filter(deviceLedger -> deviceLedger.getIsDepr() != null && deviceLedger.getIsDepr() == 1).collect(Collectors.toList()); // 根据当前年份和设备录入时间年份比较 * 每年折旧金额 = 设备折旧金额 BigDecimal total = new BigDecimal(0); if(CollectionUtils.isNotEmpty(collect)){ for (DeviceLedger deviceLedger : collect) { BigDecimal totalDepreciation = calculatePreciseDepreciation(deviceLedger); total = total.add(totalDepreciation); } map.put("deprAmount",total); } // 净值 = 设备资产原值 - 设备累计折旧金额 map.put("netValue",reduce.subtract(total)); } // 负债 LambdaQueryWrapper borrowInfoLambdaQueryWrapper = new LambdaQueryWrapper<>(); borrowInfoLambdaQueryWrapper.like(BorrowInfo::getCreateTime,year) .eq(BorrowInfo::getStatus,1); List borrowInfos = borrowInfoMapper.selectList(borrowInfoLambdaQueryWrapper); if(CollectionUtils.isNotEmpty(borrowInfos)){ BigDecimal reduce = borrowInfos.stream() .map(BorrowInfo::getBorrowAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); map.put("debt",reduce); } // 库存资产 LambdaQueryWrapper procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>(); procurementRecordStorageLambdaQueryWrapper.like(ProcurementRecordStorage::getCreateTime,year); List procurementRecordStorages = procurementRecordMapper.selectList(procurementRecordStorageLambdaQueryWrapper); BigDecimal procurementRecordTotal = new BigDecimal(0); if(CollectionUtils.isNotEmpty(procurementRecordStorages)){ // 获取出库数据 LambdaQueryWrapper procurementRecordOutLambdaQueryWrapper = new LambdaQueryWrapper<>(); procurementRecordOutLambdaQueryWrapper.like(ProcurementRecordOut::getCreateTime,year) .in(ProcurementRecordOut::getProcurementRecordStorageId, procurementRecordStorages .stream() .map(ProcurementRecordStorage::getId) .collect(Collectors.toList())) .in(ProcurementRecordOut::getType,Arrays.asList(1,2)); List procurementRecordOuts = procurementRecordOutMapper.selectList(procurementRecordOutLambdaQueryWrapper); for (ProcurementRecordStorage procurementRecordStorage : procurementRecordStorages) { // 采购,生产入库总价值 procurementRecordTotal.add(procurementRecordStorage.getUnitPrice().multiply(procurementRecordStorage.getInboundNum())); // 通过入库id,类型获取出库数据 List procurementRecordOutsByStorageId = procurementRecordOuts.stream() .filter(procurementRecordOut -> procurementRecordOut.getProcurementRecordStorageId().equals(procurementRecordStorage.getId()) && procurementRecordOut.getType().equals(procurementRecordStorage.getType())) .collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(procurementRecordOutsByStorageId)){ for (ProcurementRecordOut procurementRecordOut : procurementRecordOutsByStorageId) { // 采购,生产出库总价值 procurementRecordTotal.subtract(procurementRecordStorage.getUnitPrice().multiply(procurementRecordOut.getInboundNum())); } } } } LambdaQueryWrapper customStorageLambdaQueryWrapper = new LambdaQueryWrapper<>(); customStorageLambdaQueryWrapper.like(CustomStorage::getInboundDate,year); List customStorages = customStorageMapper.selectList(customStorageLambdaQueryWrapper); BigDecimal customStorageTotal = new BigDecimal(0); if(CollectionUtils.isNotEmpty(customStorages)){ // 获取出库数据 LambdaQueryWrapper procurementRecordOutLambdaQueryWrapper = new LambdaQueryWrapper<>(); procurementRecordOutLambdaQueryWrapper.like(ProcurementRecordOut::getCreateTime,year) .in(ProcurementRecordOut::getProcurementRecordStorageId, customStorages .stream() .map(CustomStorage::getId) .collect(Collectors.toList())) .eq(ProcurementRecordOut::getType,3); List procurementRecordOuts = procurementRecordOutMapper.selectList(procurementRecordOutLambdaQueryWrapper); customStorages.forEach(customStorage -> { // 自定义入库总价值 customStorageTotal.add(customStorage.getTaxInclusiveUnitPrice().multiply(customStorage.getInboundNum())); // 通过入库id,类型获取出库数据 List procurementRecordOutsByStorageId = procurementRecordOuts.stream() .filter(procurementRecordOut -> procurementRecordOut.getProcurementRecordStorageId().equals(customStorage.getId())) .collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(procurementRecordOutsByStorageId)){ for (ProcurementRecordOut procurementRecordOut : procurementRecordOutsByStorageId) { // 自定义出库总价值 customStorageTotal.subtract(procurementRecordOut.getInboundNum().multiply(customStorage.getTaxInclusiveUnitPrice())); } } }); } map.put("inventoryValue",procurementRecordTotal.add(customStorageTotal)); return AjaxResult.success( map); } /** * 计算设备累计折旧金额 * @param deviceLedger 设备台账实体 * @return 累计折旧金额(BigDecimal,保留2位小数) */ public static BigDecimal calculateTotalDepreciation(DeviceLedger deviceLedger) { // 1. 空值校验 if (deviceLedger == null) { return BigDecimal.ZERO; } // 2. 判断是否开启折旧,未开启则折旧金额为0 Integer isDepr = deviceLedger.getIsDepr(); if (isDepr == null || isDepr != 1) { // 1-是 2-否 return BigDecimal.ZERO; } // 3. 获取每年折旧金额,为空则返回0 BigDecimal annualDepreciation = deviceLedger.getAnnualDepreciationAmount(); if (annualDepreciation == null || annualDepreciation.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; } // 4. 获取设备录入时间,为空则返回0 LocalDateTime createTime = deviceLedger.getCreateTime(); if (createTime == null) { return BigDecimal.ZERO; } // 5. 计算年份差值 int currentYear = Year.now().getValue(); // 当前年份 int createYear = createTime.getYear(); // 设备录入年份 int yearDiff = currentYear - createYear; // 6. 处理年份差值为负数的情况(录入时间在未来) if (yearDiff < 0) { return BigDecimal.ZERO; } // 7. 计算总折旧金额 = 年份差值 * 每年折旧金额 BigDecimal totalDepreciation = annualDepreciation.multiply(BigDecimal.valueOf(yearDiff)); // 8. 返回保留2位小数的结果(金额规范) return totalDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP); } /** * 【进阶版】按实际天数计算折旧(更精准) * @param deviceLedger 设备台账实体 * @return 累计折旧金额 */ public static BigDecimal calculatePreciseDepreciation(DeviceLedger deviceLedger) { if (deviceLedger == null) { return BigDecimal.ZERO; } // 判断是否开启折旧 Integer isDepr = deviceLedger.getIsDepr(); if (isDepr == null || isDepr != 1) { return BigDecimal.ZERO; } // 获取每年折旧金额 BigDecimal annualDepreciation = deviceLedger.getAnnualDepreciationAmount(); if (annualDepreciation == null || annualDepreciation.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; } // 获取设备录入时间 LocalDateTime createTime = deviceLedger.getCreateTime(); if (createTime == null) { return BigDecimal.ZERO; } // 当前时间 LocalDateTime now = LocalDateTime.now(); // 如果录入时间在未来,返回0 if (createTime.isAfter(now)) { return BigDecimal.ZERO; } // 计算总天数 long days = ChronoUnit.DAYS.between(createTime, now); // 按每年365天计算折旧金额 BigDecimal dailyDepreciation = annualDepreciation.divide(BigDecimal.valueOf(365), 6, BigDecimal.ROUND_HALF_UP); BigDecimal totalDepreciation = dailyDepreciation.multiply(BigDecimal.valueOf(days)); return totalDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP); } public AjaxResult deviceTypeDistribution(Integer year) { // 2. 组装返回VO DeviceTypeDistributionVO vo = new DeviceTypeDistributionVO(); List details = deviceLedgerMapper.getDeviceTypeDistributionByYear( year); vo.setDetails(details); if(CollectionUtils.isNotEmpty(details)){ // 3. 提取图表所需的分类和数据 vo.setCategories(details.stream() .map(DeviceTypeDetail::getType) .collect(Collectors.toList())); vo.setCountData(details.stream() .map(DeviceTypeDetail::getCount) .collect(Collectors.toList())); vo.setAmountData(details.stream() .map(DeviceTypeDetail::getAmount) .collect(Collectors.toList())); vo.setTotalCount(vo.getCategories().size()); } return AjaxResult.success(vo); } public AjaxResult calculateDepreciation(Page page, Integer year) { LambdaQueryWrapper deviceLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>(); deviceLedgerLambdaQueryWrapper.like(DeviceLedger::getCreateTime,year) .eq(DeviceLedger::getIsDepr,1); IPage deviceLedgerIPage = deviceLedgerMapper.selectPage(page, deviceLedgerLambdaQueryWrapper); for (DeviceLedger record : deviceLedgerIPage.getRecords()) { record.setDeprAmount(calculatePreciseDepreciation(record)); record.setNetValue(record.getTaxIncludingPriceTotal().subtract(record.getDeprAmount())); } return AjaxResult.success(deviceLedgerIPage); } }