From 1c607c0b2d9398daff957d5a983c82af49d22814 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Tue, 10 Mar 2026 16:10:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=B5=81=E6=B0=B4=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E6=9F=A5=E8=AF=A2=E6=9C=8D=E5=8A=A1=E5=B1=82=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ICcdiBankStatementService.java | 13 ++ .../impl/CcdiBankStatementServiceImpl.java | 112 ++++++++++++++++++ .../CcdiBankStatementServiceImplTest.java | 38 ++++++ 3 files changed, 163 insertions(+) create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java index e949cdd..5523571 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java @@ -1,6 +1,9 @@ package com.ruoyi.ccdi.project.service; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO; import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO; +import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO; /** * 流水明细查询Service接口 @@ -16,4 +19,14 @@ public interface ICcdiBankStatementService { * @return 筛选项 */ CcdiBankStatementFilterOptionsVO getFilterOptions(Long projectId); + + /** + * 分页查询流水明细 + * + * @param page 分页对象 + * @param queryDTO 查询条件 + * @return 分页结果 + */ + Page selectStatementPage(Page page, + CcdiBankStatementQueryDTO queryDTO); } diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java new file mode 100644 index 0000000..96558d7 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java @@ -0,0 +1,112 @@ +package com.ruoyi.ccdi.project.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO; +import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO; +import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO; +import com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper; +import com.ruoyi.ccdi.project.service.ICcdiBankStatementService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 流水明细查询Service实现 + * + * @author ruoyi + */ +@Service +public class CcdiBankStatementServiceImpl implements ICcdiBankStatementService { + + private static final Set ALLOWED_TAB_TYPES = Set.of("all", "in", "out"); + private static final Set ALLOWED_ORDER_DIRECTIONS = Set.of("asc", "desc"); + + @Resource + private CcdiBankStatementMapper bankStatementMapper; + + @Override + public CcdiBankStatementFilterOptionsVO getFilterOptions(Long projectId) { + CcdiBankStatementFilterOptionsVO options = bankStatementMapper.selectFilterOptions(projectId); + return options == null ? new CcdiBankStatementFilterOptionsVO() : options; + } + + @Override + public Page selectStatementPage(Page page, + CcdiBankStatementQueryDTO queryDTO) { + CcdiBankStatementQueryDTO normalizedQuery = queryDTO == null ? new CcdiBankStatementQueryDTO() : queryDTO; + normalizeQuery(normalizedQuery); + return bankStatementMapper.selectStatementPage(page, normalizedQuery); + } + + private void normalizeQuery(CcdiBankStatementQueryDTO queryDTO) { + queryDTO.setTransactionStartTime(normalizeText(queryDTO.getTransactionStartTime())); + queryDTO.setTransactionEndTime(normalizeText(queryDTO.getTransactionEndTime())); + queryDTO.setCounterpartyName(normalizeText(queryDTO.getCounterpartyName())); + queryDTO.setUserMemo(normalizeText(queryDTO.getUserMemo())); + queryDTO.setCounterpartyAccount(normalizeText(queryDTO.getCounterpartyAccount())); + queryDTO.setTransactionType(normalizeText(queryDTO.getTransactionType())); + queryDTO.setOurSubjects(normalizeList(queryDTO.getOurSubjects())); + queryDTO.setOurBanks(normalizeList(queryDTO.getOurBanks())); + queryDTO.setOurAccounts(normalizeList(queryDTO.getOurAccounts())); + queryDTO.setCounterpartyNameEmpty(Boolean.TRUE.equals(queryDTO.getCounterpartyNameEmpty())); + queryDTO.setUserMemoEmpty(Boolean.TRUE.equals(queryDTO.getUserMemoEmpty())); + queryDTO.setCounterpartyAccountEmpty(Boolean.TRUE.equals(queryDTO.getCounterpartyAccountEmpty())); + queryDTO.setTransactionTypeEmpty(Boolean.TRUE.equals(queryDTO.getTransactionTypeEmpty())); + queryDTO.setTabType(normalizeTabType(queryDTO.getTabType())); + queryDTO.setOrderBy(normalizeOrderBy(queryDTO.getOrderBy())); + queryDTO.setOrderDirection(normalizeOrderDirection(queryDTO.getOrderDirection())); + } + + private String normalizeTabType(String tabType) { + String normalized = normalizeLowerCase(tabType); + return normalized != null && ALLOWED_TAB_TYPES.contains(normalized) ? normalized : "all"; + } + + private String normalizeOrderBy(String orderBy) { + String normalized = normalizeText(orderBy); + if (normalized == null) { + return "trxDate"; + } + if ("amount".equalsIgnoreCase(normalized)) { + return "amount"; + } + if ("trxDate".equalsIgnoreCase(normalized)) { + return "trxDate"; + } + return "trxDate"; + } + + private String normalizeOrderDirection(String orderDirection) { + String normalized = normalizeLowerCase(orderDirection); + return normalized != null && ALLOWED_ORDER_DIRECTIONS.contains(normalized) ? normalized : "desc"; + } + + private String normalizeLowerCase(String value) { + String normalized = normalizeText(value); + return normalized == null ? null : normalized.toLowerCase(Locale.ROOT); + } + + private String normalizeText(String value) { + if (value == null) { + return null; + } + String trimmed = value.trim(); + return trimmed.isEmpty() ? null : trimmed; + } + + private List normalizeList(List values) { + if (values == null || values.isEmpty()) { + return null; + } + List normalized = values.stream() + .map(this::normalizeText) + .filter(item -> item != null) + .distinct() + .collect(Collectors.toList()); + return normalized.isEmpty() ? null : normalized; + } +} diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java index 0312252..adf9065 100644 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java @@ -15,9 +15,11 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -47,9 +49,45 @@ class CcdiBankStatementServiceImplTest { queryDTO.setProjectId(100L); queryDTO.setOrderBy("amount"); queryDTO.setOrderDirection("desc"); + doReturn(page).when(bankStatementMapper).selectStatementPage(eq(page), same(queryDTO)); service.selectStatementPage(page, queryDTO); verify(bankStatementMapper).selectStatementPage(eq(page), same(queryDTO)); } + + @Test + void normalizeQuery_shouldFallbackToSafeDefaults() { + Page page = new Page<>(1, 10); + CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO(); + queryDTO.setProjectId(100L); + queryDTO.setOrderBy("drop table"); + queryDTO.setOrderDirection("sideways"); + doReturn(page).when(bankStatementMapper).selectStatementPage(eq(page), same(queryDTO)); + + service.selectStatementPage(page, queryDTO); + + assertEquals("trxDate", queryDTO.getOrderBy()); + assertEquals("desc", queryDTO.getOrderDirection()); + assertEquals("all", queryDTO.getTabType()); + } + + @Test + void normalizeQuery_shouldTrimBlankStringsToNull() { + Page page = new Page<>(1, 10); + CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO(); + queryDTO.setProjectId(100L); + queryDTO.setCounterpartyName(" "); + queryDTO.setUserMemo(" "); + queryDTO.setCounterpartyAccount(" "); + queryDTO.setTransactionType(" "); + doReturn(page).when(bankStatementMapper).selectStatementPage(eq(page), same(queryDTO)); + + service.selectStatementPage(page, queryDTO); + + assertNull(queryDTO.getCounterpartyName()); + assertNull(queryDTO.getUserMemo()); + assertNull(queryDTO.getCounterpartyAccount()); + assertNull(queryDTO.getTransactionType()); + } }