shiyunteng
2026-06-18 5badb0e02901c3ea5570fdb9cf497aec7e48fd65
feat:新增账龄行业、地区分析账龄分析
10个文件已修改
4个文件已添加
824 ■■■■■ 已修改文件
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AgingQueryDTO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AnalysisCommonDTO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/BusinessCustomer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingAnalysisVo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingCompanyVo.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingVo.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/PaymentConfirmController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/StatisticController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/ContractPaymentScheduleMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/PaymentConfirmService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/StatisticService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/StatisticServiceImpl.java 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/mapper/ContractPaymentScheduleMapper.xml 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AgingQueryDTO.java
New file
@@ -0,0 +1,28 @@
package com.by4cloud.platformx.business.dto;
import lombok.Data;
import java.util.Date;
@Data
public class AgingQueryDTO {
    private Long companyId;
    private String areaId;
    private String industryId;
    /**
     * 账龄计算日期类型
     *  1/约定时间 2/发货时间 3/开票时间
     */
    private String agingType;
    /**
     * 账龄计算日期
     *  1/约定时间 2/发货时间 3/开票时间
     */
    private Date agingDate;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AnalysisCommonDTO.java
@@ -7,4 +7,10 @@
    private String year;
    /**
     * 账龄计算日期
     *  1/约定时间 2/发货时间 3/开票时间
     */
    private String agingType;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/BusinessCustomer.java
@@ -78,7 +78,7 @@
    private String registerName;
    @Schema(description = "开户银行")
    @Column(columnDefinition = "VARCHAR(20) comment '开户银行'")
    @Column(columnDefinition = "VARCHAR(255) comment '开户银行'")
    private String bankName;
    @Schema(description = "银行账号")
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingAnalysisVo.java
New file
@@ -0,0 +1,16 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class AgingAnalysisVo {
    private String companyName;
    private List<BigDecimal> amount;
    private List<BigDecimal> percent;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingCompanyVo.java
New file
@@ -0,0 +1,12 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class AgingCompanyVo {
    private Long companyId;
    private Long compId;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/AgingVo.java
New file
@@ -0,0 +1,26 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class AgingVo {
    private String overdueRange;
    private BigDecimal totalAmount;
    private BigDecimal totalPercent;
    public AgingVo(String overdueRange,BigDecimal totalAmount, BigDecimal totalPercent) {
        this.overdueRange = overdueRange;
        this.totalAmount = totalAmount;
        this.totalPercent = totalPercent;
    }
    public AgingVo(String overdueRange, BigDecimal totalAmount) {
        this.overdueRange = overdueRange;
        this.totalAmount = totalAmount;
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/PaymentConfirmController.java
@@ -13,6 +13,7 @@
import com.by4cloud.platformx.common.log.annotation.SysLog;
import com.by4cloud.platformx.business.entity.PaymentConfirm;
import com.by4cloud.platformx.business.service.PaymentConfirmService;
import com.by4cloud.platformx.common.security.annotation.Inner;
import org.springframework.security.access.prepost.PreAuthorize;
import com.by4cloud.platformx.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -142,4 +143,13 @@
    public R queryAllBusinessType(){
        return paymentConfirmService.queryAllBusinessType();
    }
    /**
     * 账龄详细查询
     */
    @GetMapping("queryAging")
    public R queryAging(){
        return paymentConfirmService.queryAging();
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/StatisticController.java
@@ -120,4 +120,31 @@
    public R contractAmountAnalysisBySaleModel(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisBySaleModel(commonDTO);
    }
    /**
     * 账龄地区分析
     * @return R
     */
    @PostMapping("/agingAnalysisByArea")
    public R agingAnalysisByArea(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.agingAnalysisByArea(commonDTO);
    }
    /**
     * 账龄行业分析
     * @return R
     */
    @PostMapping("/agingAnalysisByIndustry")
    public R agingAnalysisByIndustry(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.agingAnalysisByIndustry(commonDTO);
    }
    /**
     * 账龄分析
     * @return R
     */
    @PostMapping("/agingAnalysis")
    public R agingAnalysis(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.agingAnalysis(commonDTO);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/ContractPaymentScheduleMapper.java
@@ -1,11 +1,29 @@
package com.by4cloud.platformx.business.mapper;
import com.by4cloud.platformx.business.dto.AgingQueryDTO;
import com.by4cloud.platformx.business.entity.ContractPaymentSchedule;
import com.by4cloud.platformx.business.vo.AgingCompanyVo;
import com.by4cloud.platformx.business.vo.AgingVo;
import com.by4cloud.platformx.common.data.datascope.DataScope;
import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ContractPaymentScheduleMapper extends PlatformxBaseMapper<ContractPaymentSchedule> {
    List<AgingCompanyVo> selectAgingCompany(@Param("queryDTO") AgingQueryDTO queryDT,DataScope compId);
    List<AgingVo> selectAgingTotal(@Param("queryDTO") AgingQueryDTO queryDTO);
    List<AgingCompanyVo> selectAgingCompanyShip(DataScope comp_id);
    List<AgingCompanyVo> selectAgingCompanyInvoice(DataScope comp_id);
    List<AgingVo> selectAgingTotalShip(@Param("queryDTO") AgingQueryDTO queryDTO);
    List<AgingVo> selectAgingTotalInvoice(@Param("queryDTO") AgingQueryDTO queryDTO);
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/PaymentConfirmService.java
@@ -17,4 +17,6 @@
    void saveBipRequestRecord(JSONObject params,String methodName, String result);
    R queryAllBusinessType();
    R queryAging();
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/StatisticService.java
@@ -23,4 +23,10 @@
    R contractAmountAnalysisByComp(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisBySaleModel(AnalysisCommonDTO commonDTO);
    R agingAnalysisByArea(AnalysisCommonDTO commonDTO);
    R agingAnalysisByIndustry(AnalysisCommonDTO commonDTO);
    R agingAnalysis(AnalysisCommonDTO commonDTO);
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -13,6 +13,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.admin.api.entity.SysDept;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.business.dto.AgingQueryDTO;
import com.by4cloud.platformx.business.dto.PaymentConfirmAddDTO;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.*;
@@ -20,7 +21,11 @@
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.business.service.PaymentConfirmService;
import com.by4cloud.platformx.business.utils.SignHelper;
import com.by4cloud.platformx.business.vo.AgingAnalysisVo;
import com.by4cloud.platformx.business.vo.AgingCompanyVo;
import com.by4cloud.platformx.business.vo.AgingVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.data.datascope.DataScope;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -30,11 +35,13 @@
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
 * 收款确认
@@ -849,4 +856,96 @@
        return R.ok(baseMapper.selectList(Wrappers.<PaymentConfirm>lambdaQuery().select(PaymentConfirm::getBusinessType).isNotNull(PaymentConfirm::getBusinessType)
                        .groupBy(PaymentConfirm::getBusinessType)).stream().map(PaymentConfirm::getBusinessType).collect(Collectors.toList()));
    }
    @Override
    public R queryAging() {
        List<AgingCompanyVo> companys = contractPaymentScheduleMapper.selectAgingCompany(null,DataScope.of("comp_id"));
        if (ArrayUtil.isEmpty(companys.toArray())){
            return R.failed("暂无账龄");
        }
        List<AgingAnalysisVo> result = new ArrayList<>();
        AgingQueryDTO queryDTO = new AgingQueryDTO();
        List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotal(null);
        companys.stream().forEach(company->{
            BusinessCustomer businessCustomer = businessCustomerService.getById(company.getCompanyId());
            AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
            agingAnalysisVo.setCompanyName(businessCustomer.getCompanyName());
            queryDTO.setCompanyId(company.getCompanyId());
            List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotal(queryDTO);
            //补全数据
            if (ArrayUtil.isEmpty(companyAgingVo.toArray())){
                companyAgingVo = new ArrayList<>();
                AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                companyAgingVo.add(agingVo1);
                companyAgingVo.add(agingVo2);
                companyAgingVo.add(agingVo3);
                companyAgingVo.add(agingVo4);
                companyAgingVo.add(agingVo5);
                companyAgingVo.add(agingVo6);
            }else {
                List<String> overdueRanges = companyAgingVo.stream().map(AgingVo::getOverdueRange).collect(Collectors.toList());
                if (!ArrayUtil.contains(overdueRanges.toArray(),"0-30天")){
                    AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo1);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"31-60天")){
                    AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo2);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"61-90天")){
                    AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo3);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"91-180天")){
                    AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo4);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"181-365天")){
                    AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo5);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"1年以上")){
                    AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo6);
                }
            }
            agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
            List<AgingVo> finalCompanyAgingVo = companyAgingVo;
            agingAnalysisVo.setPercent(IntStream.range(0, agingVoList.size())
                    .mapToObj(i -> {
                        BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                        BigDecimal total = agingVoList.get(i).getTotalAmount();
                        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                            return null;
                        }
                        return part.divide(total, 4, RoundingMode.HALF_UP)
                                .multiply(new BigDecimal("100"))
                                .setScale(2, RoundingMode.HALF_UP);
                    })
                    .collect(Collectors.toList()));
            result.add(agingAnalysisVo);
        });
        //合计
        AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
        agingAnalysisVo.setCompanyName("合计");
        agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
        List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
                .mapToObj(i -> {
                    if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                        return null;
                    }else {
                        return new BigDecimal("100");
                    }
                })
                .collect(Collectors.toList());
        agingAnalysisVo.setPercent(percent);
        result.add(agingAnalysisVo);
        return R.ok(result);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/StatisticServiceImpl.java
