|
@@ -1,18 +1,25 @@
|
|
|
package com.jzg.organization.utils;
|
|
package com.jzg.organization.utils;
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
-import java.time.Instant;
|
|
|
|
|
-import java.time.LocalDateTime;
|
|
|
|
|
-import java.time.ZoneId;
|
|
|
|
|
-import java.util.*;
|
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
|
-
|
|
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.jzg.commons.entity.finance.dto.InsPlyIncomeDto;
|
|
|
|
|
+import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoice;
|
|
|
import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceLink;
|
|
import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceLink;
|
|
|
import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceSettlement;
|
|
import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceSettlement;
|
|
|
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
|
|
+import com.jzg.commons.entity.finance.vo.SettlementReportQueryVo;
|
|
|
import com.jzg.organization.mapper.InsPlyIncomeInvoiceLinkMapper;
|
|
import com.jzg.organization.mapper.InsPlyIncomeInvoiceLinkMapper;
|
|
|
|
|
+import com.jzg.organization.mapper.InsPlyIncomeInvoiceMapper;
|
|
|
import com.jzg.organization.mapper.InsPlyIncomeInvoiceSettlementMapper;
|
|
import com.jzg.organization.mapper.InsPlyIncomeInvoiceSettlementMapper;
|
|
|
|
|
+import com.jzg.organization.mapper.ReceivableMapper;
|
|
|
|
|
+
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.function.Function;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
public class IncomeInvoiceLinkUtil {
|
|
public class IncomeInvoiceLinkUtil {
|
|
|
|
|
|
|
@@ -20,13 +27,13 @@ public class IncomeInvoiceLinkUtil {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 根据incomeId集合 查询应收开票结算
|
|
|
|
|
|
|
+ * 根据incomeId集合 查询应收开票结算的数据
|
|
|
* @param incomeIdList 应收主表id集合
|
|
* @param incomeIdList 应收主表id集合
|
|
|
* @param linkMapper link表mapper
|
|
* @param linkMapper link表mapper
|
|
|
* @param settlementMapper settlement表mapper
|
|
* @param settlementMapper settlement表mapper
|
|
|
* @return key: invoiceId, value: settlement结算记录,旧值会被新值替换,按创建时间倒序
|
|
* @return key: invoiceId, value: settlement结算记录,旧值会被新值替换,按创建时间倒序
|
|
|
*/
|
|
*/
|
|
|
- public static Map<String, InsPlyIncomeInvoiceSettlement> querySettlementByIncomeList(List<Long> incomeIdList,
|
|
|
|
|
|
|
+ public static Map<String, InsPlyIncomeInvoiceSettlement> querySettlementByIncomeList(List<String> incomeIdList,
|
|
|
InsPlyIncomeInvoiceLinkMapper linkMapper,
|
|
InsPlyIncomeInvoiceLinkMapper linkMapper,
|
|
|
InsPlyIncomeInvoiceSettlementMapper settlementMapper) {
|
|
InsPlyIncomeInvoiceSettlementMapper settlementMapper) {
|
|
|
if (CollUtil.isEmpty(incomeIdList)) {
|
|
if (CollUtil.isEmpty(incomeIdList)) {
|
|
@@ -57,19 +64,44 @@ public class IncomeInvoiceLinkUtil {
|
|
|
.collect(Collectors.toMap(InsPlyIncomeInvoiceSettlement::getInvoiceId, s -> s, (exist, newVal) -> newVal));
|
|
.collect(Collectors.toMap(InsPlyIncomeInvoiceSettlement::getInvoiceId, s -> s, (exist, newVal) -> newVal));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ return settlementMap;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
|
- return settlementMap;
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据应收id集合,获取 key:incomeId, value:对应多个invoiceId集合 的Map
|
|
|
|
|
+ * @param incomeIdList 应收主表id集合
|
|
|
|
|
+ * @param linkMapper link中间表mapper
|
|
|
|
|
+ * @return key:incomeId,value:该应收关联的发票id集合,无数据返回空Map,内部list不会为null
|
|
|
|
|
+ */
|
|
|
|
|
+ public static Map<String, List<String>> queryIncomeToInvoiceIdMap(List<String> incomeIdList,
|
|
|
|
|
+ InsPlyIncomeInvoiceLinkMapper linkMapper) {
|
|
|
|
|
+ if (CollUtil.isEmpty(incomeIdList)) {
|
|
|
|
|
+ return MapUtil.empty();
|
|
|
|
|
+ }
|
|
|
|
|
+ List<InsPlyIncomeInvoiceLink> invoiceLinkList = getInvoiceLinkList(incomeIdList, linkMapper);
|
|
|
|
|
+ if (CollUtil.isEmpty(invoiceLinkList)) {
|
|
|
|
|
+ return MapUtil.empty();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 按incomeId分组,提取每个下的invoiceId,过滤null并去重
|
|
|
|
|
+ return invoiceLinkList.stream()
|
|
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
|
|
+ InsPlyIncomeInvoiceLink::getIncomeId,
|
|
|
|
|
+ Collectors.mapping(InsPlyIncomeInvoiceLink::getInvoiceId,
|
|
|
|
|
+ Collectors.filtering(Objects::nonNull,
|
|
|
|
|
+ Collectors.toList()))
|
|
|
|
|
+ ));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 根据incomeId获取invoiceLink的Map分组
|
|
* 根据incomeId获取invoiceLink的Map分组
|
|
|
- * @param incomeIdList
|
|
|
|
|
- * @param linkMapper
|
|
|
|
|
- * @return
|
|
|
|
|
|
|
+ * @param incomeIdList incomeId的集合
|
|
|
|
|
+ * @param linkMapper ins_ply_income_invoice_link中间表的数据
|
|
|
|
|
+ * @return 按incomeId分组,一个income可能多条link
|
|
|
*/
|
|
*/
|
|
|
- public static Map<String, List<InsPlyIncomeInvoiceLink>> queryInvoiceLinkByIncomeId(List<Long> incomeIdList,
|
|
|
|
|
|
|
+ public static Map<String, List<InsPlyIncomeInvoiceLink>> queryInvoiceLinkByIncomeId(List<String> incomeIdList,
|
|
|
InsPlyIncomeInvoiceLinkMapper linkMapper) {
|
|
InsPlyIncomeInvoiceLinkMapper linkMapper) {
|
|
|
|
|
|
|
|
List<InsPlyIncomeInvoiceLink> invoiceLinkList = getInvoiceLinkList(incomeIdList, linkMapper);
|
|
List<InsPlyIncomeInvoiceLink> invoiceLinkList = getInvoiceLinkList(incomeIdList, linkMapper);
|
|
@@ -84,12 +116,200 @@ public class IncomeInvoiceLinkUtil {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
- // 单纯获取InsPlyIncomeInvoiceLink的列表
|
|
|
|
|
- public static List<InsPlyIncomeInvoiceLink> getInvoiceLinkList(List<Long> incomeIdList, InsPlyIncomeInvoiceLinkMapper linkMapper) {
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 单纯获取InsPlyIncomeInvoiceLink的列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<InsPlyIncomeInvoiceLink> getInvoiceLinkList(List<String> incomeIdList, InsPlyIncomeInvoiceLinkMapper linkMapper) {
|
|
|
// 1、查询link关联表
|
|
// 1、查询link关联表
|
|
|
LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
|
|
|
linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIdList);
|
|
linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIdList);
|
|
|
linkWrapper.eq(InsPlyIncomeInvoiceLink::getIsDelete, 0);
|
|
linkWrapper.eq(InsPlyIncomeInvoiceLink::getIsDelete, 0);
|
|
|
return linkMapper.selectList(linkWrapper);
|
|
return linkMapper.selectList(linkWrapper);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据发票状态、开票时间、结算时间过滤收入数据
|
|
|
|
|
+ * 优化:嵌套anyMatch改为HashMapID映射匹配,O(n²) -> O(n)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param incomeList 待过滤收入dto列表
|
|
|
|
|
+ * @param queryVo 查询条件
|
|
|
|
|
+ * @param incomeInvoiceLinkMapper 收入发票链路mapper
|
|
|
|
|
+ * @param incomeInvoiceMapper 发票mapper
|
|
|
|
|
+ * @param invoiceSettlementMapper 发票结算mapper
|
|
|
|
|
+ * @return 过滤之后收入数据
|
|
|
|
|
+ */
|
|
|
|
|
+ public static List<InsPlyIncomeDto> filterIncomeByInvoiceAndSettleCondition(
|
|
|
|
|
+ List<InsPlyIncomeDto> incomeList,
|
|
|
|
|
+ SettlementReportQueryVo queryVo,
|
|
|
|
|
+ InsPlyIncomeInvoiceLinkMapper incomeInvoiceLinkMapper,
|
|
|
|
|
+ InsPlyIncomeInvoiceMapper incomeInvoiceMapper,
|
|
|
|
|
+ InsPlyIncomeInvoiceSettlementMapper invoiceSettlementMapper
|
|
|
|
|
+ ) {
|
|
|
|
|
+
|
|
|
|
|
+ String status = queryVo.getStatus();
|
|
|
|
|
+ String invoiceStartTime = queryVo.getInvoiceStartTime();
|
|
|
|
|
+ String invoiceEndTime = queryVo.getInvoiceEndTime();
|
|
|
|
|
+ String settleStartTime = queryVo.getSettlementStartTime();
|
|
|
|
|
+ String settleEndTime = queryVo.getSettlementEndTime();
|
|
|
|
|
+
|
|
|
|
|
+ // 无筛选条件,直接原数据返回
|
|
|
|
|
+ boolean noFilterCond = StrUtil.isBlank(status)
|
|
|
|
|
+ && (StrUtil.isBlank(invoiceStartTime) || StrUtil.isBlank(invoiceEndTime))
|
|
|
|
|
+ && (StrUtil.isBlank(settleStartTime) || StrUtil.isBlank(settleEndTime));
|
|
|
|
|
+ if (noFilterCond || CollUtil.isEmpty(incomeList)) {
|
|
|
|
|
+ return incomeList;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询收入关联链路
|
|
|
|
|
+ List<String> incomeIds = incomeList.stream()
|
|
|
|
|
+ .map(InsPlyIncomeDto::getId)
|
|
|
|
|
+ .distinct()
|
|
|
|
|
+ .toList();
|
|
|
|
|
+
|
|
|
|
|
+ LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIds);
|
|
|
|
|
+ List<InsPlyIncomeInvoiceLink> linkList = incomeInvoiceLinkMapper.selectList(linkWrapper);
|
|
|
|
|
+ if (CollUtil.isEmpty(linkList)) {
|
|
|
|
|
+ return new ArrayList<>(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 链路ID映射
|
|
|
|
|
+ Map<String, InsPlyIncomeInvoiceLink> linkInvoiceIdMap = linkList.stream()
|
|
|
|
|
+ .collect(Collectors.toMap(InsPlyIncomeInvoiceLink::getInvoiceId,
|
|
|
|
|
+ Function.identity(),
|
|
|
|
|
+ (k1, k2) -> k1));
|
|
|
|
|
+ Set<String> linkInvoiceIds = linkInvoiceIdMap.keySet();
|
|
|
|
|
+
|
|
|
|
|
+ // 查询发票
|
|
|
|
|
+ LambdaQueryWrapper<InsPlyIncomeInvoice> invoiceWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ invoiceWrapper.in(InsPlyIncomeInvoice::getId, linkInvoiceIds);
|
|
|
|
|
+ if (StrUtil.isNotBlank(status)) {
|
|
|
|
|
+ invoiceWrapper.eq(InsPlyIncomeInvoice::getStatus, status);
|
|
|
|
|
+ }
|
|
|
|
|
+ boolean invoiceTimeCond = StrUtil.isNotBlank(invoiceStartTime) && StrUtil.isNotBlank(invoiceEndTime);
|
|
|
|
|
+ if (invoiceTimeCond) {
|
|
|
|
|
+ invoiceWrapper.between(InsPlyIncomeInvoice::getInvoiceTime,
|
|
|
|
|
+ toStartDateTime(invoiceStartTime),
|
|
|
|
|
+ toEndDateTime(invoiceEndTime));
|
|
|
|
|
+ }
|
|
|
|
|
+ invoiceWrapper.eq(InsPlyIncomeInvoice::getInvoiceType, queryVo.getInvoiceType());
|
|
|
|
|
+ List<InsPlyIncomeInvoice> invoiceList = incomeInvoiceMapper.selectList(invoiceWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ if ((StrUtil.isNotBlank(status) || invoiceTimeCond) && CollUtil.isEmpty(invoiceList)) {
|
|
|
|
|
+ return new ArrayList<>(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 结算时间过滤
|
|
|
|
|
+ boolean settleTimeCond = StrUtil.isNotBlank(settleStartTime) && StrUtil.isNotBlank(settleEndTime);
|
|
|
|
|
+ if (settleTimeCond) {
|
|
|
|
|
+ Set<String> invoiceIdSet = invoiceList.stream()
|
|
|
|
|
+ .map(InsPlyIncomeInvoice::getId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+
|
|
|
|
|
+ LambdaQueryWrapper<InsPlyIncomeInvoiceSettlement> settleWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ settleWrapper.in(InsPlyIncomeInvoiceSettlement::getInvoiceId, invoiceIdSet);
|
|
|
|
|
+ settleWrapper.between(InsPlyIncomeInvoiceSettlement::getCreateTime,
|
|
|
|
|
+ toStartDateTime(settleStartTime),
|
|
|
|
|
+ toEndDateTime(settleEndTime));
|
|
|
|
|
+
|
|
|
|
|
+ List<InsPlyIncomeInvoiceSettlement> settleList = invoiceSettlementMapper.selectList(settleWrapper);
|
|
|
|
|
+ if (CollUtil.isEmpty(settleList)) {
|
|
|
|
|
+ return new ArrayList<>(0);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 保留存在结算记录的发票
|
|
|
|
|
+ Set<String> validSettleInvoiceIds = settleList.stream()
|
|
|
|
|
+ .map(InsPlyIncomeInvoiceSettlement::getInvoiceId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+
|
|
|
|
|
+ invoiceList = invoiceList.stream()
|
|
|
|
|
+ .filter(invoice -> validSettleInvoiceIds.contains(invoice.getId()))
|
|
|
|
|
+ .toList();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 合法发票ID集合
|
|
|
|
|
+ Set<String> validInvoiceIds = invoiceList.stream()
|
|
|
|
|
+ .map(InsPlyIncomeInvoice::getId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+
|
|
|
|
|
+ // 过滤合法链路
|
|
|
|
|
+ List<InsPlyIncomeInvoiceLink> validLinkList = linkList.stream()
|
|
|
|
|
+ .filter(link -> validInvoiceIds.contains(link.getInvoiceId()))
|
|
|
|
|
+ .toList();
|
|
|
|
|
+
|
|
|
|
|
+ Set<String> validIncomeIds = validLinkList.stream()
|
|
|
|
|
+ .map(InsPlyIncomeInvoiceLink::getIncomeId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+
|
|
|
|
|
+ // 最终过滤收入数据
|
|
|
|
|
+ return incomeList.stream()
|
|
|
|
|
+ .filter(income -> validIncomeIds.contains(income.getId()))
|
|
|
|
|
+ .toList();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 结算状态内存过滤(无接口,函数式getter)
|
|
|
|
|
+ * 0-已开票未结清 1-已结清 2-未开票
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param records 待过滤dto列表
|
|
|
|
|
+ * @param settlementStatus 结算状态:0/1/2
|
|
|
|
|
+ * @param getInvoiceIdFunc 获取invoiceIds的getter函数
|
|
|
|
|
+ * @param baseMapper mapper,用于统计未结清发票数量
|
|
|
|
|
+ * @param <T> 任意类型
|
|
|
|
|
+ * @return 过滤后集合
|
|
|
|
|
+ */
|
|
|
|
|
+ public static <T> List<T> filterBySettlementStatus(
|
|
|
|
|
+ List<T> records,
|
|
|
|
|
+ String settlementStatus,
|
|
|
|
|
+ Function<T, String> getInvoiceIdFunc,
|
|
|
|
|
+ ReceivableMapper baseMapper
|
|
|
|
|
+ ) {
|
|
|
|
|
+ if (CollUtil.isEmpty(records) || StrUtil.isBlank(settlementStatus)) {
|
|
|
|
|
+ return records;
|
|
|
|
|
+ }
|
|
|
|
|
+ return records.stream().filter(action -> {
|
|
|
|
|
+ String invoiceIds = getInvoiceIdFunc.apply(action);
|
|
|
|
|
+ if ("2".equals(settlementStatus)) {
|
|
|
|
|
+ return StrUtil.isEmpty(invoiceIds);
|
|
|
|
|
+ } else if ("0".equals(settlementStatus)) {
|
|
|
|
|
+ if (StrUtil.isEmpty(invoiceIds)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<String> invoiceIdList = Arrays.asList(invoiceIds.split(","));
|
|
|
|
|
+ return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) > 0;
|
|
|
|
|
+ } else if ("1".equals(settlementStatus)) {
|
|
|
|
|
+ if (StrUtil.isEmpty(invoiceIds)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<String> invoiceIdList = Arrays.asList(invoiceIds.split(","));
|
|
|
|
|
+ return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) == 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }).toList();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * yyyy-MM-dd 转当天起始 LocalDateTime
|
|
|
|
|
+ */
|
|
|
|
|
+ public static LocalDateTime toStartDateTime(String dateStr) {
|
|
|
|
|
+ if (StrUtil.isBlank(dateStr)){
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
|
|
|
|
|
+ return date.atStartOfDay();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * yyyy-MM-dd 转当天结束 LocalDateTime
|
|
|
|
|
+ */
|
|
|
|
|
+ public static LocalDateTime toEndDateTime(String dateStr) {
|
|
|
|
|
+ if (StrUtil.isBlank(dateStr)){
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
|
|
|
|
|
+ return date.atTime(23, 59, 59, 999999999);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|