diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/InvoiceApplicationController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/InvoiceApplicationController.java index 35ddac0..4a817b4 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/InvoiceApplicationController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/InvoiceApplicationController.java @@ -80,8 +80,11 @@ public class InvoiceApplicationController extends BladeController { @GetMapping("/settlement-candidates") @ApiOperationSupport(order = 3) @Operation(summary = "可开票正式结算单") - public R>> settlementCandidates(@RequestParam(required = false) String keyword) { - return R.data(invoiceApplicationService.settlementCandidates(keyword)); + public R>> settlementCandidates(Query query, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) String contractCategory) { + return R.data(invoiceApplicationService.settlementCandidates( + Condition.getPage(query), keyword, contractCategory)); } @GetMapping("/settlement-details") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IInvoiceApplicationService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IInvoiceApplicationService.java index fe65e70..9434bfc 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IInvoiceApplicationService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IInvoiceApplicationService.java @@ -44,7 +44,7 @@ import java.util.Map; public interface IInvoiceApplicationService extends BaseService { IPage selectPage(IPage page, InvoiceApplicationVO query); InvoiceApplicationVO detail(Long id); - List> settlementCandidates(String keyword); + IPage> settlementCandidates(IPage page, String keyword, String contractCategory); List settlementDetails(String settlementIds); Map receiverInformation(String settlementIds); Long saveDraft(InvoiceApplicationSaveRequest request); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceApplicationServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceApplicationServiceImpl.java index eff9419..431a5e1 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceApplicationServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InvoiceApplicationServiceImpl.java @@ -28,6 +28,7 @@ package org.springblade.transport.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; @@ -37,6 +38,7 @@ import org.springblade.core.tool.utils.Func; import org.springblade.transport.mapper.CustomerArchiveMapper; import org.springblade.transport.mapper.CustomerContactMapper; import org.springblade.transport.mapper.CustomerInvoiceInfoMapper; +import org.springblade.transport.mapper.ContractManageMapper; import org.springblade.transport.mapper.FormalSettlementDetailMapper; import org.springblade.transport.mapper.FormalSettlementMapper; import org.springblade.transport.mapper.InvoiceApplicationDetailMapper; @@ -50,6 +52,7 @@ import org.springblade.transport.pojo.dto.InvoiceApplicationStatusRequest; import org.springblade.transport.pojo.entity.CustomerArchive; import org.springblade.transport.pojo.entity.CustomerContact; import org.springblade.transport.pojo.entity.CustomerInvoiceInfo; +import org.springblade.transport.pojo.entity.ContractManage; import org.springblade.transport.pojo.entity.FormalSettlement; import org.springblade.transport.pojo.entity.FormalSettlementDetail; import org.springblade.transport.pojo.entity.InvoiceApplication; @@ -102,6 +105,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl> settlementCandidates(String keyword) { + public IPage> settlementCandidates(IPage page, String keyword, + String contractCategory) { + List contractIds = Func.isEmpty(contractCategory) ? List.of() + : contractManageMapper.selectList(Wrappers.lambdaQuery() + .select(ContractManage::getId) + .eq(ContractManage::getContractCategory, contractCategory) + .eq(ContractManage::getIsDeleted, 0)) + .stream().map(ContractManage::getId).toList(); + if (Func.isNotEmpty(contractCategory) && contractIds.isEmpty()) { + return new Page<>(page.getCurrent(), page.getSize(), 0); + } List settlements = formalSettlementMapper.selectList(Wrappers.lambdaQuery() .eq(FormalSettlement::getSettlementType, "payable") .eq(FormalSettlement::getApprovalStatus, APPROVED) .eq(FormalSettlement::getStatus, 1) + .in(Func.isNotEmpty(contractCategory), FormalSettlement::getContractId, contractIds) .and(Func.isNotEmpty(keyword), wrapper -> wrapper.like(FormalSettlement::getFormalSettlementNo, keyword) .or().like(FormalSettlement::getProjectName, keyword) .or().like(FormalSettlement::getContractName, keyword)) - .orderByDesc(FormalSettlement::getCreateTime).last("limit 200")); - return settlements.stream().map(settlement -> { - BigDecimal available = availableAmount(settlement, null); - Map row = new LinkedHashMap<>(); - row.put("id", settlement.getId()); - row.put("formalSettlementNo", settlement.getFormalSettlementNo()); - row.put("projectId", settlement.getProjectId()); - row.put("projectName", settlement.getProjectName()); - row.put("deptId", settlement.getDeptId()); - row.put("deptName", settlement.getDeptName()); - row.put("contractId", settlement.getContractId()); - row.put("contractNo", settlement.getContractNo()); - row.put("contractName", settlement.getContractName()); - row.put("issuerName", settlement.getPayeeName()); - row.put("receiverName", settlement.getPayerName()); - row.put("settlementAmount", money(settlement.getSettlementAmount())); - row.put("availableInvoiceAmount", available); - return row; - }).filter(row -> ((BigDecimal) row.get("availableInvoiceAmount")).compareTo(BigDecimal.ZERO) > 0).toList(); + .orderByDesc(FormalSettlement::getCreateTime)); + Map availableAmounts = candidateAvailableAmounts(settlements); + List> candidates = settlements.stream() + .map(settlement -> settlementCandidateMap(settlement, + availableAmounts.getOrDefault(settlement.getId(), BigDecimal.ZERO))) + .filter(row -> ((BigDecimal) row.get("availableInvoiceAmount")).compareTo(BigDecimal.ZERO) > 0) + .toList(); + long current = Math.max(page.getCurrent(), 1); + long size = Math.max(page.getSize(), 1); + long offset = Math.min((current - 1) * size, candidates.size()); + long end = Math.min(offset + size, candidates.size()); + Page> result = new Page<>(current, size, candidates.size()); + result.setRecords(candidates.subList((int) offset, (int) end)); + return result; + } + + private Map candidateAvailableAmounts(List settlements) { + if (settlements.isEmpty()) return Map.of(); + List settlementIds = settlements.stream().map(FormalSettlement::getId).toList(); + List relations = settlementRelationMapper.selectList( + Wrappers.lambdaQuery() + .in(InvoiceApplicationSettlement::getFormalSettlementId, settlementIds)); + if (relations.isEmpty()) { + return settlements.stream().collect(Collectors.toMap(FormalSettlement::getId, + settlement -> money(settlement.getSettlementAmount()), (first, duplicate) -> first, + LinkedHashMap::new)); + } + Map applications = listByIds(relations.stream() + .map(InvoiceApplicationSettlement::getInvoiceApplicationId).distinct().toList()).stream() + .collect(Collectors.toMap(InvoiceApplication::getId, Function.identity())); + Map allocatedAmounts = relations.stream() + .filter(relation -> { + InvoiceApplication application = applications.get(relation.getInvoiceApplicationId()); + return application != null && !VOIDED.equals(application.getApprovalStatus()) + && !Objects.equals(application.getIsDeleted(), 1); + }) + .collect(Collectors.groupingBy(InvoiceApplicationSettlement::getFormalSettlementId, + Collectors.reducing(BigDecimal.ZERO, + relation -> money(relation.getAllocatedInvoiceAmount()), BigDecimal::add))); + return settlements.stream().collect(Collectors.toMap(FormalSettlement::getId, + settlement -> money(settlement.getSettlementAmount()) + .subtract(allocatedAmounts.getOrDefault(settlement.getId(), BigDecimal.ZERO)) + .max(BigDecimal.ZERO), + (first, duplicate) -> first, LinkedHashMap::new)); + } + + private Map settlementCandidateMap(FormalSettlement settlement, BigDecimal available) { + Map row = new LinkedHashMap<>(); + row.put("id", settlement.getId()); + row.put("formalSettlementNo", settlement.getFormalSettlementNo()); + row.put("projectId", settlement.getProjectId()); + row.put("projectName", settlement.getProjectName()); + row.put("deptId", settlement.getDeptId()); + row.put("deptName", settlement.getDeptName()); + row.put("contractId", settlement.getContractId()); + row.put("contractNo", settlement.getContractNo()); + row.put("contractName", settlement.getContractName()); + row.put("issuerName", settlement.getPayeeName()); + row.put("receiverName", settlement.getPayerName()); + row.put("settlementAmount", money(settlement.getSettlementAmount())); + row.put("availableInvoiceAmount", available); + return row; } @Override