diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/mechanicaldepreciation/MechanicalDepreciationController.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/mechanicaldepreciation/MechanicalDepreciationController.java index a034f2c..9db05b3 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/mechanicaldepreciation/MechanicalDepreciationController.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/mechanicaldepreciation/MechanicalDepreciationController.java @@ -100,5 +100,9 @@ public class MechanicalDepreciationController { ExcelUtils.write(response, "自有机械折旧子.xls", "数据", MechanicalDepreciationRespVO.class, BeanUtils.toBean(list, MechanicalDepreciationRespVO.class)); } + @GetMapping(value = "/batchSaveMechDepr") + public void batchSaveMechDepr(@RequestParam String depreciationMethod) { + mechanicalDepreciationService.batchSaveMechDepr(depreciationMethod); + } -} \ No newline at end of file +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/mechanicalcost/MechanicalCostDO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/mechanicalcost/MechanicalCostDO.java index 0fe781a..1be0497 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/mechanicalcost/MechanicalCostDO.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/mechanicalcost/MechanicalCostDO.java @@ -77,7 +77,7 @@ public class MechanicalCostDO extends BaseDO { /** * 使用年限 */ - private Long serviceLife; + private Integer serviceLife; /** * 结束使用时间 */ diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/costfee/CostFeeMachDepr.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/costfee/CostFeeMachDepr.java new file mode 100644 index 0000000..0001054 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/costfee/CostFeeMachDepr.java @@ -0,0 +1,30 @@ +package com.zteits.urbanops.module.garden.job.costfee; + +import com.zteits.urbanops.framework.quartz.core.handler.JobHandler; +import com.zteits.urbanops.module.garden.service.mechanicaldepreciation.MechanicalDepreciationService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; + +/** + * @Classname CostFeeMachDepr + * @Description 人机材自有机械折旧处理 + * @Date 2025/12/25 10:43 + * @Created by wangqian + */ +@Component +@Slf4j +public class CostFeeMachDepr implements JobHandler { + @Resource + private MechanicalDepreciationService mechanicalDepreciationService; + @Override + public String execute(String param) throws Exception { + log.info("自有机械折旧定时任务,开始========"+ LocalDate.now()); + int count = mechanicalDepreciationService.batchSaveMechDepr(param); + log.info("自有机械折,mechanicalCostList.size=" + count); + log.info("自有机械折旧定时任务,结束========"+ LocalDate.now()); + return "Successfully"; + } +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/task/AssignTaskJob.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/task/AssignTaskJob.java new file mode 100644 index 0000000..26fc92c --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/task/AssignTaskJob.java @@ -0,0 +1,27 @@ +package com.zteits.urbanops.module.garden.job.task; + +import com.zteits.urbanops.framework.quartz.core.handler.JobHandler; +import com.zteits.urbanops.module.garden.service.assigntasks.AssignTasksService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @Classname AssignTaskJob + * @Description 派单超时处理 + * @Date 2025/12/25 10:37 + * @Created by wangqian + */ +@Component +@Slf4j +public class AssignTaskJob implements JobHandler { + + @Resource + private AssignTasksService assignTasksService; + + @Override + public String execute(String param) throws Exception { + assignTasksService.tasksOutTimeAuto(); + return "Successfully"; + } +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasks/AssignTasksServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasks/AssignTasksServiceImpl.java index 47c18c9..a3a3e4b 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasks/AssignTasksServiceImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasks/AssignTasksServiceImpl.java @@ -219,7 +219,7 @@ public class AssignTasksServiceImpl implements AssignTasksService { List taskInfoList = assiAssignTasksInfoMapper.selectList(queryWrapper); if (CollectionUtils.isEmpty(taskInfoList)) { log.info("未找到未完成的派单详情,无需处理"); - return 0; + continue; } // 4. 筛选“已超时”的派单详情(截止时间 < 当前时间) diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationService.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationService.java index b1be38d..4f5c1d4 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationService.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationService.java @@ -67,4 +67,6 @@ public interface MechanicalDepreciationService { */ void deleteMechanicalDepreciationByMechId(Long mechId); + public int batchSaveMechDepr(String depreciationMethod); + } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationServiceImpl.java index 8dd4ea2..5ba7882 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationServiceImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/mechanicaldepreciation/MechanicalDepreciationServiceImpl.java @@ -6,13 +6,27 @@ import com.zteits.urbanops.framework.common.pojo.PageResult; import com.zteits.urbanops.framework.common.util.object.BeanUtils; import com.zteits.urbanops.module.garden.controller.admin.mechanicaldepreciation.vo.MechanicalDepreciationPageReqVO; import com.zteits.urbanops.module.garden.controller.admin.mechanicaldepreciation.vo.MechanicalDepreciationSaveReqVO; +import com.zteits.urbanops.module.garden.dal.dataobject.mechanicalcost.MechanicalCostDO; import com.zteits.urbanops.module.garden.dal.dataobject.mechanicaldepreciation.MechanicalDepreciationDO; +import com.zteits.urbanops.module.garden.dal.mysql.mechanicalcost.MechanicalCostMapper; import com.zteits.urbanops.module.garden.dal.mysql.mechanicaldepreciation.MechanicalDepreciationMapper; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.MECHANICAL_DEPRECIATION_NOT_EXISTS; @@ -25,10 +39,13 @@ import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.MECHANI */ @Service @Validated +@Slf4j public class MechanicalDepreciationServiceImpl implements MechanicalDepreciationService { @Resource private MechanicalDepreciationMapper mechanicalDepreciationMapper; + @Resource + private MechanicalCostMapper mechanicalCostMapper; @Override public Long createMechanicalDepreciation(MechanicalDepreciationSaveReqVO createReqVO) { @@ -90,4 +107,172 @@ public class MechanicalDepreciationServiceImpl implements MechanicalDepreciation mechanicalDepreciationMapper.delete(queryWrapper); } + @Override + public int batchSaveMechDepr(String depreciationMethod) { + log.info("自有机械折旧业务处理,start"); + List mechanicalCostList = mechanicalCostMapper.selectList(MechanicalCostDO::getStatus, 0); + if (!CollectionUtils.isEmpty(mechanicalCostList)) { + straightLineMethod(mechanicalCostList); + } + log.info("自有机械折旧业务处理,end"); + return mechanicalCostList.size(); + } + /** + * @Author wangqian + * @Description 直线法 + * @Date 2025/8/3 10:47 + * @Param mechanicalCostList + * @Return int + */ + public void straightLineMethod(List mechanicalCostList) { + if (CollectionUtils.isEmpty(mechanicalCostList)) { + return; // 空集合直接返回,避免无效处理 + } + + // 1. 批量查询已有折旧记录 + Set mechIdSet = mechanicalCostList.stream() + .map(MechanicalCostDO::getId) + .collect(Collectors.toSet()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(MechanicalDepreciationDO::getMechId, mechIdSet); + List existingDepreciations = mechanicalDepreciationMapper.selectList(queryWrapper); + Set existingMechIdSet = existingDepreciations.stream() + .map(MechanicalDepreciationDO::getMechId) + .collect(Collectors.toSet()); + + // 2. 统一获取当前时间 + + for (MechanicalCostDO cost : mechanicalCostList) { + Long mechId = cost.getId(); + // 跳过已存在折旧记录的资产 + if (existingMechIdSet.contains(mechId)) { + continue; + } + // 3. 单价 + BigDecimal originalValue = cost.getUnitPrice(); + Integer serviceLifeYears = cost.getServiceLife(); + if (originalValue == null || originalValue.compareTo(BigDecimal.ZERO) <= 0 + || serviceLifeYears == null || serviceLifeYears <= 0) { + log.warn("资产ID:{} 折旧参数异常,原值:{}, 使用年限:{}", + mechId, originalValue, serviceLifeYears); + continue; + } + List toSaveList = new ArrayList<>(); // 收集待保存对象,批量插入 + + // 4. 计算固定参数 + Integer totalMonths = serviceLifeYears * 12; + BigDecimal residualRate = BigDecimal.ZERO; // 默认残值率0 + BigDecimal netValue = originalValue.multiply(BigDecimal.ONE.subtract(residualRate)); + + // 优化尾差计算:基础月折旧额 + 最后一个月调整 + // 先计算未四舍五入的精确月折旧额 + BigDecimal exactMonthlyDepreciation = netValue.divide(new BigDecimal(totalMonths), 10, BigDecimal.ROUND_HALF_UP); + // 计算四舍五入到分的基础月折旧额 + BigDecimal baseMonthlyDepreciation = exactMonthlyDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP); + // 计算总折旧额(基础月折旧 × 总月数) + BigDecimal totalDepreciation = baseMonthlyDepreciation.multiply(new BigDecimal(totalMonths)); + // 计算尾差(需要调整的金额) + BigDecimal tailDifference = netValue.subtract(totalDepreciation); + + // 5. 生成折旧期间列表(如YYYY-MM) + List depreciationPeriods = generateMonths(cost.getStartUseTime(), serviceLifeYears); + if (depreciationPeriods.size() != totalMonths) { + log.warn("资产ID:{} 折旧期间数量不匹配,计算月数:{}, 实际生成:{}", + mechId, totalMonths, depreciationPeriods.size()); + continue; // 期间数量异常时跳过,避免数据错误 + } + + // 6. 循环生成每月折旧记录 + BigDecimal accumulatedDepreciation = BigDecimal.ZERO; // 累计折旧初始化为0 + for (int i = 0; i < depreciationPeriods.size(); i++) { + MechanicalDepreciationDO depreciation = new MechanicalDepreciationDO(); + + // 固定属性(一次设置) + depreciation.setMechId(mechId); + depreciation.setOriginalValue(originalValue); + depreciation.setDepreciationMethod("直线法"); + depreciation.setResidualRate(residualRate); + depreciation.setServiceLife(serviceLifeYears); + depreciation.setNetValue(netValue); + + // 月度变化属性 - 处理尾差 + BigDecimal monthlyDepreciation; + // 如果是最后一个月,加上尾差调整 + if (i == depreciationPeriods.size() - 1) { + monthlyDepreciation = baseMonthlyDepreciation.add(tailDifference); + // 确保最后调整后没有因精度问题产生的微小偏差 + monthlyDepreciation = monthlyDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + monthlyDepreciation = baseMonthlyDepreciation; + } + + accumulatedDepreciation = accumulatedDepreciation.add(monthlyDepreciation); + depreciation.setDepreciationAmount(monthlyDepreciation); + depreciation.setAccumulatedDepreciation(accumulatedDepreciation); + depreciation.setRemainingPeriods(totalMonths - (i + 1)); // 剩余期数=总月数-已计提月数 + depreciation.setDepreciationPeriod(depreciationPeriods.get(i)); + + toSaveList.add(depreciation); + } + + // 额外校验:确保累计折旧等于净残值,避免计算错误 + if (accumulatedDepreciation.compareTo(netValue) != 0) { + log.error("资产ID:{} 折旧总和校验失败,应有:{}, 实际计算:{}", + mechId, netValue, accumulatedDepreciation); + continue; + } + + // 7. 批量插入,减少数据库交互 + if (!toSaveList.isEmpty()) { + mechanicalDepreciationMapper.insertBatch(toSaveList); // 假设新增批量插入方法 + } + } + } + + + + /** + * 生成从开始日期起指定年限内的所有月份(格式:yyyy-MM) + * + * @param localStartDate 开始日期(不能为null) + * @param years 年限(必须大于等于0) + * @return 月份字符串集合,若输入参数无效则返回空集合 + */ + public static List generateMonths(LocalDate localStartDate, Integer years) { + // 初始化返回集合 + List months = new ArrayList<>(); + + // 参数校验 + if (localStartDate == null || years == null || years < 0) { + return months; + } + + try { + // 转换为年月对象,从开始日期的当月开始 + YearMonth current = YearMonth.from(localStartDate); + + // 计算结束年月(开始日期加上指定年数) + YearMonth end = current.plusYears(years).minusMonths(1); + + // 定义日期格式化器(线程安全) + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM"); + + // 循环添加每个月 + while (!current.isAfter(end)) { + months.add(current.format(formatter)); + current = current.plusMonths(1); + } + } catch (Exception e) { + // 捕获所有异常,避免方法抛出异常影响调用方 + // 实际应用中可根据需要记录日志 + e.printStackTrace(); + } + + return months; + } + + public static void main(String[] args) { + LocalDate localDate = LocalDate.of(2024, 5, 6); + System.out.println(generateMonths(localDate, 1)); + } }