feat:导出

This commit is contained in:
dzc committed 2025-12-17 14:32:33 +08:00
1 parent e5f652d9af
commit 8e18dda8c8
16 files changed
+481 -2

No files matched your search

+43
View File
@@ -0,0 +1,43 @@
CREATE OR REPLACE VIEW pjcloudx_wallet.v_mch_dept_tree AS
WITH RECURSIVE
root AS (SELECT m.dept_id AS root_dept_id,
m.id AS mch_id,
m.name AS mch_name
FROM pjcloudx_wallet.mch_manage AS m
JOIN pjcloudx.sys_dept AS d
ON d.dept_id = m.dept_id
AND d.del_flag = '0'
WHERE m.del_flag = '0'
AND m.types = '1'),
r (dept_id, parent_id, dept_name, root_dept_id, mch_id, mch_name, level) AS (SELECT d.dept_id,
d.parent_id,
d.name,
root.root_dept_id,
root.mch_id,
root.mch_name,
0
FROM pjcloudx.sys_dept AS d
JOIN root
ON root.root_dept_id = d.dept_id
WHERE d.del_flag = '0'
UNION ALL
SELECT c.dept_id,
c.parent_id,
c.name,
r.root_dept_id,
r.mch_id,
r.mch_name,
r.level + 1
FROM pjcloudx.sys_dept AS c
JOIN r
ON c.parent_id = r.dept_id
WHERE c.del_flag = '0')
SELECT root_dept_id AS mchDeptId,
mch_id AS mchId,
mch_name AS mchName,
dept_id AS deptId,
parent_id AS parentId,
dept_name AS deptName,
level AS level
FROM r
ORDER BY mchDeptId, level, deptId;
@@ -23,6 +23,11 @@ public class WalletTransactionDto extends WalletTransactionEntity implements Bas
private Integer type;
/**
* 商户相关
*/
private Long mchId;
/**
* 用户id
*/
@@ -41,6 +46,8 @@ public class WalletTransactionDto extends WalletTransactionEntity implements Bas
*/
private Boolean isFindOrder = false;
private List<Long> totalDpetIds;
/**
* 部门ids
*/
@@ -0,0 +1,13 @@
package com.bsd.pjcloud.wallet.api.dto.mch;
import com.bsd.pjcloud.wallet.api.entity.mch.view.WalletMchDeptViewEntity;
import lombok.Data;
import java.util.List;
@Data
public class WalletMchDeptViewDto extends WalletMchDeptViewEntity {
private List<Long> mchIdList;
}
@@ -0,0 +1,48 @@
package com.bsd.pjcloud.wallet.api.entity.mch.view;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 商户部门视图
*/
@Data
@Schema(description = "商户部门视图")
public class WalletMchDeptViewEntity {
/**
* 商户部门id
*/
private Long mchDeptId;
/**
* 商户id
*/
private Long mchId;
/**
* 商户名
*/
private String mchName;
/**
* 上级部门id
*/
private Long parentId;
/**
* 部门id
*/
private Long deptId;
/**
* 部门名
*/
private String deptName;
/**
* 层级
*/
private Long level;
}
@@ -0,0 +1,55 @@
package com.bsd.pjcloud.wallet.api.vo;
import lombok.Data;
@Data
public class WalletCzTotalVo {
/**
* 商户id
*/
private Long mchId;
/**
* 商户名
*/
private String mchName;
/**
* 部门id
*/
private Long deptId;
/**
* 部门名
*/
private String deptName;
/**
* 充值金额
*/
private Long price = 0L;
private String priceStr;
/**
* 充值人数
*/
private Long personCount = 0L;
private String personCountStr;
/**
* 充值次数
*/
private Long timeCount = 0L;
private String timeCountStr;
/**
* 导出相关
*/
private Long lineNumber;
}
@@ -5,6 +5,11 @@ import lombok.Data;
@Data
public class WalletTypeCountVo {
/**
* 部门id
*/
private Long deptId;
/**
* 充值次数
*/
@@ -15,4 +20,9 @@ public class WalletTypeCountVo {
*/
private Long priceTotal;
/**
* 充值人数
*/
private Long personTotal;
}
@@ -0,0 +1,8 @@
package com.bsd.pjcloud.wallet.api.vo.mch;
import com.bsd.pjcloud.wallet.api.entity.mch.view.WalletMchDeptViewEntity;
import lombok.Data;
@Data
public class WalletMchDeptViewVo extends WalletMchDeptViewEntity {
}
@@ -5,7 +5,6 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.data.datascope.DataScopeFuncEnum;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
@@ -15,6 +14,7 @@ import com.bsd.pjcloud.wallet.api.dto.WalletBalanceTransactionDto;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionDto;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionSumAndCountDto;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletCzTotalVo;
import com.bsd.pjcloud.wallet.api.vo.WalletTransactionSumAndCountVo;
import com.bsd.pjcloud.wallet.api.vo.WalletTypeTotalVo;
import com.bsd.pjcloud.wallet.api.vo.transaction.WalletTransactionVo;
@@ -101,6 +101,42 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.scopePageList(page, dto, dataScope));
}
@Operation(summary = "后台充值统计", description = "后台充值统计")
@PostMapping("/page-cz-total")
public R<List<WalletCzTotalVo>> listCzTotal(@RequestBody WalletTransactionDto dto) {
dto.setBizTypes(WalletBizEnum.getTopUpCodes());
dto.setType(WalletTransactionDto.TYPE_INCOME);
if (ObjectUtil.isNotEmpty(dto.getPrice())) {
dto.setPrice(dto.getPrice() * 100);
}
DataScope dataScope = new DataScope();
return R.ok(walletTransactionService.pageCzTotalList(dto, dataScope));
}
@Operation(summary = "后台充值统计(导出)", description = "后台充值统计(导出)")
@PostMapping("/export-cz-total")
public void exportCzTotal(HttpServletResponse response, @RequestBody WalletTransactionDto dto) {
dto.setBizTypes(WalletBizEnum.getTopUpCodes());
dto.setType(WalletTransactionDto.TYPE_INCOME);
if (ObjectUtil.isNotEmpty(dto.getPrice())) {
dto.setPrice(dto.getPrice() * 100);
}
walletTransactionService.exportCzTotal(response, dto, null);
}
@Operation(summary = "后台充值统计", description = "后台充值统计")
@PostMapping("/page-cz-dept-total")
public R<List<WalletCzTotalVo>> listDeptCzTotal(@RequestBody WalletTransactionDto dto) {
dto.setBizTypes(WalletBizEnum.getTopUpCodes());
dto.setType(WalletTransactionDto.TYPE_INCOME);
if (ObjectUtil.isNotEmpty(dto.getPrice())) {
dto.setPrice(dto.getPrice() * 100);
}
DataScope dataScope = new DataScope();
return R.ok(walletTransactionService.listDeptCzTotal(dto, dataScope));
}
@Operation(summary = "后台记账扣款记录分页", description = "后台记账扣款记录分页")
@PostMapping("/page-jz")
public R pageJz(@ParameterObject Page page, @RequestBody WalletTransactionDto dto) {
@@ -71,6 +71,8 @@ public interface WalletTransactionMapper extends PjcloudBaseMapper<WalletTransac
WalletTypeCountVo walletTypetotal(@Param("dto") WalletTransactionDto dto, @Param("dataScope") DataScope dataScope);
List<WalletTypeCountVo> walletTypetotalByDept(@Param("dto") WalletTransactionDto dto, @Param("dataScope") DataScope dataScope);
default List<WalletTransactionVo> scopeList(WalletTransactionDto dto, DataScope dataScope) {
List<WalletTransactionEntity> list = selectListByScope(commonWrapperQuery(dto), dataScope);
return BeanUtils.toBean(list, WalletTransactionVo.class);
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.wallet.mapper.mch.view;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.wallet.api.dto.mch.WalletMchDeptViewDto;
import com.bsd.pjcloud.wallet.api.entity.mch.view.WalletMchDeptViewEntity;
import com.bsd.pjcloud.wallet.api.vo.mch.WalletMchDeptViewVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface MchDeptViewMapper {
List<WalletMchDeptViewVo> selectList(@Param("dto") WalletMchDeptViewDto dto);
}
@@ -6,6 +6,7 @@ import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionDto;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletCzTotalVo;
import com.bsd.pjcloud.wallet.api.vo.WalletTypeTotalVo;
import com.bsd.pjcloud.wallet.api.vo.transaction.WalletTransactionVo;
import jakarta.servlet.http.HttpServletResponse;
@@ -16,6 +17,16 @@ public interface WalletTransactionService extends IService<WalletTransactionEnti
Page<WalletTransactionVo> scopePageList(Page page, WalletTransactionDto dto, DataScope dataScope);
/**
* 后台充值统计
*/
List<WalletCzTotalVo> pageCzTotalList(WalletTransactionDto dto, DataScope dataScope);
/**
* 后台充值统计(按照部门)
*/
List<WalletCzTotalVo> listDeptCzTotal(WalletTransactionDto dto, DataScope dataScope);
/**
* 记账列表
*/
@@ -57,4 +68,9 @@ public interface WalletTransactionService extends IService<WalletTransactionEnti
Boolean updateWalletBalance(WalletTransactionDto dto);
void exportByTemplate(HttpServletResponse response, WalletTransactionDto dto, String fileName, List<WalletTransactionVo> list);
/**
* 后台充值统计(导出)
*/
void exportCzTotal(HttpServletResponse response, WalletTransactionDto dto, DataScope dataScope);
}
@@ -21,21 +21,30 @@ import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.mch.WalletMchSupType;
import com.bsd.pjcloud.wallet.api.dto.MchManageDto;
import com.bsd.pjcloud.wallet.api.dto.WalletManageDto;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionDto;
import com.bsd.pjcloud.wallet.api.dto.WalletTypeDto;
import com.bsd.pjcloud.wallet.api.dto.mch.WalletMchDeptViewDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.api.utils.WalletDataUtil;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletCzTotalVo;
import com.bsd.pjcloud.wallet.api.vo.WalletTypeCountVo;
import com.bsd.pjcloud.wallet.api.vo.WalletTypeTotalVo;
import com.bsd.pjcloud.wallet.api.vo.mch.WalletMchDeptViewVo;
import com.bsd.pjcloud.wallet.api.vo.transaction.WalletTransactionVo;
import com.bsd.pjcloud.wallet.mapper.WalletManageMapper;
import com.bsd.pjcloud.wallet.mapper.WalletTransactionMapper;
import com.bsd.pjcloud.wallet.mapper.WalletTypeMapper;
import com.bsd.pjcloud.wallet.mapper.mch.view.MchDeptViewMapper;
import com.bsd.pjcloud.wallet.service.MchManageService;
import com.bsd.pjcloud.wallet.service.WalletManageService;
import com.bsd.pjcloud.wallet.service.WalletThirdZyService;
import com.bsd.pjcloud.wallet.service.WalletTransactionService;
@@ -74,6 +83,9 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
private final WalletManageMapper walletManageMapper;
private final WalletTypeMapper walletTypeMapper;
private final MchDeptViewMapper mchDeptViewMapper;
private final MchManageService mchManageService;
private final RemoteUserService userService;
private final RemoteDeptService deptService;
@@ -182,6 +194,85 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
return list;
}
/**
* 后台充值统计
*/
@Override
public List<WalletCzTotalVo> pageCzTotalList(WalletTransactionDto dto, DataScope dataScope) {
List<WalletCzTotalVo> resultList = new ArrayList<>();
// 查询食堂
MchManageDto mchQueryDto = MchManageDto.builder().typesList(List.of(HardTypeEnum.SUPERMARKET.getType())).build();
if (ObjectUtil.isNotEmpty(dto.getMchId())) {
mchQueryDto.setId(dto.getMchId());
}
List<MchManageVo> list = mchManageService.list(mchQueryDto);
if (ObjectUtil.isEmpty(list)) return List.of();
resultList = list.stream().map(item -> {
WalletCzTotalVo entity = new WalletCzTotalVo();
entity.setMchId(item.getId());
entity.setMchName(item.getName());
entity.setDeptId(item.getDeptId());
entity.setDeptName(item.getDeptName());
return entity;
}).toList();
// 查询食堂的充值情况
WalletMchDeptViewDto query = new WalletMchDeptViewDto();
query.setMchIdList(list.stream().map(MchManageVo::getId).toList());
List<WalletMchDeptViewVo> mchDeptList = mchDeptViewMapper.selectList(query);
if (ObjectUtil.isEmpty(list)) return List.of();
for (WalletCzTotalVo item : resultList) {
Long mchId = item.getMchId();
List<Long> mchAllDeptIdList = mchDeptList.stream().filter(v -> ObjectUtil.equals(v.getMchId(), mchId)).map(WalletMchDeptViewVo::getDeptId).toList();
if (ObjectUtil.isEmpty(mchAllDeptIdList)) continue;
WalletTransactionDto totalQuery = BeanUtils.toBean(dto, WalletTransactionDto.class);
totalQuery.setTotalDpetIds(mchAllDeptIdList);
WalletTypeCountVo totalVo = baseMapper.walletTypetotal(totalQuery, null);
if (ObjectUtil.isEmpty(totalVo)) continue;
item.setPrice(totalVo.getPriceTotal());
item.setPersonCount(totalVo.getPersonTotal());
item.setTimeCount(totalVo.getTimeTotal());
}
return resultList;
}
/**
* 后台充值统计(按照部门)
*/
@Override
public List<WalletCzTotalVo> listDeptCzTotal(WalletTransactionDto dto, DataScope dataScope) {
List<WalletCzTotalVo> resultList = new ArrayList<>();
// 查询食堂的充值情况
WalletMchDeptViewDto query = new WalletMchDeptViewDto();
query.setMchId(dto.getMchId());
List<WalletMchDeptViewVo> mchDeptList = mchDeptViewMapper.selectList(query);
if (ObjectUtil.isEmpty(mchDeptList)) return List.of();
resultList = mchDeptList.stream().map(item -> {
WalletCzTotalVo entity = new WalletCzTotalVo();
entity.setMchId(item.getMchId());
entity.setMchName(item.getMchName());
entity.setDeptId(item.getDeptId());
entity.setDeptName(item.getDeptName());
return entity;
}).toList();
// 查询部门的充值情况
WalletTransactionDto totalQuery = BeanUtils.toBean(dto, WalletTransactionDto.class);
totalQuery.setTotalDpetIds(resultList.stream().map(WalletCzTotalVo::getDeptId).toList());
List<WalletTypeCountVo> deptTotalList = baseMapper.walletTypetotalByDept(totalQuery, null);
for (WalletCzTotalVo item : resultList) {
Long deptId = item.getDeptId();
WalletTypeCountVo targetTotal = deptTotalList.stream().filter(v -> ObjectUtil.equals(v.getDeptId(), deptId)).findFirst().orElse(null);
if (ObjectUtil.isEmpty(targetTotal)) {
continue;
}
item.setPrice(targetTotal.getPriceTotal());
item.setPersonCount(targetTotal.getPersonTotal());
item.setTimeCount(targetTotal.getTimeTotal());
}
return resultList;
}
/**
* 记账列表
*/
@@ -261,6 +352,56 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
}
}
/**
* 后台充值统计(导出)
*/
@Override
public void exportCzTotal(HttpServletResponse response, WalletTransactionDto dto, DataScope dataScope) {
String fileName = "file/钱包充值统计.xlsx";
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(ResourceUtil.getStream(fileName)).build()) {
// 查询导出数据
List<WalletCzTotalVo> list = pageCzTotalList(dto, dataScope);
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
Map<String, Object> map = new HashMap<String, Object>();
if (ObjectUtil.isNotEmpty(dto.getCreateTimeList())) {
map.put("timeSpan", " 到 ");
map.put("startTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[1], DatePattern.NORM_DATETIME_PATTERN));
}
if (ObjectUtil.isNotEmpty(list)) {
BigDecimal priceTotal = BigDecimal.ZERO;
BigDecimal personCountTotal = BigDecimal.ZERO;
BigDecimal timeCountTotal = BigDecimal.ZERO;
Long lineNumber = 1L;
for (WalletCzTotalVo v : list) {
v.setLineNumber(lineNumber);
lineNumber++;
if (ObjectUtil.isNotEmpty(v.getPrice())) {
priceTotal = priceTotal.add(BigDecimal.valueOf(v.getPrice()));
v.setPriceStr(BigDecimal.valueOf(v.getPrice()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString());
}
if (ObjectUtil.isNotEmpty(v.getPersonCount())) {
v.setPersonCountStr(v.getPersonCount().toString());
personCountTotal = personCountTotal.add(BigDecimal.valueOf(v.getPersonCount()));
}
if (ObjectUtil.isNotEmpty(v.getTimeCount())) {
v.setTimeCountStr(v.getTimeCount().toString());
timeCountTotal = timeCountTotal.add(BigDecimal.valueOf(v.getTimeCount()));
}
}
map.put("priceTotal", priceTotal.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString());
map.put("personCountTotal", personCountTotal.toString());
map.put("timeCountTotal", timeCountTotal.toString());
}
excelWriter.fill(map, writeSheet);
excelWriter.fill(list, fillConfig, writeSheet);
} catch (IOException e) {
e.printStackTrace();
log.error("|{}|后台充值统计(导出),dto:|{}|,fileName:|{}|,error:|{}|", TAG, JSON.toJSONString(dto), fileName, e.getMessage());
}
}
private void disposeList(List<WalletTransactionVo> list, WalletTransactionDto dto) {
if (ObjectUtil.isNotEmpty(list)) {
@@ -47,6 +47,9 @@
<if test="dto.deptId != null">
and a.dept_id = #{dto.deptId}
</if>
<if test="dto.price != null">
and a.price = #{dto.price}
</if>
<if test="dto.type != null and dto.type == 1 ">
and a.price &gt; 0
</if>
@@ -68,6 +71,12 @@
<if test="dto.createTimeList != null and dto.createTimeList.length == 2">
and a.create_time between #{dto.createTimeList[0]} and #{dto.createTimeList[1]}
</if>
<if test="dto.totalDpetIds != null and dto.totalDpetIds.size() != 0">
and a.dept_id IN
<foreach collection="dto.totalDpetIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.deptIds != null and dto.deptIds.size() != 0">
<choose>
<when test="dto.isInclude != null and dto.isInclude == true">
@@ -224,7 +233,7 @@
</select>
<select id="walletTypetotal" resultType="com.bsd.pjcloud.wallet.api.vo.WalletTypeCountVo">
select ifnull(sum(a.price), 0) as priceTotal, count(0) as timeTotal
select ifnull(sum(a.price), 0) as priceTotal, count(distinct a.user_id) as personTotal, count(0) as timeTotal
FROM wallet_transaction a
left join wallet_manage m on m.id = a.wallet_id
<where>
@@ -234,4 +243,20 @@
</if>
</where>
</select>
<select id="walletTypetotalByDept" resultType="com.bsd.pjcloud.wallet.api.vo.WalletTypeCountVo">
select a.dept_id,
ifnull(sum(a.price), 0) as priceTotal,
count(distinct a.user_id) as personTotal,
count(0) as timeTotal
FROM wallet_transaction a
left join wallet_manage m on m.id = a.wallet_id
<where>
<include refid="whereA"/>
<if test="dto.walletTypeId != null">
and m.wallet_type_id = #{dto.walletTypeId}
</if>
</where>
group by a.dept_id
</select>
</mapper>
@@ -59,6 +59,9 @@
<sql id="whereA">
a.del_flag = 0
<if test="dto.id != null">
and a.id = #{dto.id}
</if>
<if test="dto.types != null">
and a.types = #{dto.types}
</if>
@@ -0,0 +1,55 @@
<?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.bsd.pjcloud.wallet.mapper.mch.view.MchDeptViewMapper">
<sql id="selectA">
select a.mchDeptId,
a.mchId,
a.mchName,
a.deptId,
a.parentId,
a.deptName,
a.level
</sql>
<sql id="whereA">
<if test="dto.mchDeptId != null">
and a.mchDeptId = #{dto.mchDeptId}
</if>
<if test="dto.mchId != null">
and a.mchId = #{dto.mchId}
</if>
<if test="dto.mchIdList != null and dto.mchIdList.size() != 0">
and a.mchId IN
<foreach collection="dto.mchIdList" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.mchName != null">
and a.mchName like concat('%',#{dto.mchName},'%')
</if>
<if test="dto.deptId != null">
and a.deptId = #{dto.deptId}
</if>
<if test="dto.parentId != null">
and a.parentId = #{dto.parentId}
</if>
<if test="dto.deptName != null">
and a.deptName like concat('%',#{dto.deptName},'%')
</if>
<if test="dto.level != null">
and a.level = #{dto.level}
</if>
</sql>
<select id="selectList" resultType="com.bsd.pjcloud.wallet.api.vo.mch.WalletMchDeptViewVo">
<include refid="selectA"/>
from v_mch_dept_tree a
<where>
<include refid="whereA"/>
</where>
order by a.mchDeptId, a.level
</select>
</mapper>