@@ -5,25 +5,35 @@
import com.by4cloud.platformx.admin.api.entity.SysDictItem;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.admin.api.feign.RemoteDictService;
import com.by4cloud.platformx.business.dto.AgingQueryDTO;
import com.by4cloud.platformx.business.dto.AnalysisCommonDTO;
import com.by4cloud.platformx.business.entity.BusinessCustomer;
import com.by4cloud.platformx.business.mapper.BusinessCustomerMapper;
import com.by4cloud.platformx.business.mapper.ContractMapper;
import com.by4cloud.platformx.business.mapper.ContractPaymentScheduleMapper;
import com.by4cloud.platformx.business.service.StatisticService;
import com.by4cloud.platformx.business.vo.*;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.data.datascope.DataScope;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Service
@RequiredArgsConstructor
public class StatisticServiceImpl implements StatisticService {
    private final ContractMapper contractMapper;
    private final ContractPaymentScheduleMapper contractPaymentScheduleMapper;
    private final BusinessCustomerMapper businessCustomerMapper;
    private final RemoteDeptService remoteDeptService;
    private final RemoteDictService remoteDictService;
@@ -102,7 +112,7 @@
        R<List<SysDictItem>> r = remoteDictService.getDictByType("company_area");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
            return R.failed("地区字典分类获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
@@ -142,7 +152,7 @@
        R<List<SysDictItem>> r = remoteDictService.getDictByType("industry_sector");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
            return R.failed("行业字典分类获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
@@ -182,7 +192,7 @@
        R<List<SysDictItem>> r = remoteDictService.getDictByType("market_type");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
            return R.failed("市场类型字典分类获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
@@ -222,7 +232,7 @@
        R<List<SysDictItem>> r = remoteDictService.getDictByType("supply_attribute");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
            return R.failed("供应属性字典分类获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
@@ -303,7 +313,7 @@
        R<List<SysDictItem>> r = remoteDictService.getDictByType("sales_model");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
            return R.failed("销售模式字典分类获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
@@ -338,4 +348,355 @@
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R agingAnalysisByArea(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("company_area");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("地区字典分类获取异常");
        }
//        List<AgingCompanyVo> companys = contractPaymentScheduleMapper.selectAgingCompany(DataScope.of("comp_id"));
//        if (ArrayUtil.isEmpty(companys.toArray())){
//            return R.failed("暂无账龄");
//        }
        List<AgingAnalysisVo> result = new ArrayList<>();
        AgingQueryDTO queryDTO = new AgingQueryDTO();
        List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotal(null);
        items.stream().forEach(item->{
            AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
            agingAnalysisVo.setCompanyName(item.getLabel());
            queryDTO.setAreaId(item.getItemValue());
            List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotal(queryDTO);
            //补全数据
            if (ArrayUtil.isEmpty(companyAgingVo.toArray())){
                companyAgingVo = new ArrayList<>();
                AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                companyAgingVo.add(agingVo1);
                companyAgingVo.add(agingVo2);
                companyAgingVo.add(agingVo3);
                companyAgingVo.add(agingVo4);
                companyAgingVo.add(agingVo5);
                companyAgingVo.add(agingVo6);
            }else {
                List<String> overdueRanges = companyAgingVo.stream().map(AgingVo::getOverdueRange).collect(Collectors.toList());
                if (!ArrayUtil.contains(overdueRanges.toArray(),"0-30天")){
                    AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo1);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"31-60天")){
                    AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo2);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"61-90天")){
                    AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo3);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"91-180天")){
                    AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo4);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"181-365天")){
                    AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo5);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"1年以上")){
                    AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo6);
                }
            }
            agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
            List<AgingVo> finalCompanyAgingVo = companyAgingVo;
            agingAnalysisVo.setPercent(IntStream.range(0, agingVoList.size())
                    .mapToObj(i -> {
                        BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                        BigDecimal total = agingVoList.get(i).getTotalAmount();
                        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                            return null;
                        }
                        return part.divide(total, 4, RoundingMode.HALF_UP)
                                .multiply(new BigDecimal("100"))
                                .setScale(2, RoundingMode.HALF_UP);
                    })
                    .collect(Collectors.toList()));
            result.add(agingAnalysisVo);
        });
        //合计
        AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
        agingAnalysisVo.setCompanyName("合计");
        agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
        List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
                .mapToObj(i -> {
                    if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                        return null;
                    }else {
                        return new BigDecimal("100");
                    }
                })
                .collect(Collectors.toList());
        agingAnalysisVo.setPercent(percent);
        result.add(agingAnalysisVo);
        return R.ok(result);
    }
    @Override
    public R agingAnalysisByIndustry(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("industry_sector");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("地区字典分类获取异常");
        }
        List<AgingAnalysisVo> result = new ArrayList<>();
        AgingQueryDTO queryDTO = new AgingQueryDTO();
        List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotal(null);
        items.stream().forEach(item->{
            AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
            agingAnalysisVo.setCompanyName(item.getLabel());
            queryDTO.setIndustryId(item.getItemValue());
            List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotal(queryDTO);
            //补全数据
            if (ArrayUtil.isEmpty(companyAgingVo.toArray())){
                companyAgingVo = new ArrayList<>();
                AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                companyAgingVo.add(agingVo1);
                companyAgingVo.add(agingVo2);
                companyAgingVo.add(agingVo3);
                companyAgingVo.add(agingVo4);
                companyAgingVo.add(agingVo5);
                companyAgingVo.add(agingVo6);
            }else {
                List<String> overdueRanges = companyAgingVo.stream().map(AgingVo::getOverdueRange).collect(Collectors.toList());
                if (!ArrayUtil.contains(overdueRanges.toArray(),"0-30天")){
                    AgingVo agingVo1 = new AgingVo("0-30天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo1);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"31-60天")){
                    AgingVo agingVo2 = new AgingVo("31-60天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo2);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"61-90天")){
                    AgingVo agingVo3 = new AgingVo("61-90天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo3);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"91-180天")){
                    AgingVo agingVo4 = new AgingVo("91-180天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo4);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"181-365天")){
                    AgingVo agingVo5 = new AgingVo("181-365天",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo5);
                }
                if (!ArrayUtil.contains(overdueRanges.toArray(),"1年以上")){
                    AgingVo agingVo6 = new AgingVo("1年以上",new BigDecimal("0"),null);
                    companyAgingVo.add(agingVo6);
                }
            }
            agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
            List<AgingVo> finalCompanyAgingVo = companyAgingVo;
            agingAnalysisVo.setPercent(IntStream.range(0, agingVoList.size())
                    .mapToObj(i -> {
                        BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                        BigDecimal total = agingVoList.get(i).getTotalAmount();
                        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                            return null;
                        }
                        return part.divide(total, 4, RoundingMode.HALF_UP)
                                .multiply(new BigDecimal("100"))
                                .setScale(2, RoundingMode.HALF_UP);
                    })
                    .collect(Collectors.toList()));
            result.add(agingAnalysisVo);
        });
        //合计
        AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
        agingAnalysisVo.setCompanyName("合计");
        agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
        List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
                .mapToObj(i -> {
                    if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                        return null;
                    }else {
                        return new BigDecimal("100");
                    }
                })
                .collect(Collectors.toList());
        agingAnalysisVo.setPercent(percent);
        result.add(agingAnalysisVo);
        return R.ok(result);
    }
    @Override
    public R agingAnalysis(AnalysisCommonDTO commonDTO) {
        if (commonDTO.getAgingType().equals("2")) {
            AgingQueryDTO queryDTO = new AgingQueryDTO();
            List<AgingCompanyVo> companys = contractPaymentScheduleMapper.selectAgingCompanyShip(DataScope.of("comp_id"));
            if (ArrayUtil.isEmpty(companys.toArray())) {
                return R.failed("暂无账龄");
            }
            //合计数据
            List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotalShip(queryDTO);
            agingVoList = completeData(agingVoList);
            List<AgingVo> finalAgingVoList = agingVoList;
            List<AgingAnalysisVo> result = new ArrayList<>();
            companys.stream().forEach(company -> {
                BusinessCustomer businessCustomer = businessCustomerMapper.selectById(company.getCompanyId());
                AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
                agingAnalysisVo.setCompanyName(businessCustomer.getCompanyName());
                queryDTO.setCompanyId(company.getCompanyId());
                List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotalShip(queryDTO);
                //补全数据
                companyAgingVo = completeData(companyAgingVo);
                agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
                List<AgingVo> finalCompanyAgingVo = companyAgingVo;
                agingAnalysisVo.setPercent(IntStream.range(0, finalAgingVoList.size())
                        .mapToObj(i -> {
                            BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                            BigDecimal total = finalAgingVoList.get(i).getTotalAmount();
                            if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                                return null;
                            }
                            return part.divide(total, 4, RoundingMode.HALF_UP)
                                    .multiply(new BigDecimal("100"))
                                    .setScale(2, RoundingMode.HALF_UP);
                        })
                        .collect(Collectors.toList()));
                result.add(agingAnalysisVo);
            });
            //合计
            AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
            agingAnalysisVo.setCompanyName("合计");
            agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
            List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
                    .mapToObj(i -> {
                        if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                            return null;
                        } else {
                            return new BigDecimal("100");
                        }
                    })
                    .collect(Collectors.toList());
            agingAnalysisVo.setPercent(percent);
            result.add(agingAnalysisVo);
            return R.ok(result);
        }
        if (commonDTO.getAgingType().equals("3")) {
            AgingQueryDTO queryDTO = new AgingQueryDTO();
            List<AgingCompanyVo> companys = contractPaymentScheduleMapper.selectAgingCompanyInvoice(DataScope.of("comp_id"));
            if (ArrayUtil.isEmpty(companys.toArray())) {
                return R.failed("暂无账龄");
            }
            //合计数据
            List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotalInvoice(queryDTO);
            agingVoList = completeData(agingVoList);
            List<AgingVo> finalAgingVoList = agingVoList;
            List<AgingAnalysisVo> result = new ArrayList<>();
            companys.stream().forEach(company -> {
                BusinessCustomer businessCustomer = businessCustomerMapper.selectById(company.getCompanyId());
                AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
                agingAnalysisVo.setCompanyName(businessCustomer.getCompanyName());
                queryDTO.setCompanyId(company.getCompanyId());
                List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotalInvoice(queryDTO);
                //补全数据
                companyAgingVo = completeData(companyAgingVo);
                agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
                List<AgingVo> finalCompanyAgingVo = companyAgingVo;
                agingAnalysisVo.setPercent(IntStream.range(0, finalAgingVoList.size())
                        .mapToObj(i -> {
                            BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                            BigDecimal total = finalAgingVoList.get(i).getTotalAmount();
                            if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                                return null;
                            }
                            return part.divide(total, 4, RoundingMode.HALF_UP)
                                    .multiply(new BigDecimal("100"))
                                    .setScale(2, RoundingMode.HALF_UP);
                        })
                        .collect(Collectors.toList()));
                result.add(agingAnalysisVo);
            });
            //合计
            AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
            agingAnalysisVo.setCompanyName("合计");
            agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
            List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
                    .mapToObj(i -> {
                        if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                            return null;
                        } else {
                            return new BigDecimal("100");
                        }
                    })
                    .collect(Collectors.toList());
            agingAnalysisVo.setPercent(percent);
            result.add(agingAnalysisVo);
            return R.ok(result);
        }
        return R.ok();
    }
    private List<AgingVo> completeData(List<AgingVo> companyAgingVo) {
        if (ArrayUtil.isEmpty(companyAgingVo.toArray())) {
            companyAgingVo = new ArrayList<>();
            AgingVo agingVo1 = new AgingVo("0-30天", new BigDecimal("0"), null);
            AgingVo agingVo2 = new AgingVo("31-60天", new BigDecimal("0"), null);
            AgingVo agingVo3 = new AgingVo("61-90天", new BigDecimal("0"), null);
            AgingVo agingVo4 = new AgingVo("91-180天", new BigDecimal("0"), null);
            AgingVo agingVo5 = new AgingVo("181-365天", new BigDecimal("0"), null);
            AgingVo agingVo6 = new AgingVo("1年以上", new BigDecimal("0"), null);
            companyAgingVo.add(agingVo1);
            companyAgingVo.add(agingVo2);
            companyAgingVo.add(agingVo3);
            companyAgingVo.add(agingVo4);
            companyAgingVo.add(agingVo5);
            companyAgingVo.add(agingVo6);
        } else {
            List<String> overdueRanges = companyAgingVo.stream().map(AgingVo::getOverdueRange).collect(Collectors.toList());
            if (!ArrayUtil.contains(overdueRanges.toArray(), "0-30天")) {
                AgingVo agingVo1 = new AgingVo("0-30天", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo1);
            }
            if (!ArrayUtil.contains(overdueRanges.toArray(), "31-60天")) {
                AgingVo agingVo2 = new AgingVo("31-60天", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo2);
            }
            if (!ArrayUtil.contains(overdueRanges.toArray(), "61-90天")) {
                AgingVo agingVo3 = new AgingVo("61-90天", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo3);
            }
            if (!ArrayUtil.contains(overdueRanges.toArray(), "91-180天")) {
                AgingVo agingVo4 = new AgingVo("91-180天", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo4);
            }
            if (!ArrayUtil.contains(overdueRanges.toArray(), "181-365天")) {
                AgingVo agingVo5 = new AgingVo("181-365天", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo5);
            }
            if (!ArrayUtil.contains(overdueRanges.toArray(), "1年以上")) {
                AgingVo agingVo6 = new AgingVo("1年以上", new BigDecimal("0"), null);
                companyAgingVo.add(agingVo6);
            }
        }
        return companyAgingVo;
    }
}
platformx-business-finance-biz/src/main/resources/mapper/ContractPaymentScheduleMapper.xml
@@ -16,7 +16,7 @@
        <result property="paymentRatio" column="payment_ratio"/>
        <result property="paymentStatus" column="payment_status"/>
        <result property="plannedAmount" column="planned_amount"/>
        <result property="plannedPaymentDate" column="planned_payment_date"/>
