资金流水
parent
820f28fd17
commit
367639ae1b
|
|
@ -89,6 +89,18 @@
|
|||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.35</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
package com.njzscloud.dispose.common.utils;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.poi.excel.BigExcelWriter;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
||||
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* File工具类,扩展
|
||||
*
|
||||
* @author ljw
|
||||
* @date 2505-10-13
|
||||
*/
|
||||
@Slf4j
|
||||
public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||
|
||||
/**
|
||||
* 系统临时目录
|
||||
* <br>
|
||||
* windows 包含路径分割符,但Linux 不包含,
|
||||
* 在windows \\==\ 前提下,
|
||||
* 为安全起见 同意拼装 路径分割符,
|
||||
* <pre>
|
||||
* java.io.tmpdir
|
||||
* windows : C:\Users/xxx\AppData\Local\Temp\
|
||||
* linux: /temp
|
||||
* </pre>
|
||||
*/
|
||||
public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
|
||||
|
||||
/**
|
||||
* 导出excel,支持自定义文件名
|
||||
*/
|
||||
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response, String fileName) throws IOException {
|
||||
String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
|
||||
File file = new File(tempPath);
|
||||
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
|
||||
// 处理数据以防止CSV注入
|
||||
List<Map<String, Object>> sanitizedList = list.parallelStream().map(map -> {
|
||||
Map<String, Object> sanitizedMap = new LinkedHashMap<>();
|
||||
map.forEach((key, value) -> {
|
||||
if (value instanceof String) {
|
||||
String strValue = (String) value;
|
||||
// 检查并处理以特殊字符开头的值
|
||||
if (strValue.startsWith("=") || strValue.startsWith("+") || strValue.startsWith("-") || strValue.startsWith("@")) {
|
||||
strValue = "'" + strValue; // 添加单引号前缀
|
||||
}
|
||||
sanitizedMap.put(key, strValue);
|
||||
} else {
|
||||
sanitizedMap.put(key, value);
|
||||
}
|
||||
});
|
||||
return sanitizedMap;
|
||||
}).collect(Collectors.toList());
|
||||
// 一次性写出内容,使用默认样式,强制输出标题
|
||||
writer.write(sanitizedList, true);
|
||||
SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
|
||||
|
||||
// 手动设置列宽,确保标题和数据内容都能完整显示
|
||||
/*int columnCount = sheet.getRow(0).getLastCellNum();
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
String headerText = "";
|
||||
int maxContentLength = 0;
|
||||
|
||||
try {
|
||||
// 获取标题文本
|
||||
if (sheet.getRow(0) != null && sheet.getRow(0).getCell(i) != null) {
|
||||
headerText = sheet.getRow(0).getCell(i).getStringCellValue();
|
||||
}
|
||||
|
||||
// 遍历所有数据行,找到最长的内容
|
||||
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
||||
if (sheet.getRow(rowIndex) != null && sheet.getRow(rowIndex).getCell(i) != null) {
|
||||
String cellValue = sheet.getRow(rowIndex).getCell(i).getStringCellValue();
|
||||
if (cellValue != null) {
|
||||
maxContentLength = Math.max(maxContentLength, cellValue.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略获取单元格值的异常
|
||||
}
|
||||
|
||||
// 根据标题和内容的最大长度计算合适的列宽
|
||||
int headerLength = headerText.length();
|
||||
int contentLength = maxContentLength;
|
||||
int maxLength = Math.max(headerLength, contentLength);
|
||||
|
||||
// 设置列宽:每个字符约2个字符宽度,最小8个字符,最大50个字符
|
||||
int calculatedWidth = Math.max(Math.min(maxLength * 2, 50), 8) * 256;
|
||||
int currentWidth = sheet.getColumnWidth(i);
|
||||
|
||||
// 设置列宽,确保标题和内容都能完整显示
|
||||
sheet.setColumnWidth(i, Math.max(calculatedWidth, currentWidth));
|
||||
}*/
|
||||
|
||||
// 尝试自动调整列宽
|
||||
try {
|
||||
sheet.trackAllColumnsForAutoSizing();
|
||||
writer.autoSizeColumnAll();
|
||||
} catch (Exception e) {
|
||||
log.warn("自动调整列宽失败,使用手动设置的列宽", e);
|
||||
}
|
||||
//response为HttpServletResponse对象
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
|
||||
//设置文件名,支持中文文件名
|
||||
try {
|
||||
String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
|
||||
} catch (Exception e) {
|
||||
// 如果编码失败,使用默认文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
|
||||
}
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
// 终止后删除临时文件
|
||||
file.deleteOnExit();
|
||||
writer.flush(out, true);
|
||||
//此处记得关闭输出Servlet流
|
||||
IoUtil.close(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,11 +4,14 @@ import com.njzscloud.common.core.utils.R;
|
|||
import com.njzscloud.common.mp.support.PageParam;
|
||||
import com.njzscloud.common.mp.support.PageResult;
|
||||
import com.njzscloud.dispose.finance.pojo.entity.MoneyFlowEntity;
|
||||
import com.njzscloud.dispose.finance.pojo.param.SearchMoneyFlowParam;
|
||||
import com.njzscloud.dispose.finance.pojo.result.MoneyFlowResult;
|
||||
import com.njzscloud.dispose.finance.service.MoneyFlowService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -62,8 +65,16 @@ public class MoneyFlowController {
|
|||
* 分页查询
|
||||
*/
|
||||
@GetMapping("/paging")
|
||||
public R<PageResult<MoneyFlowEntity>> paging(PageParam pageParam, MoneyFlowEntity moneyFlowEntity) {
|
||||
return R.success(moneyFlowService.paging(pageParam, moneyFlowEntity));
|
||||
public R<PageResult<MoneyFlowResult>> paging(PageParam pageParam, SearchMoneyFlowParam flowParam) {
|
||||
return R.success(moneyFlowService.paging(pageParam, flowParam));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出资金流水
|
||||
*/
|
||||
@GetMapping(value = "/export")
|
||||
public void export(HttpServletResponse response, SearchMoneyFlowParam flowParam) throws IOException {
|
||||
moneyFlowService.export(response, flowParam);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,26 @@
|
|||
package com.njzscloud.dispose.finance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.njzscloud.dispose.finance.pojo.entity.MoneyFlowEntity;
|
||||
import com.njzscloud.dispose.finance.pojo.result.MoneyFlowResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资金流水
|
||||
*
|
||||
* @author ljw
|
||||
*/
|
||||
@Mapper
|
||||
public interface MoneyFlowMapper extends BaseMapper<MoneyFlowEntity> {
|
||||
}
|
||||
|
||||
IPage<MoneyFlowResult> paging(Page<Object> page, @Param("ew") QueryWrapper<?> ew);
|
||||
|
||||
List<MoneyFlowResult> paging(@Param("ew") QueryWrapper<?> ew);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.njzscloud.dispose.finance.pojo.param;
|
||||
|
||||
import com.njzscloud.dispose.finance.constant.AccountType;
|
||||
import com.njzscloud.dispose.finance.constant.MoneyChangeCategory;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 资金流水
|
||||
*
|
||||
* @author ljw
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
public class SearchMoneyFlowParam {
|
||||
|
||||
/**
|
||||
* 订单 Id
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String orderSn;
|
||||
|
||||
/**
|
||||
* 车次
|
||||
*/
|
||||
private Integer trainNum;
|
||||
|
||||
/**
|
||||
* 资金账户 Id;fin_money_account.id
|
||||
*/
|
||||
private Long moneyAccountId;
|
||||
|
||||
/**
|
||||
* 变动类型;字典代码:money_change_category
|
||||
*/
|
||||
private MoneyChangeCategory moneyChangeCategory;
|
||||
|
||||
/**
|
||||
* 账户名称(客户姓名或组织名称)
|
||||
*/
|
||||
private String accountName;
|
||||
|
||||
/**
|
||||
* 账户类型;GeRen-->个人、QiYe-->企业
|
||||
*/
|
||||
private AccountType accountType;
|
||||
|
||||
private LocalDateTime startTime;
|
||||
|
||||
private LocalDateTime endTime;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package com.njzscloud.dispose.finance.pojo.result;
|
||||
|
||||
import com.njzscloud.dispose.finance.constant.AccountType;
|
||||
import com.njzscloud.dispose.finance.constant.MoneyChangeCategory;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资金流水结果类
|
||||
*
|
||||
* @author ljw
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
public class MoneyFlowResult {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单 Id
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String orderSn;
|
||||
|
||||
/**
|
||||
* 车次
|
||||
*/
|
||||
private Integer trainNum;
|
||||
|
||||
/**
|
||||
* 资金账户 Id
|
||||
*/
|
||||
private Long moneyAccountId;
|
||||
|
||||
/**
|
||||
* 变动前余额
|
||||
*/
|
||||
private BigDecimal beforeBalance;
|
||||
|
||||
/**
|
||||
* 变动金额;有正负
|
||||
*/
|
||||
private BigDecimal delta;
|
||||
|
||||
/**
|
||||
* 变动后余额
|
||||
*/
|
||||
private BigDecimal afterBalance;
|
||||
|
||||
/**
|
||||
* 变动类型;字典代码:money_change_category
|
||||
*/
|
||||
private MoneyChangeCategory moneyChangeCategory;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
/**
|
||||
* 附件地址
|
||||
*/
|
||||
private List<String> fileUrl;
|
||||
|
||||
/**
|
||||
* 创建人 Id
|
||||
*/
|
||||
private Long creatorId;
|
||||
|
||||
/**
|
||||
* 修改人 Id
|
||||
*/
|
||||
private Long modifierId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private LocalDateTime modifyTime;
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
*/
|
||||
private Boolean deleted;
|
||||
|
||||
/**
|
||||
* 账户名称(客户姓名或组织名称)
|
||||
*/
|
||||
private String accountName;
|
||||
|
||||
/**
|
||||
* 账户类型;GeRen-->个人、QiYe-->企业
|
||||
*/
|
||||
private AccountType accountType;
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +1,27 @@
|
|||
package com.njzscloud.dispose.finance.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.njzscloud.common.mp.support.PageParam;
|
||||
import com.njzscloud.common.mp.support.PageResult;
|
||||
import com.njzscloud.dispose.common.utils.FileUtil;
|
||||
import com.njzscloud.dispose.finance.mapper.MoneyFlowMapper;
|
||||
import com.njzscloud.dispose.finance.pojo.entity.MoneyFlowEntity;
|
||||
import com.njzscloud.dispose.finance.pojo.param.SearchMoneyFlowParam;
|
||||
import com.njzscloud.dispose.finance.pojo.result.MoneyFlowResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资金流水
|
||||
|
|
@ -52,10 +62,56 @@ public class MoneyFlowService extends ServiceImpl<MoneyFlowMapper, MoneyFlowEnti
|
|||
return this.getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
*/
|
||||
private QueryWrapper<MoneyFlowEntity> buildQueryWrapper(SearchMoneyFlowParam param) {
|
||||
return Wrappers.<MoneyFlowEntity>query()
|
||||
.eq("fmf.deleted", Boolean.FALSE)
|
||||
.eq(param.getOrderId() != null, "fmf.order_id", param.getOrderId())
|
||||
.like(StrUtil.isNotBlank(param.getOrderSn()), "fmf.order_sn", param.getOrderSn())
|
||||
.eq(param.getTrainNum() != null, "fmf.train_num", param.getTrainNum())
|
||||
.eq(param.getMoneyAccountId() != null, "fmf.money_account_id", param.getMoneyAccountId())
|
||||
.eq(param.getMoneyChangeCategory() != null, "fmf.money_change_category", param.getMoneyChangeCategory())
|
||||
.and(StrUtil.isNotBlank(param.getAccountName()), wrapper ->
|
||||
wrapper.like("cc.customer_name", param.getAccountName())
|
||||
.or()
|
||||
.like("co.org_name", param.getAccountName())
|
||||
)
|
||||
.eq(param.getAccountType() != null, "fma.account_type", param.getAccountType())
|
||||
.ge(param.getStartTime() != null, "fmf.create_time", param.getStartTime())
|
||||
.le(param.getEndTime() != null, "fmf.create_time", param.getEndTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<MoneyFlowEntity> paging(PageParam pageParam, MoneyFlowEntity moneyFlowEntity) {
|
||||
return PageResult.of(this.page(pageParam.toPage(), Wrappers.query(moneyFlowEntity)));
|
||||
public PageResult<MoneyFlowResult> paging(PageParam pageParam, SearchMoneyFlowParam param) {
|
||||
return PageResult.of(baseMapper.paging(pageParam.toPage(), buildQueryWrapper(param)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*/
|
||||
public void export(HttpServletResponse response, SearchMoneyFlowParam param) throws IOException {
|
||||
List<MoneyFlowResult> exportList = baseMapper.paging(buildQueryWrapper(param));
|
||||
List<Map<String, Object>> downList = new ArrayList<>();
|
||||
int i = 1;
|
||||
for (MoneyFlowResult result : exportList) {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("编号", i);
|
||||
map.put("账户名称", result.getAccountName());
|
||||
map.put("账户类型", result.getAccountType().getTxt());
|
||||
map.put("订单号", result.getOrderSn());
|
||||
map.put("车次", result.getTrainNum());
|
||||
map.put("变动类型", result.getMoneyChangeCategory().getTxt());
|
||||
map.put("变动前金额", result.getBeforeBalance());
|
||||
map.put("变动金额", result.getDelta());
|
||||
map.put("变动后金额", result.getAfterBalance());
|
||||
map.put("备注", result.getMemo());
|
||||
downList.add(map);
|
||||
i++;
|
||||
}
|
||||
FileUtil.downloadExcel(downList, response, "资金变动明细.xlsx");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.njzscloud.dispose.finance.mapper.MoneyFlowMapper">
|
||||
<resultMap id="BaseResultMap" type="com.njzscloud.dispose.finance.pojo.result.MoneyFlowResult" autoMapping="true">
|
||||
<id column="id" property="id"/>
|
||||
<result column="file_url" property="fileUrl" typeHandler="com.njzscloud.common.mp.support.handler.j.JsonTypeHandler"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="SearchMoneyFlowResultSql">
|
||||
SELECT fmf.id,
|
||||
fmf.order_id,
|
||||
fmf.order_sn,
|
||||
fmf.train_num,
|
||||
fmf.money_account_id,
|
||||
fmf.before_balance,
|
||||
fmf.delta,
|
||||
fmf.after_balance,
|
||||
fmf.money_change_category,
|
||||
fmf.memo,
|
||||
fmf.file_url,
|
||||
fmf.creator_id,
|
||||
fmf.modifier_id,
|
||||
fmf.create_time,
|
||||
fmf.modify_time,
|
||||
fmf.deleted,
|
||||
CASE fma.account_type
|
||||
WHEN 'GeRen' THEN cc.customer_name
|
||||
WHEN 'QiYe' THEN co.org_name
|
||||
ELSE NULL
|
||||
END AS account_name,
|
||||
fma.account_type
|
||||
FROM fin_money_flow fmf
|
||||
LEFT JOIN fin_money_account fma ON fma.id = fmf.money_account_id
|
||||
LEFT JOIN cst_customer cc ON cc.id = fma.customer_id
|
||||
LEFT JOIN cst_org co ON co.id = fma.org_id
|
||||
</sql>
|
||||
|
||||
<select id="paging" resultMap="BaseResultMap">
|
||||
<include refid="SearchMoneyFlowResultSql"/>
|
||||
<if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
|
||||
${ew.customSqlSegment}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue