From 5a6aaf5da72ef3ab00638bf8c9cbe068b66920a9 Mon Sep 17 00:00:00 2001 From: syruan <15555146157@163.com> Date: Sat, 30 Aug 2025 16:53:11 +0800 Subject: [PATCH] =?UTF-8?q?=EF=BC=88new=EF=BC=89=E5=8C=BA=E9=97=B4?= =?UTF-8?q?=E8=B4=B9=E7=94=A8=E8=AE=A1=E7=AE=97=E5=8A=9F=E8=83=BD=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/LeaseOutDetailsServiceImpl.java | 12 +- .../SltAgreementInfoController.java | 76 +++- .../domain/dto/PeriodCostQueryDto.java | 64 +++ .../domain/vo/PeriodCostResultVo.java | 96 ++++ .../domain/vo/PeriodCostSummaryVo.java | 100 +++++ .../mapper/SltAgreementInfoMapper.java | 9 + .../service/ISltAgreementInfoService.java | 20 +- .../impl/SltAgreementInfoServiceImpl.java | 423 ++++++++++++++++++ .../settlement/SltAgreementInfoMapper.xml | 120 +++++ 9 files changed, 911 insertions(+), 9 deletions(-) create mode 100644 bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/dto/PeriodCostQueryDto.java create mode 100644 bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostResultVo.java create mode 100644 bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostSummaryVo.java diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/lease/service/impl/LeaseOutDetailsServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/lease/service/impl/LeaseOutDetailsServiceImpl.java index a3d37a90..3a5970c9 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/lease/service/impl/LeaseOutDetailsServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/lease/service/impl/LeaseOutDetailsServiceImpl.java @@ -67,19 +67,19 @@ public class LeaseOutDetailsServiceImpl implements ILeaseOutDetailsService { private static final Integer SYNC_RESOURCE = GlobalConstants.INT_2; @Autowired - LeaseApplyInfoMapper leaseApplyInfoMapper; + private LeaseApplyInfoMapper leaseApplyInfoMapper; @Autowired private LeaseOutDetailsMapper leaseOutDetailsMapper; @Autowired - LeaseApplyDetailsMapper leaseApplyDetailsMapper; + private LeaseApplyDetailsMapper leaseApplyDetailsMapper; @Autowired - MachineMapper machineMapper; + private MachineMapper machineMapper; @Autowired - TypeMapper typeMapper; + private TypeMapper typeMapper; @Autowired private TmTaskMapper tmTaskMapper; @@ -88,10 +88,10 @@ public class LeaseOutDetailsServiceImpl implements ILeaseOutDetailsService { private SltAgreementInfoMapper sltAgreementInfoMapper; @Autowired - BmAgreementInfoMapper bmAgreementInfoMapper; + private BmAgreementInfoMapper bmAgreementInfoMapper; @Autowired - TmTaskAgreementMapper tmTaskAgreementMapper; + private TmTaskAgreementMapper tmTaskAgreementMapper; @Resource private BmQrBoxMapper bmQrBoxMapper; diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/controller/SltAgreementInfoController.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/controller/SltAgreementInfoController.java index 141f2686..f261851b 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/controller/SltAgreementInfoController.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/controller/SltAgreementInfoController.java @@ -15,10 +15,9 @@ import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONObject; import com.bonus.common.biz.config.ListPagingUtil; import com.bonus.common.biz.config.PoiOutPage; -import com.bonus.common.core.exception.ServiceException; import com.bonus.common.core.utils.ServletUtils; import com.bonus.common.log.enums.OperaType; -import com.bonus.common.security.utils.SecurityUtils; +import com.bonus.common.log.enums.OperatorType; import com.bonus.material.basic.domain.BmProject; import com.bonus.material.common.annotation.PreventRepeatSubmit; import com.bonus.material.common.domain.dto.SelectDto; @@ -42,12 +41,17 @@ import org.springframework.web.bind.annotation.*; import com.bonus.common.log.annotation.SysLog; import com.bonus.common.security.annotation.RequiresPermissions; import com.bonus.material.settlement.domain.SltAgreementInfo; +import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto; +import com.bonus.material.settlement.domain.vo.PeriodCostResultVo; +import com.bonus.material.settlement.domain.vo.PeriodCostSummaryVo; import com.bonus.material.settlement.service.ISltAgreementInfoService; import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.utils.poi.ExcelUtil; import com.bonus.common.core.web.page.TableDataInfo; +import java.util.ArrayList; + /** * 结算信息Controller * @@ -1530,4 +1534,72 @@ public class SltAgreementInfoController extends BaseController { return error("系统错误, " + e.getMessage()); } } + + /** + * 查询租赁区间费用明细 + */ + @ApiOperation(value = "查询租赁区间费用明细") + //@RequiresPermissions("settlement:info:periodCost") + @GetMapping("/leasePeriodCostDetails") + public TableDataInfo leasePeriodCostDetails(PeriodCostQueryDto queryDto) { + try { + //startPage(); + List list = sltAgreementInfoService.selectPeriodCostList(queryDto); + return getDataTable(list); + } catch (Exception e) { + log.error("查询区间费用失败", e); + return getDataTable(new ArrayList<>()); + } + } + + /** + * 导出区间费用计算结果 + */ + @ApiOperation(value = "导出区间费用计算结果") + //@RequiresPermissions("settlement:info:periodCostExport") + @SysLog(title = "区间费用计算", module = "费用报表", operatorType = OperatorType.MANAGE) + @PostMapping("/periodCost/export") + public void exportPeriodCost(HttpServletResponse response, @RequestBody PeriodCostQueryDto queryDto) { + try { + List list = sltAgreementInfoService.selectPeriodCostList(queryDto); + ExcelUtil util = new ExcelUtil<>(PeriodCostResultVo.class); + util.exportExcel(response, list, "区间费用计算结果"); + } catch (Exception e) { + log.error("导出区间费用失败", e); + } + } + + /** + * 查询区间租赁费用汇总报表(按协议汇总) + */ + @ApiOperation(value = "查询区间租赁费用汇总报表") + //@RequiresPermissions("settlement:info:periodCostSummary") + @GetMapping("leasePeriodCostList") + public TableDataInfo leasePeriodCostList(PeriodCostQueryDto queryDto) { + try { + //startPage(); + List list = sltAgreementInfoService.selectPeriodCostSummary(queryDto); + return getDataTable(list); + } catch (Exception e) { + log.error("查询区间费用汇总失败", e); + return getDataTable(new ArrayList<>()); + } + } + + /** + * 导出区间费用汇总结果 + */ + @ApiOperation(value = "导出区间费用汇总结果") + @RequiresPermissions("settlement:info:periodCostSummaryExport") + @SysLog(title = "区间费用汇总", module = "费用报表", operatorType = OperatorType.MANAGE) + @PostMapping("/periodCost/summary/export") + public void exportPeriodCostSummary(HttpServletResponse response, @RequestBody PeriodCostQueryDto queryDto) { + try { + List list = sltAgreementInfoService.selectPeriodCostSummary(queryDto); + ExcelUtil util = new ExcelUtil<>(PeriodCostSummaryVo.class); + util.exportExcel(response, list, "区间费用汇总结果"); + } catch (Exception e) { + log.error("导出区间费用汇总失败", e); + } + } } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/dto/PeriodCostQueryDto.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/dto/PeriodCostQueryDto.java new file mode 100644 index 00000000..65f49857 --- /dev/null +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/dto/PeriodCostQueryDto.java @@ -0,0 +1,64 @@ +package com.bonus.material.settlement.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * 区间费用查询DTO + * + * @author system + * @date 2024-12-30 + */ +@Data +@ApiModel("区间费用查询DTO") +public class PeriodCostQueryDto { + + @ApiModelProperty(value = "开始日期", required = true) + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "开始日期不能为空") + private Date startDate; + + @ApiModelProperty(value = "结束日期", required = true) + @JsonFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "结束日期不能为空") + private Date endDate; + + @ApiModelProperty(value = "协议ID列表") + private List agreementIds; + + @ApiModelProperty(value = "协议ID") + private Long agreementId; + + @ApiModelProperty(value = "往来单位ID列表") + private List unitIds; + + @ApiModelProperty(value = "工程标段ID列表") + private List projectIds; + + @ApiModelProperty(value = "机具规格ID列表") + private List typeIds; + + @ApiModelProperty(value = "结算状态 0-未结算 1-已结算") + private String settlementStatus; + + @ApiModelProperty(value = "协议编号") + private String agreementCode; + + @ApiModelProperty(value = "往来单位名称") + private String unitName; + + @ApiModelProperty(value = "工程标段名称") + private String projectName; + + @ApiModelProperty(value = "结算管理类型 1工器具 2安全工器具") + private Byte sltManageType; + + @ApiModelProperty(value = "数据所属组织ID") + private Long companyId; +} diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostResultVo.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostResultVo.java new file mode 100644 index 00000000..54afe21a --- /dev/null +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostResultVo.java @@ -0,0 +1,96 @@ +package com.bonus.material.settlement.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 区间费用计算结果VO + * + * @author syruan + */ +@Data +@ApiModel("区间费用计算结果VO") +public class PeriodCostResultVo { + + @ApiModelProperty(value = "协议ID") + private Long agreementId; + + @ApiModelProperty(value = "协议编号") + private String agreementCode; + + @ApiModelProperty(value = "往来单位ID") + private Long unitId; + + @ApiModelProperty(value = "往来单位名称") + private String unitName; + + @ApiModelProperty(value = "工程标段ID") + private Long projectId; + + @ApiModelProperty(value = "工程标段名称") + private String projectName; + + @ApiModelProperty(value = "机具规格ID") + private Long typeId; + + @ApiModelProperty(value = "机具规格名称") + private String typeName; + + @ApiModelProperty(value = "规格型号") + private String modelName; + + @ApiModelProperty(value = "机具ID") + private Long maId; + + @ApiModelProperty(value = "机具编号") + private String maCode; + + @ApiModelProperty(value = "租赁数量") + private BigDecimal num; + + @ApiModelProperty(value = "租赁单价") + private BigDecimal leasePrice; + + @ApiModelProperty(value = "计算开始时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date calcStartTime; + + @ApiModelProperty(value = "计算结束时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date calcEndTime; + + @ApiModelProperty(value = "租赁天数") + private Long leaseDays; + + @ApiModelProperty(value = "租赁费用") + private BigDecimal leaseCost; + + @ApiModelProperty(value = "是否已结算 0-未结算 1-已结算") + private String isSettled; + + @ApiModelProperty(value = "结算时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date settlementTime; + + @ApiModelProperty(value = "领料时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date startTime; + + @ApiModelProperty(value = "退料时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date endTime; + + @ApiModelProperty(value = "状态 0-在用 1-退回") + private String status; + + @ApiModelProperty(value = "计量单位") + private String mtUnitName; + + @ApiModelProperty(value = "备注") + private String remark; +} diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostSummaryVo.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostSummaryVo.java new file mode 100644 index 00000000..108887a0 --- /dev/null +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/domain/vo/PeriodCostSummaryVo.java @@ -0,0 +1,100 @@ +package com.bonus.material.settlement.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import com.bonus.common.core.annotation.Excel; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 区间费用汇总结果VO(按协议汇总) + * + * @author system + * @date 2024-12-30 + */ +@Data +@ApiModel("区间费用汇总结果VO") +public class PeriodCostSummaryVo { + + @ApiModelProperty(value = "协议ID") + private Long agreementId; + + @ApiModelProperty(value = "协议编号") + @Excel(name = "协议编号") + private String agreementCode; + + @ApiModelProperty(value = "往来单位ID") + private Long unitId; + + @ApiModelProperty(value = "往来单位名称") + @Excel(name = "往来单位") + private String unitName; + + @ApiModelProperty(value = "工程标段ID") + private Long projectId; + + @ApiModelProperty(value = "工程标段名称") + @Excel(name = "工程标段") + private String projectName; + + @ApiModelProperty(value = "协议签订日期") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "签订日期", width = 30, dateFormat = "yyyy-MM-dd") + private Date signTime; + + @ApiModelProperty(value = "是否已结算 0-未结算 1-已结算") + @Excel(name = "结算状态", readConverterExp = "0=未结算,1=已结算") + private String isSettled; + + @ApiModelProperty(value = "设备种类数量") + @Excel(name = "设备种类数") + private Integer equipmentTypeCount; + + @ApiModelProperty(value = "设备总数量") + @Excel(name = "设备总数") + private BigDecimal totalEquipmentCount; + + @ApiModelProperty(value = "总租赁天数") + @Excel(name = "总租赁天数") + private Long totalLeaseDays; + + @ApiModelProperty(value = "总租赁费用") + @Excel(name = "总租赁费用") + private BigDecimal totalLeaseCost; + + @ApiModelProperty(value = "平均日租金") + @Excel(name = "平均日租金") + private BigDecimal avgDailyRent; + + @ApiModelProperty(value = "查询区间开始时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "查询开始日期", width = 30, dateFormat = "yyyy-MM-dd") + private Date queryStartDate; + + @ApiModelProperty(value = "查询区间结束时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "查询结束日期", width = 30, dateFormat = "yyyy-MM-dd") + private Date queryEndDate; + + @ApiModelProperty(value = "最早领料时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "最早领料时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date earliestLeaseTime; + + @ApiModelProperty(value = "最晚退料时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "最晚退料时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date latestReturnTime; + + @ApiModelProperty(value = "结算时间") + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "结算时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date settlementTime; + + @ApiModelProperty(value = "备注") + @Excel(name = "备注") + private String remark; +} diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/mapper/SltAgreementInfoMapper.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/mapper/SltAgreementInfoMapper.java index efde9af7..5b308bcc 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/mapper/SltAgreementInfoMapper.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/mapper/SltAgreementInfoMapper.java @@ -11,6 +11,8 @@ import com.bonus.material.settlement.domain.SltAgreementApply; import com.bonus.material.settlement.domain.SltAgreementInfo; import com.bonus.material.settlement.domain.SltAgreementRelation; import com.bonus.material.settlement.domain.vo.SltInfoVo; +import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto; +import com.bonus.material.settlement.domain.vo.PeriodCostResultVo; import com.bonus.material.task.domain.TmTask; import org.apache.ibatis.annotations.Param; @@ -267,4 +269,11 @@ public interface SltAgreementInfoMapper { * @return */ List getSltAgreementInfoById(SltAgreementInfo info); + + /** + * 查询区间费用计算结果 + * @param queryDto 查询条件 + * @return 区间费用计算结果列表 + */ + List selectLeasePeriodCostList(PeriodCostQueryDto queryDto); } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/ISltAgreementInfoService.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/ISltAgreementInfoService.java index 481e3ce4..da0e5e4e 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/ISltAgreementInfoService.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/ISltAgreementInfoService.java @@ -5,10 +5,12 @@ import java.util.List; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.material.basic.domain.BmProject; import com.bonus.material.common.domain.dto.SelectDto; -import com.bonus.material.countersign.domain.SignConfigVo; import com.bonus.material.settlement.domain.SltAgreementApply; import com.bonus.material.settlement.domain.SltAgreementInfo; import com.bonus.material.settlement.domain.vo.SltInfoVo; +import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto; +import com.bonus.material.settlement.domain.vo.PeriodCostResultVo; +import com.bonus.material.settlement.domain.vo.PeriodCostSummaryVo; /** * 结算信息Service接口 @@ -156,4 +158,20 @@ public interface ISltAgreementInfoService { AjaxResult getAgreementInfoById(SelectDto dto); + + /** + * 查询区间费用计算结果 + * + * @param queryDto 查询条件 + * @return 区间费用计算结果列表 + */ + List selectPeriodCostList(PeriodCostQueryDto queryDto); + + /** + * 查询区间费用汇总结果(按协议汇总) + * + * @param queryDto 查询条件 + * @return 区间费用汇总结果列表 + */ + List selectPeriodCostSummary(PeriodCostQueryDto queryDto); } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/impl/SltAgreementInfoServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/impl/SltAgreementInfoServiceImpl.java index 23d15675..a2c360d0 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/impl/SltAgreementInfoServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/settlement/service/impl/SltAgreementInfoServiceImpl.java @@ -32,11 +32,19 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.bonus.material.settlement.mapper.SltAgreementInfoMapper; import com.bonus.material.settlement.domain.SltAgreementInfo; +import com.bonus.material.settlement.domain.dto.PeriodCostQueryDto; +import com.bonus.material.settlement.domain.vo.PeriodCostResultVo; +import com.bonus.material.settlement.domain.vo.PeriodCostSummaryVo; import com.bonus.material.settlement.service.ISltAgreementInfoService; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Comparator; +import java.util.Map; +import java.util.Objects; /** * 结算信息Service业务层处理 @@ -1059,4 +1067,419 @@ public class SltAgreementInfoServiceImpl implements ISltAgreementInfoService { } return AjaxResult.success(vo); } + + /** + * 查询区间费用计算结果 + * + * @param queryDto 查询条件 + * @return 区间费用计算结果列表 + */ + @Override + public List selectPeriodCostList(@NotNull(message = "查询条件不能为空") PeriodCostQueryDto queryDto) { + // 参数校验 + if (queryDto.getStartDate() == null || queryDto.getEndDate() == null) { + throw new ServiceException("开始日期和结束日期不能为空"); + } + + if (queryDto.getStartDate().after(queryDto.getEndDate())) { + throw new ServiceException("开始日期不能大于结束日期"); + } + + try { + // 查询当前登陆用户的结算管理权限 + Byte settlementType = this.checkLoginUserHasSettlementPermission(); + queryDto.setSltManageType(settlementType); + + // 从数据库查询基础数据 + List rawResults = sltAgreementInfoMapper.selectLeasePeriodCostList(queryDto); + + // 先过滤掉不在查询范围内的数据 + List filteredResults = filterDataInRange(rawResults, queryDto.getStartDate(), queryDto.getEndDate()); + + // 在Service层进行逻辑计算 + return calculatePeriodCosts(filteredResults, queryDto.getStartDate(), queryDto.getEndDate()); + } catch (Exception e) { + throw new ServiceException("查询区间费用失败:" + e.getMessage()); + } + } + + /** + * 过滤掉不在查询范围内的数据 + * + * @param rawResults 原始查询结果 + * @param inputStartDate 前端输入的开始日期 + * @param inputEndDate 前端输入的结束日期 + * @return 过滤后的结果列表 + */ + private List filterDataInRange(List rawResults, + Date inputStartDate, Date inputEndDate) { + List filteredResults = new ArrayList<>(); + + for (PeriodCostResultVo result : rawResults) { + if (isDataInRange(result, inputStartDate, inputEndDate)) { + filteredResults.add(result); + } + } + + return filteredResults; + } + + /** + * 判断数据是否在查询范围内 + * + * @param result 数据记录 + * @param inputStartDate 前端输入的开始日期 + * @param inputEndDate 前端输入的结束日期 + * @return 是否在范围内 + */ + private boolean isDataInRange(PeriodCostResultVo result, Date inputStartDate, Date inputEndDate) { + Date leaseStartTime = result.getStartTime(); // 领料时间 + Date returnTime = result.getEndTime(); // 退料时间 + Date settlementTime = result.getSettlementTime(); // 结算时间 + + // 如果是已结算协议 + if ("1".equals(result.getIsSettled())) { + // 检查领料时间、退料时间、结算时间是否有任何一个在查询范围内 + boolean leaseInRange = isDateInRange(leaseStartTime, inputStartDate, inputEndDate); + boolean returnInRange = isDateInRange(returnTime, inputStartDate, inputEndDate); + boolean settlementInRange = isDateInRange(settlementTime, inputStartDate, inputEndDate); + + return leaseInRange || returnInRange || settlementInRange; + } else { + // 如果是未结算协议 + // 检查领料时间、退料时间是否有任何一个在查询范围内 + boolean leaseInRange = isDateInRange(leaseStartTime, inputStartDate, inputEndDate); + boolean returnInRange = isDateInRange(returnTime, inputStartDate, inputEndDate); + + return leaseInRange || returnInRange; + } + } + + /** + * 判断日期是否在指定范围内 + * + * @param date 要检查的日期 + * @param startDate 范围开始日期 + * @param endDate 范围结束日期 + * @return 是否在范围内 + */ + private boolean isDateInRange(Date date, Date startDate, Date endDate) { + if (date == null) { + return false; + } + + return !date.before(startDate) && !date.after(endDate); + } + + /** + * 计算区间费用 + * + * @param filteredResults 过滤后的查询结果 + * @param inputStartDate 前端输入的开始日期 + * @param inputEndDate 前端输入的结束日期 + * @return 计算后的结果列表 + */ + private List calculatePeriodCosts(List filteredResults, + Date inputStartDate, Date inputEndDate) { + List calculatedResults = new ArrayList<>(); + + for (PeriodCostResultVo result : filteredResults) { + try { + // 计算实际的开始和结束时间 + Date calcStartTime; + Date calcEndTime; + + if ("1".equals(result.getIsSettled())) { + // 已结算协议计算规则 + calcStartTime = calculateSettledStartTime(result, inputStartDate); + calcEndTime = calculateSettledEndTime(result, inputEndDate); + } else { + // 未结算协议计算规则 + calcStartTime = calculateUnsettledStartTime(result, inputStartDate); + calcEndTime = calculateUnsettledEndTime(result, inputEndDate); + } + + // 确保计算时间在输入区间内且合理 + if (calcStartTime != null && calcEndTime != null && !calcStartTime.after(calcEndTime)) { + // 计算租赁天数 + long leaseDays = calculateDaysBetween(calcStartTime, calcEndTime); + + // 计算租赁费用 + BigDecimal leaseCost = BigDecimal.ZERO; + if (result.getNum() != null && result.getLeasePrice() != null && leaseDays > 0) { + leaseCost = result.getNum() + .multiply(result.getLeasePrice()) + .multiply(new BigDecimal(leaseDays)) + .setScale(2, RoundingMode.HALF_UP); + } + + // 设置计算结果 + result.setCalcStartTime(calcStartTime); + result.setCalcEndTime(calcEndTime); + result.setLeaseDays(leaseDays); + result.setLeaseCost(leaseCost); + + calculatedResults.add(result); + } + + } catch (Exception e) { + // 记录错误但不中断处理 + System.err.println("计算协议 " + result.getAgreementCode() + " 费用时出错: " + e.getMessage()); + } + } + + return calculatedResults; + } + + /** + * 计算已结算协议的开始时间 + */ + private Date calculateSettledStartTime(PeriodCostResultVo result, Date inputStartDate) { + Date leaseStartTime = result.getStartTime(); // 领料时间 + + if (leaseStartTime == null) { + return inputStartDate; + } + + // 如果领料时间在输入区间开始之前,使用输入开始时间 + if (leaseStartTime.before(inputStartDate)) { + return inputStartDate; + } + + // 否则使用领料时间 + return leaseStartTime; + } + + /** + * 计算已结算协议的结束时间 + */ + private Date calculateSettledEndTime(PeriodCostResultVo result, Date inputEndDate) { + Date settlementTime = result.getSettlementTime(); // 结算时间 + Date returnTime = result.getEndTime(); // 退料时间 + + // 如果有退料时间,优先使用退料时间 + if (returnTime != null) { + // 如果退料时间在输入区间结束之后,使用输入结束时间 + if (returnTime.after(inputEndDate)) { + return inputEndDate; + } + return returnTime; + } + + // 如果没有退料时间但有结算时间,使用结算时间作为退料时间 + if (settlementTime != null) { + // 如果结算时间在输入区间结束之前,使用结算时间 + if (settlementTime.before(inputEndDate) || settlementTime.equals(inputEndDate)) { + return settlementTime; + } + // 如果结算时间在输入区间结束之后,使用输入结束时间 + return inputEndDate; + } + + // 如果既没有退料时间也没有结算时间,使用输入结束时间 + return inputEndDate; + } + + /** + * 计算未结算协议的开始时间 + */ + private Date calculateUnsettledStartTime(PeriodCostResultVo result, Date inputStartDate) { + Date leaseStartTime = result.getStartTime(); // 领料时间 + + if (leaseStartTime == null) { + return inputStartDate; + } + + // 如果领料时间在输入区间开始之前,使用输入开始时间 + if (leaseStartTime.before(inputStartDate)) { + return inputStartDate; + } + + // 否则使用领料时间 + return leaseStartTime; + } + + /** + * 计算未结算协议的结束时间 + */ + private Date calculateUnsettledEndTime(PeriodCostResultVo result, Date inputEndDate) { + Date returnTime = result.getEndTime(); // 退料时间 + + // 如果有退料时间 + if (returnTime != null) { + // 如果退料时间在输入区间结束之后,使用输入结束时间 + if (returnTime.after(inputEndDate)) { + return inputEndDate; + } + return returnTime; + } + + // 如果没有退料时间,使用输入结束时间 + return inputEndDate; + } + + /** + * 计算两个日期之间的天数(包含起始和结束日期) + * 只计算日期,不考虑具体时间 + * 例如:8月15日~8月16日 = 2天 + * + * @param startDate 开始日期 + * @param endDate 结束日期 + * @return 天数 + */ + private long calculateDaysBetween(Date startDate, Date endDate) { + if (startDate == null || endDate == null) { + return 0; + } + + if (startDate.after(endDate)) { + return 0; + } + + // 使用Calendar来确保只计算日期部分,忽略时间 + Calendar startCal = Calendar.getInstance(); + startCal.setTime(startDate); + startCal.set(Calendar.HOUR_OF_DAY, 0); + startCal.set(Calendar.MINUTE, 0); + startCal.set(Calendar.SECOND, 0); + startCal.set(Calendar.MILLISECOND, 0); + + Calendar endCal = Calendar.getInstance(); + endCal.setTime(endDate); + endCal.set(Calendar.HOUR_OF_DAY, 0); + endCal.set(Calendar.MINUTE, 0); + endCal.set(Calendar.SECOND, 0); + endCal.set(Calendar.MILLISECOND, 0); + + // 计算天数差异 + long diffInMillies = endCal.getTimeInMillis() - startCal.getTimeInMillis(); + long diffInDays = diffInMillies / (24 * 60 * 60 * 1000); + + // 包含起始和结束日期,所以要加1 + return diffInDays + 1; + } + + /** + * 查询区间费用汇总结果(按协议汇总) + * + * @param queryDto 查询条件 + * @return 区间费用汇总结果列表 + */ + @Override + public List selectPeriodCostSummary(PeriodCostQueryDto queryDto) { + // 参数校验 + if (queryDto.getStartDate() == null || queryDto.getEndDate() == null) { + throw new ServiceException("开始日期和结束日期不能为空"); + } + + if (queryDto.getStartDate().after(queryDto.getEndDate())) { + throw new ServiceException("开始日期不能大于结束日期"); + } + + try { + // 先获取明细数据 + List detailList = this.selectPeriodCostList(queryDto); + + // 按协议ID分组汇总 + return aggregateByAgreement(detailList, queryDto.getStartDate(), queryDto.getEndDate()); + } catch (Exception e) { + throw new ServiceException("查询区间费用汇总失败:" + e.getMessage()); + } + } + + /** + * 按协议汇总费用数据 + * + * @param detailList 明细数据列表 + * @param queryStartDate 查询开始日期 + * @param queryEndDate 查询结束日期 + * @return 汇总结果列表 + */ + private List aggregateByAgreement(List detailList, + Date queryStartDate, Date queryEndDate) { + // 按协议ID分组 + Map> groupedByAgreement = detailList.stream() + .collect(Collectors.groupingBy(PeriodCostResultVo::getAgreementId)); + + List summaryList = new ArrayList<>(); + + for (Map.Entry> entry : groupedByAgreement.entrySet()) { + Long agreementId = entry.getKey(); + List agreementDetails = entry.getValue(); + + if (agreementDetails.isEmpty()) { + continue; + } + + // 取第一条记录的基本信息 + PeriodCostResultVo firstDetail = agreementDetails.get(0); + + PeriodCostSummaryVo summary = new PeriodCostSummaryVo(); + summary.setAgreementId(agreementId); + summary.setAgreementCode(firstDetail.getAgreementCode()); + summary.setUnitId(firstDetail.getUnitId()); + summary.setUnitName(firstDetail.getUnitName()); + summary.setProjectId(firstDetail.getProjectId()); + summary.setProjectName(firstDetail.getProjectName()); + summary.setIsSettled(firstDetail.getIsSettled()); + summary.setQueryStartDate(queryStartDate); + summary.setQueryEndDate(queryEndDate); + summary.setRemark(firstDetail.getRemark()); + + // 计算汇总数据 + int equipmentTypeCount = agreementDetails.size(); // 设备种类数量 + BigDecimal totalEquipmentCount = agreementDetails.stream() + .map(detail -> detail.getNum() != null ? detail.getNum() : BigDecimal.ZERO) + .reduce(BigDecimal.ZERO, BigDecimal::add); // 设备总数量 + + long totalLeaseDays = agreementDetails.stream() + .mapToLong(detail -> detail.getLeaseDays() != null ? detail.getLeaseDays() : 0L) + .sum(); // 总租赁天数 + + BigDecimal totalLeaseCost = agreementDetails.stream() + .map(detail -> detail.getLeaseCost() != null ? detail.getLeaseCost() : BigDecimal.ZERO) + .reduce(BigDecimal.ZERO, BigDecimal::add); // 总租赁费用 + + // 计算平均日租金 + BigDecimal avgDailyRent = BigDecimal.ZERO; + if (totalLeaseDays > 0) { + avgDailyRent = totalLeaseCost.divide(new BigDecimal(totalLeaseDays), 2, RoundingMode.HALF_UP); + } + + // 找出最早领料时间和最晚退料时间 + Date earliestLeaseTime = agreementDetails.stream() + .map(PeriodCostResultVo::getStartTime) + .filter(Objects::nonNull) + .min(Date::compareTo) + .orElse(null); + + Date latestReturnTime = agreementDetails.stream() + .map(PeriodCostResultVo::getEndTime) + .filter(Objects::nonNull) + .max(Date::compareTo) + .orElse(null); + + Date settlementTime = agreementDetails.stream() + .map(PeriodCostResultVo::getSettlementTime) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + + summary.setEquipmentTypeCount(equipmentTypeCount); + summary.setTotalEquipmentCount(totalEquipmentCount); + summary.setTotalLeaseDays(totalLeaseDays); + summary.setTotalLeaseCost(totalLeaseCost); + summary.setAvgDailyRent(avgDailyRent); + summary.setEarliestLeaseTime(earliestLeaseTime); + summary.setLatestReturnTime(latestReturnTime); + summary.setSettlementTime(settlementTime); + + summaryList.add(summary); + } + + // 按协议编号排序 + summaryList.sort(Comparator.comparing(PeriodCostSummaryVo::getAgreementCode)); + + return summaryList; + } } diff --git a/bonus-modules/bonus-material/src/main/resources/mapper/material/settlement/SltAgreementInfoMapper.xml b/bonus-modules/bonus-material/src/main/resources/mapper/material/settlement/SltAgreementInfoMapper.xml index f239521c..da4647f7 100644 --- a/bonus-modules/bonus-material/src/main/resources/mapper/material/settlement/SltAgreementInfoMapper.xml +++ b/bonus-modules/bonus-material/src/main/resources/mapper/material/settlement/SltAgreementInfoMapper.xml @@ -25,6 +25,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + + + + + + + + + + + + + + + + + + + + select id, agreement_id, type_id, ma_id, num, start_time, end_time, status, lease_id, back_id, lease_price, buy_price, is_slt, slt_time, company_id, lease_type, trim_day, create_time, update_time from slt_agreement_info @@ -1082,4 +1106,100 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" GROUP BY sai.agreement_id,mt.type_id + + +