feat: 导出账单使用Excel导入账单
This commit is contained in:
parent
9264ea26d3
commit
5d8f655a5b
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.dao.dto.financial.bill;
|
||||
package cn.bunny.dao.dto.financial.bill.excel;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
@ -0,0 +1,42 @@
|
|||
package cn.bunny.dao.dto.financial.bill.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "BillAddDto对象", title = "账单信息添加内容", description = "账单信息添加内容")
|
||||
public class BillImportUserDto {
|
||||
|
||||
@Schema(name = "username", title = "类型:1 - 收入,-1 - 支出")
|
||||
@ExcelProperty(index = 0)
|
||||
private String type;
|
||||
|
||||
@Schema(name = "amount", title = "金额")
|
||||
@ExcelProperty("金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(name = "description", title = "描述")
|
||||
@ExcelProperty("描述")
|
||||
private String description;
|
||||
|
||||
@Schema(name = "transactionDate", title = "交易日期")
|
||||
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ExcelProperty("交易日期")
|
||||
private LocalDateTime transactionDate;
|
||||
|
||||
@Schema(name = "categoryId", title = "类别")
|
||||
@ExcelProperty("类别")
|
||||
private String categoryName;
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package cn.bunny.dao.dto.financial.bill.user;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Max;
|
||||
|
@ -25,28 +24,23 @@ public class BillAddUserDto {
|
|||
@NotNull(message = "类型不能为空")
|
||||
@Min(value = -1, message = "类型格式不正确")
|
||||
@Max(value = 1, message = "类型格式不正确")
|
||||
@ExcelProperty(index = 0)
|
||||
private Byte type;
|
||||
|
||||
@Schema(name = "amount", title = "金额")
|
||||
@NotNull(message = "金额不能为空")
|
||||
@Min(value = 0, message = "金额格式不正确")
|
||||
@ExcelProperty("金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(name = "description", title = "描述")
|
||||
@ExcelProperty("描述")
|
||||
private String description;
|
||||
|
||||
@Schema(name = "transactionDate", title = "交易日期")
|
||||
@NotNull(message = "交易日期不能为空")
|
||||
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ExcelProperty("交易日期")
|
||||
private LocalDateTime transactionDate;
|
||||
|
||||
@Schema(name = "categoryId", title = "类别id")
|
||||
@NotNull(message = "类别id不能为空")
|
||||
@ExcelProperty("类别id")
|
||||
private Long categoryId;
|
||||
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package cn.bunny.services.controller.financial;
|
||||
|
||||
import cn.bunny.dao.dto.financial.bill.BillDto;
|
||||
import cn.bunny.dao.dto.financial.bill.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillAddDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillUpdateUserDto;
|
||||
import cn.bunny.dao.entity.financial.Bill;
|
||||
|
@ -23,6 +23,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -76,6 +77,13 @@ public class BillController {
|
|||
return Mono.just(Result.success(vo));
|
||||
}
|
||||
|
||||
@Operation(summary = "使用Excel导入用户账单", description = "使用Excel导入用户账单")
|
||||
@PostMapping("noManage/importBill")
|
||||
public Mono<Result<Result<String>>> importBill(MultipartFile file) {
|
||||
billService.importBill(file);
|
||||
return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS));
|
||||
}
|
||||
|
||||
@Operation(summary = "导出用户账单信息", description = "导出用户账单信息")
|
||||
@PostMapping("noManage/exportBill")
|
||||
public void exportBill(@Valid @RequestBody BillExportDto dto, HttpServletResponse response) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
@ -83,6 +84,12 @@ public class FilesController {
|
|||
return filesService.downloadFilesByFilepath(filepath);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取添加账单模板文件", description = "获取添加账单模板文件")
|
||||
@GetMapping("noManage/getAddBillTemplate")
|
||||
public void getAddBillTemplate(HttpServletResponse response) {
|
||||
filesService.getAddBillTemplate(response);
|
||||
}
|
||||
|
||||
// // 无法做权限校验
|
||||
// @Operation(summary = "根据文件名访问resource下图片文件", description = "根据文件名访问resource下文件")
|
||||
// @GetMapping("noAuth/getResourceImagesByFilename/{filename}")
|
||||
|
|
|
@ -1,11 +1,74 @@
|
|||
package cn.bunny.services.excel;
|
||||
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto;
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillImportUserDto;
|
||||
import cn.bunny.dao.entity.financial.Bill;
|
||||
import cn.bunny.dao.entity.financial.Category;
|
||||
import cn.bunny.services.mapper.financial.CategoryMapper;
|
||||
import cn.bunny.services.service.financial.BillService;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BillAddUserDAO {
|
||||
public void save(List<BillAddUserDto> list) {
|
||||
// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
|
||||
|
||||
public void save(List<BillImportUserDto> cachedDataList, BillService billService, CategoryMapper categoryMapper, StrBuilder messageContent, AtomicReference<Integer> index) {
|
||||
Long userId = BaseContext.getUserId();
|
||||
|
||||
// 查询数据
|
||||
LambdaQueryWrapper<Category> queryWrapper = Wrappers.<Category>lambdaQuery().eq(Category::getUserId, userId).or().eq(Category::getIsBuiltin, true);
|
||||
Map<String, Long> categoryMap = categoryMapper.selectList(queryWrapper).stream().collect(Collectors.toMap(Category::getCategoryName, Category::getId));
|
||||
|
||||
List<Bill> billList = cachedDataList.stream()
|
||||
// 判断是否有值
|
||||
.filter(billImportUserDto -> {
|
||||
index.updateAndGet(i -> i == null ? 1 : i + 1);
|
||||
|
||||
String billImportUserDtoType = billImportUserDto.getType();
|
||||
BigDecimal amount = billImportUserDto.getAmount();
|
||||
LocalDateTime transactionDate = billImportUserDto.getTransactionDate();
|
||||
String categoryName = billImportUserDto.getCategoryName();
|
||||
if (StringUtils.isEmpty(billImportUserDtoType)
|
||||
|| amount == null
|
||||
|| StringUtils.isEmpty(categoryName)
|
||||
|| transactionDate == null) {
|
||||
|
||||
String string = "序号[" + index.get() + "]数据为空--> " + "类型:" + billImportUserDtoType + ", 金额:" + amount + ", 日期:" + transactionDate + ", 类别:" + categoryName + "<br/>";
|
||||
messageContent.append(string);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map(billImportUserDto -> {
|
||||
String billImportUserDtoType = billImportUserDto.getType();
|
||||
String categoryName = billImportUserDto.getCategoryName();
|
||||
|
||||
Bill bill = new Bill();
|
||||
BeanUtils.copyProperties(billImportUserDto, bill);
|
||||
|
||||
// 设置用户id
|
||||
bill.setUserId(userId);
|
||||
|
||||
// 判断添加的类型是否正确
|
||||
byte type = billImportUserDtoType.equals("收入") ? Byte.parseByte("1") : Byte.parseByte("-1");
|
||||
bill.setType(type);
|
||||
|
||||
// 添加的分类查找分类id
|
||||
Long categoryId = categoryMap.get(categoryName);
|
||||
bill.setCategoryId(categoryId);
|
||||
|
||||
return bill;
|
||||
}).toList();
|
||||
|
||||
billService.saveBatch(billList);
|
||||
}
|
||||
}
|
|
@ -1,27 +1,65 @@
|
|||
package cn.bunny.services.excel;
|
||||
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto;
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillImportUserDto;
|
||||
import cn.bunny.dao.entity.system.Message;
|
||||
import cn.bunny.dao.entity.system.MessageReceived;
|
||||
import cn.bunny.services.mapper.financial.CategoryMapper;
|
||||
import cn.bunny.services.mapper.message.MessageMapper;
|
||||
import cn.bunny.services.mapper.message.MessageReceivedMapper;
|
||||
import cn.bunny.services.service.financial.BillService;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||
import com.alibaba.excel.read.listener.ReadListener;
|
||||
import com.alibaba.excel.util.ListUtils;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 无法被Spring管理必须使用构造函数注入方式
|
||||
*/
|
||||
@Slf4j
|
||||
public class BillAddUserListener implements ReadListener<BillAddUserDto> {
|
||||
public class BillAddUserListener implements ReadListener<BillImportUserDto> {
|
||||
|
||||
// 缓存数据
|
||||
private static final int BATCH_COUNT = 100;
|
||||
// 需要存入数据库的数据
|
||||
private final BillAddUserDAO billAddUserDAO;
|
||||
private List<BillAddUserDto> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
|
||||
// 查询用户类别
|
||||
private final CategoryMapper categoryMapper;
|
||||
// 用户消息
|
||||
private final MessageMapper messageMapper;
|
||||
// 用户接受消息
|
||||
private final MessageReceivedMapper messageReceivedMapper;
|
||||
// 存入数据库信息
|
||||
private final BillService billService;
|
||||
private final StrBuilder messageContent = new StrBuilder();
|
||||
// 设置索引查看是第几个数据异常
|
||||
AtomicReference<Integer> index = new AtomicReference<>(1);
|
||||
private List<BillImportUserDto> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
|
||||
|
||||
public BillAddUserListener() {
|
||||
public BillAddUserListener(CategoryMapper categoryMapper, MessageMapper messageMapper, MessageReceivedMapper messageReceivedMapper, BillService billService) {
|
||||
billAddUserDAO = new BillAddUserDAO();
|
||||
this.categoryMapper = categoryMapper;
|
||||
this.billService = billService;
|
||||
this.messageMapper = messageMapper;
|
||||
this.messageReceivedMapper = messageReceivedMapper;
|
||||
}
|
||||
|
||||
public BillAddUserListener(BillAddUserDAO billAddUserDAO) {
|
||||
this.billAddUserDAO = billAddUserDAO;
|
||||
@Override
|
||||
public void onException(Exception exception, AnalysisContext context) {
|
||||
if (exception instanceof ExcelDataConvertException excelDataConvertException) {
|
||||
int row = excelDataConvertException.getRowIndex() + 1;
|
||||
int column = excelDataConvertException.getColumnIndex() + 1;
|
||||
log.warn("第{}行,第{}列解析异常,请正确填写", row, column);
|
||||
|
||||
messageContent.append("第").append(String.valueOf(row)).append("行,第").append(String.valueOf(column)).append("列解析异常,请正确填写<br/>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,8 +68,7 @@ public class BillAddUserListener implements ReadListener<BillAddUserDto> {
|
|||
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
|
||||
*/
|
||||
@Override
|
||||
public void invoke(BillAddUserDto data, AnalysisContext context) {
|
||||
log.info("解析到一条数据:{}", JSON.toJSONString(data));
|
||||
public void invoke(BillImportUserDto data, AnalysisContext context) {
|
||||
cachedDataList.add(data);
|
||||
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
|
||||
if (cachedDataList.size() >= BATCH_COUNT) {
|
||||
|
@ -46,15 +83,40 @@ public class BillAddUserListener implements ReadListener<BillAddUserDto> {
|
|||
*/
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
|
||||
saveData();
|
||||
if (StringUtils.isBlank(messageContent.toString())) return;
|
||||
|
||||
// 获取当前用户id同时也是接受人的id
|
||||
Long userId = BaseContext.getUserId();
|
||||
|
||||
// 将消息中的内容进行Base64编码,要求就是这样
|
||||
String encoded = Base64.getEncoder().encodeToString(messageContent.toString().getBytes());
|
||||
|
||||
// 如果有消息
|
||||
Message message = new Message();
|
||||
message.setTitle("导入账单时出错");
|
||||
message.setSendUserId(1L);
|
||||
message.setMessageType("1851507850609356802");
|
||||
message.setSummary("导入账单时出错");
|
||||
message.setContent(encoded);
|
||||
message.setEditorType("rich");
|
||||
message.setLevel("warning");
|
||||
message.setExtra("导入错误");
|
||||
messageMapper.insert(message);
|
||||
|
||||
// 从之前保存的消息中获取消息id,保存到消息接收表中
|
||||
MessageReceived messageReceived = new MessageReceived();
|
||||
messageReceived.setMessageId(message.getId());
|
||||
messageReceived.setReceivedUserId(userId);
|
||||
messageReceived.setStatus(false);
|
||||
messageReceivedMapper.insert(messageReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加上存储数据库
|
||||
*/
|
||||
private void saveData() {
|
||||
log.info("{}条数据,开始存储数据库!", cachedDataList.size());
|
||||
billAddUserDAO.save(cachedDataList);
|
||||
log.info("存储数据库成功!");
|
||||
billAddUserDAO.save(cachedDataList, billService, categoryMapper, messageContent, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.common.service.exception.BunnyException;
|
||||
import cn.bunny.dao.dto.financial.bill.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillExportDto;
|
||||
import cn.bunny.dao.excel.BillUserExportExcel;
|
||||
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package cn.bunny.services.service.financial;
|
||||
|
||||
import cn.bunny.dao.dto.financial.bill.BillDto;
|
||||
import cn.bunny.dao.dto.financial.bill.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillAddDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillUpdateUserDto;
|
||||
import cn.bunny.dao.entity.financial.Bill;
|
||||
|
@ -15,6 +15,7 @@ import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -107,4 +108,11 @@ public interface BillService extends IService<Bill> {
|
|||
* @param response 响应体
|
||||
*/
|
||||
void exportBillByAdmin(BillExportDto dto, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 使用Excel导入用户账单
|
||||
*
|
||||
* @param file 文件
|
||||
*/
|
||||
void importBill(MultipartFile file);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@ package cn.bunny.services.service.financial.impl;
|
|||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.common.service.exception.BunnyException;
|
||||
import cn.bunny.dao.dto.financial.bill.BillDto;
|
||||
import cn.bunny.dao.dto.financial.bill.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillAddDto;
|
||||
import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillExportDto;
|
||||
import cn.bunny.dao.dto.financial.bill.excel.BillImportUserDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto;
|
||||
import cn.bunny.dao.dto.financial.bill.user.BillUpdateUserDto;
|
||||
import cn.bunny.dao.entity.financial.Bill;
|
||||
|
@ -17,10 +18,15 @@ import cn.bunny.dao.vo.financial.user.BillUserVo;
|
|||
import cn.bunny.dao.vo.financial.user.expendAndIncome.CategoryAmount;
|
||||
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome;
|
||||
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo;
|
||||
import cn.bunny.services.excel.BillAddUserListener;
|
||||
import cn.bunny.services.factory.BillFactory;
|
||||
import cn.bunny.services.factory.HomeFactory;
|
||||
import cn.bunny.services.mapper.financial.BillMapper;
|
||||
import cn.bunny.services.mapper.financial.CategoryMapper;
|
||||
import cn.bunny.services.mapper.message.MessageMapper;
|
||||
import cn.bunny.services.mapper.message.MessageReceivedMapper;
|
||||
import cn.bunny.services.service.financial.BillService;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
@ -29,7 +35,9 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -47,9 +55,17 @@ public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements Bi
|
|||
|
||||
@Autowired
|
||||
private HomeFactory homeFactory;
|
||||
|
||||
@Autowired
|
||||
private BillFactory billFactory;
|
||||
|
||||
@Autowired
|
||||
private CategoryMapper categoryMapper;
|
||||
@Autowired
|
||||
private MessageMapper messageMapper;
|
||||
@Autowired
|
||||
private MessageReceivedMapper messageReceivedMapper;
|
||||
|
||||
/**
|
||||
* * 账单信息 服务实现类
|
||||
*
|
||||
|
@ -195,7 +211,7 @@ public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements Bi
|
|||
|
||||
// 分类列表
|
||||
List<CategoryAmount> categoryAmountList = expendWithIncomeList.stream()
|
||||
.filter(expendWithIncome -> dto.getType() != null && expendWithIncome.getType().equals(dto.getType()))
|
||||
.filter(expendWithIncome -> dto.getType() != null && expendWithIncome.getType().equals(dto.getType()) && expendWithIncome.getCategoryName() != null)
|
||||
.collect(Collectors.groupingBy(ExpendWithIncome::getCategoryName,
|
||||
Collectors.summingDouble(expend -> expend.getAmount().doubleValue()))
|
||||
).entrySet()
|
||||
|
@ -237,6 +253,20 @@ public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements Bi
|
|||
billFactory.exportBill(dto, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Excel导入用户账单
|
||||
*
|
||||
* @param file 文件
|
||||
*/
|
||||
@Override
|
||||
public void importBill(MultipartFile file) {
|
||||
try {
|
||||
EasyExcel.read(file.getInputStream(), BillImportUserDto.class, new BillAddUserListener(categoryMapper, messageMapper, messageReceivedMapper, this)).sheet().doRead();
|
||||
} catch (IOException e) {
|
||||
throw new BunnyException(ResultCodeEnum.UPDATE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除|批量删除账单信息
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@ import cn.bunny.dao.vo.system.files.FileInfoVo;
|
|||
import cn.bunny.dao.vo.system.files.FilesVo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
|
@ -84,4 +85,9 @@ public interface FilesService extends IService<Files> {
|
|||
* @return 媒体文件类型列表
|
||||
*/
|
||||
Set<String> getAllMediaTypes();
|
||||
|
||||
/**
|
||||
* 获取添加账单模板文件
|
||||
*/
|
||||
void getAddBillTemplate(HttpServletResponse response);
|
||||
}
|
||||
|
|
|
@ -9,18 +9,25 @@ import cn.bunny.dao.dto.system.files.FileUploadDto;
|
|||
import cn.bunny.dao.dto.system.files.FilesAddDto;
|
||||
import cn.bunny.dao.dto.system.files.FilesDto;
|
||||
import cn.bunny.dao.dto.system.files.FilesUpdateDto;
|
||||
import cn.bunny.dao.entity.financial.Category;
|
||||
import cn.bunny.dao.entity.system.Files;
|
||||
import cn.bunny.dao.pojo.common.MinioFilePath;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.files.FileInfoVo;
|
||||
import cn.bunny.dao.vo.system.files.FilesVo;
|
||||
import cn.bunny.services.mapper.financial.CategoryMapper;
|
||||
import cn.bunny.services.mapper.system.FilesMapper;
|
||||
import cn.bunny.services.service.system.FilesService;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
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 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
@ -38,6 +45,7 @@ import java.io.IOException;
|
|||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -63,6 +71,8 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
|||
|
||||
@Autowired
|
||||
private FilesMapper filesMapper;
|
||||
@Autowired
|
||||
private CategoryMapper categoryMapper;
|
||||
|
||||
/**
|
||||
* * 系统文件表 服务实现类
|
||||
|
@ -289,4 +299,32 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
|
|||
return Set.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加账单模板文件
|
||||
*/
|
||||
@Override
|
||||
public void getAddBillTemplate(HttpServletResponse response) {
|
||||
// 设置数据库查询时间
|
||||
Long userId = BaseContext.getUserId();
|
||||
|
||||
// 查询数据
|
||||
LambdaQueryWrapper<Category> queryWrapper = Wrappers.<Category>lambdaQuery().eq(Category::getUserId, userId).or().eq(Category::getIsBuiltin, true);
|
||||
List<Category> categoryList = categoryMapper.selectList(queryWrapper);
|
||||
|
||||
String filenameTemplate = Objects.requireNonNull(getClass().getResource("/static/bill-add-template.xlsx")).getFile();
|
||||
if (filenameTemplate == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES);
|
||||
|
||||
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(filenameTemplate).build()) {
|
||||
// 填充数据,类型数据要填充的在第二个sheet
|
||||
WriteSheet writeSheet = EasyExcel.writerSheet(1).build();
|
||||
excelWriter.fill(categoryList, writeSheet);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "bill-add-template.xlsx");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -2,13 +2,20 @@ package cn.bunny.services.service.financial.impl;
|
|||
|
||||
import cn.bunny.common.service.exception.BunnyException;
|
||||
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
|
||||
import cn.bunny.dao.entity.financial.Category;
|
||||
import cn.bunny.dao.entity.system.Message;
|
||||
import cn.bunny.dao.entity.system.MessageReceived;
|
||||
import cn.bunny.dao.excel.BillUserExportExcel;
|
||||
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome;
|
||||
import cn.bunny.services.mapper.financial.BillMapper;
|
||||
import cn.bunny.services.mapper.financial.CategoryMapper;
|
||||
import cn.bunny.services.mapper.message.MessageMapper;
|
||||
import cn.bunny.services.mapper.message.MessageReceivedMapper;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -16,16 +23,19 @@ import org.springframework.boot.test.context.SpringBootTest;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@SpringBootTest
|
||||
class BillServiceImplTest {
|
||||
@Autowired
|
||||
private BillMapper billMapper;
|
||||
@Autowired
|
||||
private CategoryMapper categoryMapper;
|
||||
@Autowired
|
||||
private MessageMapper messageMapper;
|
||||
@Autowired
|
||||
private MessageReceivedMapper messageReceivedMapper;
|
||||
|
||||
@Test
|
||||
void exportBill() {
|
||||
|
@ -81,4 +91,52 @@ class BillServiceImplTest {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void downloadAddBillTemplate() {
|
||||
// 设置数据库查询时间
|
||||
Long userId = 1849444494908125181L;
|
||||
|
||||
// 查询数据
|
||||
List<Category> categoryList = categoryMapper.selectList(Wrappers.<Category>lambdaQuery().eq(Category::getUserId, userId));
|
||||
|
||||
String filenameTemplate = Objects.requireNonNull(getClass().getResource("/static/bill-add-template.xlsx")).getFile();
|
||||
if (filenameTemplate == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES);
|
||||
|
||||
try (ExcelWriter excelWriter = EasyExcel.write("F:\\数据库备份\\bill-add-template.xlsx").withTemplate(filenameTemplate).build()) {
|
||||
// 填充数据
|
||||
WriteSheet writeSheet = EasyExcel.writerSheet(1).build();
|
||||
excelWriter.fill(categoryList, writeSheet);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void addBillByExcel() {
|
||||
String encoded = Base64.getEncoder().encodeToString("messageContent.toString()".getBytes());
|
||||
|
||||
// 如果有消息
|
||||
Message message = new Message();
|
||||
message.setTitle("导入账单时出错");
|
||||
message.setSendUserId(1L);
|
||||
message.setMessageType("1851507850609356802");
|
||||
message.setSummary("导入账单时出错");
|
||||
message.setContent(encoded);
|
||||
message.setEditorType("rich");
|
||||
message.setLevel("warning");
|
||||
message.setExtra("导入错误");
|
||||
messageMapper.insert(message);
|
||||
|
||||
// 从之前保存的消息中获取消息id,保存到消息接收表中
|
||||
// Long userId = BaseContext.getUserId();
|
||||
Long userId = 1849444494908125181L;
|
||||
MessageReceived messageReceived = new MessageReceived();
|
||||
messageReceived.setMessageId(message.getId());
|
||||
messageReceived.setReceivedUserId(userId);
|
||||
messageReceived.setStatus(false);
|
||||
messageReceivedMapper.insert(messageReceived);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package excel.fill;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
public class FillTest {
|
||||
|
||||
@Test
|
||||
void fillTest1() {
|
||||
// // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||
// String filenameTemplate = "F:\\数据库备份\\bill-template.xlsx";
|
||||
//
|
||||
// // 设置数据库查询时间
|
||||
// BillExportDto billExportDto = new BillExportDto();
|
||||
// billExportDto.setUserId(1849444494908125181L);
|
||||
// billExportDto.setStartDate(LocalDate.of(2024, 11, 1));
|
||||
// billExportDto.setEndDate(LocalDate.of(2024, 11, 30));
|
||||
//
|
||||
// EasyExcel.write("F:\\数据库备份\\" + billExportDto.getStartDate() + "~" + billExportDto.getEndDate() + ".xlsx").withTemplate(filenameTemplate).sheet().doFill(fillData);
|
||||
|
||||
// // 方案2 根据Map填充
|
||||
// fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
|
||||
// // 这里 会填充到第一个sheet, 然后文件流会自动关闭
|
||||
// Map<String, Object> map = MapUtils.newHashMap();
|
||||
// map.put("name", "张三");
|
||||
// map.put("number", 5.2);
|
||||
// EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue