新增流水明细对手方汇总查询
This commit is contained in:
@@ -3,6 +3,7 @@ package com.ruoyi.ccdi.project.controller;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.excel.CcdiBankStatementExcel;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
|
||||
@@ -55,6 +56,19 @@ public class CcdiBankStatementController extends BaseController {
|
||||
return getDataTable(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询对手方聚合列表
|
||||
*/
|
||||
@GetMapping("/counterparty/list")
|
||||
@Operation(summary = "分页查询对手方聚合列表")
|
||||
public TableDataInfo counterpartyList(CcdiBankStatementQueryDTO queryDTO) {
|
||||
projectAccessService.assertCanRead(queryDTO.getProjectId());
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Page<CcdiBankStatementCounterpartyVO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
|
||||
Page<CcdiBankStatementCounterpartyVO> result = bankStatementService.selectCounterpartyPage(page, queryDTO);
|
||||
return getDataTable(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询项目级筛选项
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.ruoyi.ccdi.project.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 流水对手方聚合VO
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
public class CcdiBankStatementCounterpartyVO {
|
||||
|
||||
/** 对方名称 */
|
||||
private String customerAccountName;
|
||||
|
||||
/** 对方名称是否为空 */
|
||||
private Boolean nameEmpty;
|
||||
|
||||
/** 关联账号数 */
|
||||
private Integer accountCount;
|
||||
|
||||
/** 流入合计 */
|
||||
private BigDecimal inAmount;
|
||||
|
||||
/** 流入笔数 */
|
||||
private Long inCount;
|
||||
|
||||
/** 流出合计 */
|
||||
private BigDecimal outAmount;
|
||||
|
||||
/** 流出笔数 */
|
||||
private Long outCount;
|
||||
|
||||
/** 总交易金额 */
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/** 总笔数 */
|
||||
private Long totalCount;
|
||||
|
||||
/** 最近交易时间 */
|
||||
private String latestTrxDate;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
|
||||
@@ -38,6 +39,9 @@ public interface CcdiBankStatementMapper extends BaseMapper<CcdiBankStatement> {
|
||||
Page<CcdiBankStatementListVO> selectStatementPage(Page<CcdiBankStatementListVO> page,
|
||||
@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
Page<CcdiBankStatementCounterpartyVO> selectCounterpartyPage(Page<CcdiBankStatementCounterpartyVO> page,
|
||||
@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
List<CcdiBankStatementListVO> selectStatementListForExport(@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
CcdiBankStatementDetailVO selectStatementDetailById(@Param("bankStatementId") Long bankStatementId);
|
||||
|
||||
@@ -3,6 +3,7 @@ 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.excel.CcdiBankStatementExcel;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
|
||||
@@ -34,6 +35,16 @@ public interface ICcdiBankStatementService {
|
||||
Page<CcdiBankStatementListVO> selectStatementPage(Page<CcdiBankStatementListVO> page,
|
||||
CcdiBankStatementQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 分页查询对手方聚合列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<CcdiBankStatementCounterpartyVO> selectCounterpartyPage(Page<CcdiBankStatementCounterpartyVO> page,
|
||||
CcdiBankStatementQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询导出列表
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ 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.excel.CcdiBankStatementExcel;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementHitTagVO;
|
||||
@@ -57,6 +58,16 @@ public class CcdiBankStatementServiceImpl implements ICcdiBankStatementService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CcdiBankStatementCounterpartyVO> selectCounterpartyPage(
|
||||
Page<CcdiBankStatementCounterpartyVO> page,
|
||||
CcdiBankStatementQueryDTO queryDTO
|
||||
) {
|
||||
CcdiBankStatementQueryDTO normalizedQuery = queryDTO == null ? new CcdiBankStatementQueryDTO() : queryDTO;
|
||||
normalizeQuery(normalizedQuery);
|
||||
return bankStatementMapper.selectCounterpartyPage(page, normalizedQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CcdiBankStatementExcel> selectStatementListForExport(CcdiBankStatementQueryDTO queryDTO) {
|
||||
CcdiBankStatementQueryDTO normalizedQuery = queryDTO == null ? new CcdiBankStatementQueryDTO() : queryDTO;
|
||||
@@ -153,6 +164,7 @@ public class CcdiBankStatementServiceImpl implements ICcdiBankStatementService {
|
||||
queryDTO.setCounterpartyAccount(normalizeText(queryDTO.getCounterpartyAccount()));
|
||||
queryDTO.setTransactionType(normalizeText(queryDTO.getTransactionType()));
|
||||
queryDTO.setOurSubjects(normalizeList(queryDTO.getOurSubjects()));
|
||||
queryDTO.setOurCertNos(normalizeList(queryDTO.getOurCertNos()));
|
||||
queryDTO.setOurBanks(normalizeList(queryDTO.getOurBanks()));
|
||||
queryDTO.setOurAccounts(normalizeList(queryDTO.getOurAccounts()));
|
||||
queryDTO.setCounterpartyNameEmpty(Boolean.TRUE.equals(queryDTO.getCounterpartyNameEmpty()));
|
||||
@@ -180,6 +192,21 @@ public class CcdiBankStatementServiceImpl implements ICcdiBankStatementService {
|
||||
if ("trxDate".equalsIgnoreCase(normalized)) {
|
||||
return "trxDate";
|
||||
}
|
||||
if ("latestTrxDate".equalsIgnoreCase(normalized)) {
|
||||
return "latestTrxDate";
|
||||
}
|
||||
if ("inAmount".equalsIgnoreCase(normalized)) {
|
||||
return "inAmount";
|
||||
}
|
||||
if ("outAmount".equalsIgnoreCase(normalized)) {
|
||||
return "outAmount";
|
||||
}
|
||||
if ("totalAmount".equalsIgnoreCase(normalized)) {
|
||||
return "totalAmount";
|
||||
}
|
||||
if ("totalCount".equalsIgnoreCase(normalized)) {
|
||||
return "totalCount";
|
||||
}
|
||||
return "trxDate";
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="displayAmount" column="displayAmount"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="CcdiBankStatementCounterpartyVOResultMap"
|
||||
type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO">
|
||||
<result property="customerAccountName" column="customerAccountName"/>
|
||||
<result property="nameEmpty" column="nameEmpty"/>
|
||||
<result property="accountCount" column="accountCount"/>
|
||||
<result property="inAmount" column="inAmount"/>
|
||||
<result property="inCount" column="inCount"/>
|
||||
<result property="outAmount" column="outAmount"/>
|
||||
<result property="outCount" column="outCount"/>
|
||||
<result property="totalAmount" column="totalAmount"/>
|
||||
<result property="totalCount" column="totalCount"/>
|
||||
<result property="latestTrxDate" column="latestTrxDate"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="CcdiBankStatementDetailVOResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO">
|
||||
<id property="bankStatementId" column="bankStatementId"/>
|
||||
<result property="projectId" column="projectId"/>
|
||||
@@ -284,6 +298,45 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<sql id="counterpartyNameExpr">
|
||||
TRIM(IFNULL(bs.CUSTOMER_ACCOUNT_NAME, ''))
|
||||
</sql>
|
||||
|
||||
<sql id="counterpartyOrderBy">
|
||||
<choose>
|
||||
<when test="query.orderBy == 'inAmount' and query.orderDirection == 'asc'">
|
||||
ORDER BY inAmount ASC, totalCount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'inAmount' and query.orderDirection == 'desc'">
|
||||
ORDER BY inAmount DESC, totalCount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'outAmount' and query.orderDirection == 'asc'">
|
||||
ORDER BY outAmount ASC, totalCount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'outAmount' and query.orderDirection == 'desc'">
|
||||
ORDER BY outAmount DESC, totalCount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'totalCount' and query.orderDirection == 'asc'">
|
||||
ORDER BY totalCount ASC, totalAmount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'totalCount' and query.orderDirection == 'desc'">
|
||||
ORDER BY totalCount DESC, totalAmount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'latestTrxDate' and query.orderDirection == 'asc'">
|
||||
ORDER BY latestTrxDate ASC, totalAmount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'latestTrxDate' and query.orderDirection == 'desc'">
|
||||
ORDER BY latestTrxDate DESC, totalAmount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<when test="query.orderBy == 'totalAmount' and query.orderDirection == 'asc'">
|
||||
ORDER BY totalAmount ASC, totalCount DESC, customerAccountName ASC
|
||||
</when>
|
||||
<otherwise>
|
||||
ORDER BY totalAmount DESC, totalCount DESC, customerAccountName ASC
|
||||
</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<select id="selectStatementPage" resultMap="CcdiBankStatementListVOResultMap">
|
||||
SELECT
|
||||
<include refid="statementListColumns"/>
|
||||
@@ -294,6 +347,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<include refid="statementOrderBy"/>
|
||||
</select>
|
||||
|
||||
<select id="selectCounterpartyPage" resultMap="CcdiBankStatementCounterpartyVOResultMap">
|
||||
SELECT
|
||||
grouped.customerAccountName,
|
||||
CASE WHEN grouped.customerAccountName = '' THEN 1 ELSE 0 END AS nameEmpty,
|
||||
grouped.accountCount,
|
||||
grouped.inAmount,
|
||||
grouped.inCount,
|
||||
grouped.outAmount,
|
||||
grouped.outCount,
|
||||
grouped.totalAmount,
|
||||
grouped.totalCount,
|
||||
grouped.latestTrxDate
|
||||
FROM (
|
||||
SELECT
|
||||
<include refid="counterpartyNameExpr"/> AS customerAccountName,
|
||||
COUNT(DISTINCT NULLIF(TRIM(IFNULL(bs.CUSTOMER_ACCOUNT_NO, '')), '')) AS accountCount,
|
||||
SUM(IFNULL(bs.AMOUNT_CR, 0)) AS inAmount,
|
||||
SUM(CASE WHEN IFNULL(bs.AMOUNT_CR, 0) > 0 THEN 1 ELSE 0 END) AS inCount,
|
||||
SUM(IFNULL(bs.AMOUNT_DR, 0)) AS outAmount,
|
||||
SUM(CASE WHEN IFNULL(bs.AMOUNT_DR, 0) > 0 THEN 1 ELSE 0 END) AS outCount,
|
||||
SUM(IFNULL(bs.AMOUNT_CR, 0) + IFNULL(bs.AMOUNT_DR, 0)) AS totalAmount,
|
||||
COUNT(1) AS totalCount,
|
||||
DATE_FORMAT(MAX(<include refid="parsedTrxDateExpr"/>), '%Y-%m-%d %H:%i:%s') AS latestTrxDate
|
||||
FROM ccdi_bank_statement bs
|
||||
<where>
|
||||
<include refid="statementFilterWhere"/>
|
||||
</where>
|
||||
GROUP BY <include refid="counterpartyNameExpr"/>
|
||||
) grouped
|
||||
<include refid="counterpartyOrderBy"/>
|
||||
</select>
|
||||
|
||||
<select id="selectStatementListForExport" resultMap="CcdiBankStatementListVOResultMap">
|
||||
SELECT
|
||||
<include refid="statementListColumns"/>
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ruoyi.ccdi.project.controller;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.excel.CcdiBankStatementExcel;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementCounterpartyVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
|
||||
@@ -80,6 +81,31 @@ class CcdiBankStatementControllerTest {
|
||||
assertEquals(1, result.getRows().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void counterpartyList_shouldReturnTableData() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("pageNum", "1");
|
||||
request.setParameter("pageSize", "10");
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
|
||||
|
||||
CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO();
|
||||
queryDTO.setProjectId(100L);
|
||||
CcdiBankStatementCounterpartyVO row = new CcdiBankStatementCounterpartyVO();
|
||||
row.setCustomerAccountName("测试对手方");
|
||||
row.setTotalCount(2L);
|
||||
Page<CcdiBankStatementCounterpartyVO> page = new Page<>(1, 10);
|
||||
page.setRecords(List.of(row));
|
||||
page.setTotal(1);
|
||||
when(bankStatementService.selectCounterpartyPage(any(), same(queryDTO))).thenReturn(page);
|
||||
|
||||
TableDataInfo result = controller.counterpartyList(queryDTO);
|
||||
|
||||
assertEquals(200, result.getCode());
|
||||
assertEquals(1L, result.getTotal());
|
||||
assertEquals(1, result.getRows().size());
|
||||
verify(projectAccessService).assertCanRead(100L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void detail_shouldReturnAjaxResultSuccess() {
|
||||
CcdiBankStatementDetailVO detailVO = new CcdiBankStatementDetailVO();
|
||||
|
||||
@@ -116,6 +116,27 @@ class CcdiBankStatementMapperXmlTest {
|
||||
assertTrue(sql.contains("END ) <= ?"), sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectCounterpartyPage_shouldGroupByTrimmedCounterpartyNameAndReuseFilters() throws Exception {
|
||||
MappedStatement mappedStatement = loadMappedStatement(
|
||||
"com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper.selectCounterpartyPage");
|
||||
CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO();
|
||||
queryDTO.setProjectId(33L);
|
||||
queryDTO.setTabType("out");
|
||||
queryDTO.setCounterpartyName("杭州");
|
||||
queryDTO.setOrderBy("totalAmount");
|
||||
queryDTO.setOrderDirection("desc");
|
||||
|
||||
String sql = renderSql(mappedStatement, queryDTO);
|
||||
|
||||
assertTrue(sql.contains("TRIM(IFNULL(bs.CUSTOMER_ACCOUNT_NAME, '')) AS customerAccountName"), sql);
|
||||
assertTrue(sql.contains("GROUP BY TRIM(IFNULL(bs.CUSTOMER_ACCOUNT_NAME, ''))"), sql);
|
||||
assertTrue(sql.contains("(bs.project_id = ?)"), sql);
|
||||
assertTrue(sql.contains("IFNULL(bs.AMOUNT_DR, 0) > 0"), sql);
|
||||
assertTrue(sql.contains("bs.CUSTOMER_ACCOUNT_NAME LIKE CONCAT('%', TRIM(?), '%')"), sql);
|
||||
assertTrue(sql.contains("ORDER BY totalAmount DESC, totalCount DESC, customerAccountName ASC"), sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectStatementDetailById_shouldJoinUploadRecordForOriginalFileMetadata() throws Exception {
|
||||
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(RESOURCE)) {
|
||||
|
||||
Reference in New Issue
Block a user