<!--        <result property="plannedPaymentDate" column="planned_payment_date"/>-->
        <result property="remark" column="remark"/>
        <result property="stageName" column="stage_name"/>
        <result property="stageOrder" column="stage_order"/>
@@ -28,4 +28,203 @@
        <result property="updateTime" column="update_time"/>
        <result property="delFlag" column="del_flag"/>
  </resultMap>
    <select id="selectAgingCompany" resultType="com.by4cloud.platformx.business.vo.AgingCompanyVo">
        SELECT
        c.party_a_id companyId,
        cps.comp_id
        FROM
        contract_payment_schedule cps,
        contract c
        WHERE
        cps.contract_id = c.id
        AND cps.del_flag = '0'
        AND c.del_flag = '0'
        AND cps.effective_end_date is not null
        AND cps.effective_end_date &lt; current_date
        AND DATEDIFF(current_date, cps.effective_end_date)>0
        AND cps.payment_status &lt;&gt; '2'
        AND cps.payment_status &lt;&gt; 3
        GROUP BY
        c.party_a_id,
        cps.comp_id
    </select>
    <select id="selectAgingTotal" resultType="com.by4cloud.platformx.business.vo.AgingVo">
        SELECT
        ranges.overdue_range,
        COALESCE(SUM(
        CASE
        WHEN cps.payment_status = '0' THEN
        cps.planned_amount
        WHEN cps.payment_status = '1' THEN
        cps.planned_amount - cps.actual_amount ELSE 0
        END
        ), 0) AS total_amount
        FROM
        (
        SELECT '0-30天' AS overdue_range, 0 AS min_days, 30 AS max_days UNION ALL
        SELECT '31-60天', 31, 60 UNION ALL
        SELECT '61-90天', 61, 90 UNION ALL
        SELECT '91-180天', 91, 180 UNION ALL
        SELECT '181-365天', 181, 365 UNION ALL
        SELECT '1年以上', 366, 999999
        ) AS ranges
        LEFT JOIN
        contract_payment_schedule cps ON
        cps.del_flag = '0'
        AND cps.payment_status NOT IN ('2', '3')
        AND cps.effective_end_date &lt; current_date
        AND DATEDIFF(current_date, cps.effective_end_date) BETWEEN ranges.min_days AND ranges.max_days
        LEFT JOIN
        contract c ON cps.contract_id = c.id
        LEFT JOIN
        business_customer bc ON c.party_a_id = bc.id
         where
         c.del_flag = '0'
        <if test="queryDTO.companyId !=null">
            and c.party_a_id = #{queryDTO.companyId}
        </if>
        <if test="queryDTO.areaId !=null">
            and bc.area_id = #{queryDTO.areaId}
        </if>
        <if test="queryDTO.industryId !=null">
            and bc.industry_id = #{queryDTO.industryId}
        </if>
        GROUP BY
        ranges.overdue_range,
        ranges.min_days
        ORDER BY
        ranges.min_days;
    </select>
    <select id="selectAgingCompanyShip" resultType="com.by4cloud.platformx.business.vo.AgingCompanyVo">
        SELECT
            c.party_a_id companyId,
            c.comp_id
        FROM
            contract c
        WHERE
            c.del_flag = '0'
          AND c.amount > c.paid_amount
          AND EXISTS ( SELECT 1 FROM contract_out_bound cob WHERE cob.del_flag = '0' AND cob.contract_id = c.id )
        GROUP BY
            c.party_a_id,
            c.comp_id;
    </select>
    <select id="selectAgingCompanyInvoice" resultType="com.by4cloud.platformx.business.vo.AgingCompanyVo">
        SELECT
            c.party_a_id companyId,
            c.comp_id
        FROM
            contract c
        WHERE
            c.del_flag = '0'
          AND c.amount > c.paid_amount
          AND EXISTS ( SELECT 1 FROM contract_invoice ci WHERE ci.del_flag = '0' AND ci.contract_id = c.id )
        GROUP BY
            c.party_a_id,
            c.comp_id;
    </select>
    <select id="selectAgingTotalShip" resultType="com.by4cloud.platformx.business.vo.AgingVo">
        SELECT
            ranges.overdue_range,
            COALESCE (
                    sum(amount-paid_amount),
                    0
                ) AS total_amount
        FROM
            (
                SELECT
                    '0-30天' AS overdue_range,
                    0 AS min_days,
                    30 AS max_days UNION ALL
                SELECT
                    '31-60天',
                    31,
                    60 UNION ALL
                SELECT
                    '61-90天',
                    61,
                    90 UNION ALL
                SELECT
                    '91-180天',
                    91,
                    180 UNION ALL
                SELECT
                    '181-365天',
                    181,
                    365 UNION ALL
                SELECT
                    '1年以上',
                    366,
                    999999
            ) ranges
                LEFT JOIN contract c ON c.del_flag = '0'
                AND DATEDIFF(
                            CURRENT_DATE,
                            ( SELECT max( out_bound_time ) FROM contract_out_bound cob WHERE cob.del_flag = '0' AND cob.contract_id = c.id ORDER BY out_bound_time ASC )) BETWEEN ranges.min_days
                AND ranges.max_days
        WHERE
            c.del_flag = '0'
          AND c.amount > c.paid_amount
        <if test="queryDTO.companyId !=null">
            and c.party_a_id = #{queryDTO.companyId}
        </if>
          AND EXISTS ( SELECT 1 FROM contract_out_bound cob WHERE cob.del_flag = '0' AND cob.contract_id = c.id )
        GROUP BY
            ranges.overdue_range,
            ranges.min_days
        ORDER BY
            ranges.min_days;
    </select>
    <select id="selectAgingTotalInvoice" resultType="com.by4cloud.platformx.business.vo.AgingVo">
        SELECT
            ranges.overdue_range,
            COALESCE (
                    sum(amount-paid_amount),
                    0
                ) AS total_amount
        FROM
            (
                SELECT
                    '0-30天' AS overdue_range,
                    0 AS min_days,
                    30 AS max_days UNION ALL
                SELECT
                    '31-60天',
                    31,
                    60 UNION ALL
                SELECT
                    '61-90天',
                    61,
                    90 UNION ALL
                SELECT
                    '91-180天',
                    91,
                    180 UNION ALL
                SELECT
                    '181-365天',
                    181,
                    365 UNION ALL
                SELECT
                    '1年以上',
                    366,
                    999999
            ) ranges
                LEFT JOIN contract c ON c.del_flag = '0'
                AND DATEDIFF(
                                                        CURRENT_DATE,
                                                        ( SELECT max( out_bound_time ) FROM contract_out_bound cob WHERE cob.del_flag = '0' AND cob.contract_id = c.id ORDER BY out_bound_time ASC )) BETWEEN ranges.min_days
                                            AND ranges.max_days
        WHERE
            c.del_flag = '0'
          AND c.amount > c.paid_amount
        <if test="queryDTO.companyId !=null">
            and c.party_a_id = #{queryDTO.companyId}
        </if>
          AND EXISTS ( SELECT 1 FROM contract_invoice ci WHERE ci.del_flag = '0' AND ci.contract_id = c.id)
        GROUP BY
            ranges.overdue_range,
            ranges.min_days
        ORDER BY
            ranges.min_days;
    </select>
</mapper>