feat: 收入和支出图表展示

This commit is contained in:
Bunny 2024-11-23 23:11:10 +08:00
parent 31ff32fe34
commit ec36a45f34
21 changed files with 279 additions and 91 deletions

View File

@ -13,6 +13,8 @@ import lombok.extern.slf4j.Slf4j;
public class BunnyException extends RuntimeException {
Integer code;// 状态码
String message;// 描述信息
ResultCodeEnum resultCodeEnum;
public BunnyException(Integer code, String message) {
super(message);
@ -29,5 +31,6 @@ public class BunnyException extends RuntimeException {
super(codeEnum.getMessage());
this.code = codeEnum.getCode();
this.message = codeEnum.getMessage();
this.resultCodeEnum = codeEnum;
}
}

View File

@ -1,21 +0,0 @@
package cn.bunny.common.service.utils;
import cn.bunny.common.service.exception.BunnyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
@Slf4j
public class EmptyUtil {
/**
* 是否为空
*
* @param value 判断值
* @param message 错误消息
*/
public static void isEmpty(Object value, String message) {
if (value == null || !StringUtils.hasText(value.toString())) {
log.error("为空对象错误:{}{}", value, message);
throw new BunnyException(message);
}
}
}

View File

@ -0,0 +1,35 @@
package cn.bunny.dao.dto.financial.bill;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "ExpendWithIncomeDto对象", title = "账单收入和支出查询表单", description = "账单收入和支出查询表单")
public class ExpendWithIncomeDto {
@Schema(name = "userId", title = "绑定的用户id")
private Long userId;
@Schema(name = "type", title = "类型")
private Byte type;
@Schema(name = "startDate", title = "开始日期")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
@NotNull(message = "日期不能为空")
private LocalDate startDate;
@Schema(name = "endDate", title = "结束日期")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
@NotNull(message = "日期不能为空")
private LocalDate endDate;
}

View File

@ -48,7 +48,7 @@ public enum ResultCodeEnum {
FILE_NOT_EXIST(206, "文件不存在"),
NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"),
MISSING_TEMPLATE_FILES(206, "缺少模板文件"),
THE_MAXIMUM_BAR_CODE(206, "最大条码为50"),
THE_MAXIMUM_BAR_CODE(206, "超过最大上限"),
// 身份过期 208
LOGIN_AUTH(208, "请先登陆"),
@ -65,15 +65,13 @@ public enum ResultCodeEnum {
ILLEGAL_DATA_REQUEST(219, "非法数据请求"),
CLASS_NOT_FOUND(219, "类名不存在"),
ADMIN_ROLE_CAN_NOT_DELETED(219, "无法删除admin角色"),
ROUTER_RANK_NEED_LARGER_THAN_THE_PARENT(219, "设置路由等级需要大于或等于父级的路由等级"),
// 无权访问 403
FAIL_REQUEST_NOT_AUTH(403, "用户未认证"),
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"),
LOGGED_IN_FROM_ANOTHER_DEVICE(403, "没有权限访问"),
TOKEN_PARSING_FAILED(403, "token解析失败"),
FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"),
ROUTER_RANK_NEED_LARGER_THAN_THE_PARENT(219, "设置路由等级需要大于或等于父级的路由等级"),
// 系统错误 500
UNKNOWN_EXCEPTION(500, "服务异常"),

View File

@ -0,0 +1,22 @@
package cn.bunny.dao.vo.financial.user.expendAndIncome;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "ExpendWithIncomeVo对象", title = "账单收入和支出", description = "账单收入和支出")
public class CategoryAmount {
@Schema(name = "amount", title = "金额")
private Number amount;
@Schema(name = "categoryName", title = "分类名称")
private String categoryName;
}

View File

@ -0,0 +1,47 @@
package cn.bunny.dao.vo.financial.user.expendAndIncome;
import cn.bunny.dao.common.vo.BaseVo;
import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "ExpendWithIncomeVo对象", title = "账单收入和支出", description = "账单收入和支出")
public class ExpendWithIncome extends BaseVo {
@Schema(name = "username", title = "类型1 - 收入,-1 - 支出")
private Byte type;
@Schema(name = "amount", title = "金额")
private BigDecimal amount;
@Schema(name = "description", title = "描述")
private String description;
@Schema(name = "categoryId", title = "分类Id")
@JsonFormat(shape = JsonFormat.Shape.STRING)
@JSONField(serializeUsing = ToStringSerializer.class)
private String categoryId;
@Schema(name = "categoryName", title = "分类名称")
private String categoryName;
@Schema(name = "transactionDate", title = "交易日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime transactionDate;
}

View File

@ -0,0 +1,24 @@
package cn.bunny.dao.vo.financial.user.expendAndIncome;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "ExpendWithIncomeVo对象", title = "账单收入和支出", description = "账单收入和支出")
public class ExpendWithIncomeListVo {
@Schema(name = "list", title = "基础列表")
private List<ExpendWithIncome> list;
@Schema(name = "categoryList", title = "分类列表")
private List<CategoryAmount> categoryAmounts;
}

View File

@ -1,6 +1,7 @@
package cn.bunny.services.controller.financial;
import cn.bunny.dao.dto.financial.bill.BillDto;
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.user.BillAddUserDto;
@ -11,6 +12,7 @@ import cn.bunny.dao.pojo.result.Result;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
import cn.bunny.dao.vo.financial.admin.BillVo;
import cn.bunny.dao.vo.financial.user.BillUserVo;
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo;
import cn.bunny.services.service.financial.BillService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
@ -65,6 +67,13 @@ public class BillController {
return Mono.just(Result.success(pageResult));
}
@Operation(summary = "账单收入和支出", description = "账单收入和支出")
@GetMapping("noManage/getExpendOrIncome")
public Mono<Result<ExpendWithIncomeListVo>> getExpendOrIncome(ExpendWithIncomeDto dto) {
ExpendWithIncomeListVo vo = billService.getExpendOrIncome(dto);
return Mono.just(Result.success(vo));
}
@Operation(summary = "添加账单信息", description = "添加账单信息")
@PostMapping("addBill")
public Mono<Result<String>> addBill(@Valid @RequestBody BillAddDto dto) {

View File

@ -1,34 +0,0 @@
package cn.bunny.services.factory;
import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.vo.log.UserLoginLogVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class UserLoginLogFactory {
/**
* 用户登录日志分页查询通用方法
*
* @param page 分页结果
* @return 分页用户登录日志
*/
public PageResult<UserLoginLogVo> getUserLoginLogVoPageResult(IPage<UserLoginLogVo> page) {
List<UserLoginLogVo> voList = page.getRecords().stream().map(userLoginLog -> {
UserLoginLogVo userLoginLogVo = new UserLoginLogVo();
BeanUtils.copyProperties(userLoginLog, userLoginLogVo);
return userLoginLogVo;
}).toList();
return PageResult.<UserLoginLogVo>builder()
.list(voList)
.pageNo(page.getCurrent())
.pageSize(page.getSize())
.total(page.getTotal())
.build();
}
}

View File

@ -1,8 +1,10 @@
package cn.bunny.services.mapper.financial;
import cn.bunny.dao.dto.financial.bill.BillDto;
import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto;
import cn.bunny.dao.entity.financial.Bill;
import cn.bunny.dao.vo.financial.admin.BillVo;
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -37,4 +39,12 @@ public interface BillMapper extends BaseMapper<Bill> {
* @return 账单信息分页结果
*/
IPage<BillVo> selectListByPage(@Param("page") Page<Bill> pageParams, @Param("dto") BillDto dto);
/**
* 账单收入和支出
*
* @param dto 请求表单
* @return 账单收入和支出
*/
List<ExpendWithIncome> selectListByExpendWithIncomeDto(@Param("dto") ExpendWithIncomeDto dto);
}

View File

@ -23,6 +23,14 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher;
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {
public static String[] annotations = {
"/", "/ws/**",
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "/swagger-ui/**",
"/error", "/*/i18n/getI18n",
};
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@ -40,12 +48,6 @@ public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
String[] annotations = {
"/", "/ws/**",
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "swagger-ui/**",
"/error", "/*/i18n/getI18n",
};
httpSecurity
// 前端段分离不需要---禁用明文验证
.httpBasic(AbstractHttpConfigurer::disable)

View File

@ -0,0 +1,22 @@
package cn.bunny.services.security.custom;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
/**
* 处理与认证相关的异常
*/
@Getter
@ToString
@Slf4j
public class CustomAuthenticationException extends AuthenticationException {
ResultCodeEnum resultCodeEnum;
public CustomAuthenticationException(ResultCodeEnum codeEnum) {
super(codeEnum.getMessage());
this.resultCodeEnum = codeEnum;
}
}

View File

@ -3,6 +3,7 @@ package cn.bunny.services.security.handelr;
import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.dao.pojo.result.Result;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
import cn.bunny.services.security.custom.CustomAuthenticationException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@ -10,26 +11,20 @@ import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
/**
* 请求未认证接口
* 自定义请求未认证接口异常
*/
@Slf4j
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
String token = request.getHeader("token");
String message = authException.getMessage();
// 创建结果对象
Result<Object> result;
if (token == null) {
result = Result.error(ResultCodeEnum.LOGIN_AUTH);
log.info("请求未登录接口:{}用户id{}", message, null);
if (authException instanceof CustomAuthenticationException customException) {
result = Result.error(customException.getResultCodeEnum());
} else {
result = Result.error(ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE);
log.info("请求未授权接口:{}用户id{}", message, token);
result = Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED);
}
// 返回响应
ResponseUtil.out(response, result);
}
}

View File

@ -5,13 +5,14 @@ import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.dao.entity.system.Power;
import cn.bunny.dao.entity.system.Role;
import cn.bunny.dao.pojo.constant.RedisUserConstant;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
import cn.bunny.dao.vo.system.user.LoginVo;
import cn.bunny.services.mapper.system.PowerMapper;
import cn.bunny.services.mapper.system.RoleMapper;
import cn.bunny.services.security.custom.CustomAuthenticationException;
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
@ -44,21 +45,21 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@SneakyThrows
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
// 用户的token和用户id请求Url
HttpServletRequest request = context.getRequest();
// 判断是否有 token
String token = request.getHeader("token");
if (token == null) {
return new AuthorizationDecision(false);
throw new CustomAuthenticationException(ResultCodeEnum.LOGIN_AUTH);
}
// 判断 token 是否过期
if (JwtHelper.isExpired(token)) {
return new AuthorizationDecision(false);
throw new CustomAuthenticationException(ResultCodeEnum.AUTHENTICATION_EXPIRED);
}
// 解析JWT中的用户名
@ -71,12 +72,12 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
// 登录信息为空
if (loginVo == null) {
return new AuthorizationDecision(false);
throw new CustomAuthenticationException(ResultCodeEnum.LOGIN_AUTH);
}
// 判断用户是否禁用
if (loginVo.getStatus()) {
return new AuthorizationDecision(false);
throw new CustomAuthenticationException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED);
}
// 设置用户信息

View File

@ -1,6 +1,7 @@
package cn.bunny.services.service.financial;
import cn.bunny.dao.dto.financial.bill.BillDto;
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.user.BillAddUserDto;
@ -9,6 +10,7 @@ import cn.bunny.dao.entity.financial.Bill;
import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.vo.financial.admin.BillVo;
import cn.bunny.dao.vo.financial.user.BillUserVo;
import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
@ -79,4 +81,12 @@ public interface BillService extends IService<Bill> {
* @param dto 更新表单
*/
void updateUserBill(BillUpdateUserDto dto);
/**
* 账单收入和支出
*
* @param dto 请求表单
* @return 账单收入和支出
*/
ExpendWithIncomeListVo getExpendOrIncome(ExpendWithIncomeDto dto);
}

View File

@ -3,6 +3,7 @@ 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.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.user.BillAddUserDto;
@ -12,6 +13,9 @@ import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
import cn.bunny.dao.vo.financial.admin.BillVo;
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.mapper.financial.BillMapper;
import cn.bunny.services.service.financial.BillService;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -22,6 +26,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
@ -144,6 +149,41 @@ public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements Bi
updateById(bill);
}
/**
* 账单收入和支出
*
* @param dto 请求表单
* @return 账单收入和支出
*/
@Override
public ExpendWithIncomeListVo getExpendOrIncome(ExpendWithIncomeDto dto) {
// 判断请求用户id是否为空
if (dto.getUserId() == null) {
dto.setUserId(BaseContext.getUserId());
}
// 查询收入和支出
List<ExpendWithIncome> expendWithIncomeList = baseMapper.selectListByExpendWithIncomeDto(dto);
// 分类列表
List<CategoryAmount> categoryAmountList = expendWithIncomeList.stream()
.filter(expendWithIncome -> dto.getType() != null && expendWithIncome.getType().equals(dto.getType()))
.collect(Collectors.groupingBy(ExpendWithIncome::getCategoryName,
Collectors.summingDouble(expend -> expend.getAmount().doubleValue()))
).entrySet()
.stream().map(expendWithIncome -> {
CategoryAmount categoryAmount = new CategoryAmount();
categoryAmount.setCategoryName(expendWithIncome.getKey());
categoryAmount.setAmount(expendWithIncome.getValue());
return categoryAmount;
}).toList();
return ExpendWithIncomeListVo.builder()
.categoryAmounts(categoryAmountList)
.list(expendWithIncomeList)
.build();
}
/**
* 删除|批量删除账单信息
*

View File

@ -34,6 +34,7 @@ public class RolePowerServiceImpl extends ServiceImpl<RolePowerMapper, RolePower
@Autowired
private RoleFactory roleFactory;
@Autowired
private UserRoleMapper userRoleMapper;

View File

@ -6,14 +6,12 @@ import cn.bunny.dao.entity.log.UserLoginLog;
import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.vo.log.UserLoginLogLocalVo;
import cn.bunny.dao.vo.log.UserLoginLogVo;
import cn.bunny.services.factory.UserLoginLogFactory;
import cn.bunny.services.mapper.system.UserLoginLogMapper;
import cn.bunny.services.service.system.UserLoginLogService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -31,9 +29,6 @@ import java.util.List;
@Transactional
public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, UserLoginLog> implements UserLoginLogService {
@Autowired
private UserLoginLogFactory factory;
/**
* * 用户登录日志 服务实现类
*
@ -45,7 +40,18 @@ public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, Use
public PageResult<UserLoginLogVo> getUserLoginLogList(Page<UserLoginLog> pageParams, UserLoginLogDto dto) {
IPage<UserLoginLogVo> page = baseMapper.selectListByPage(pageParams, dto);
return factory.getUserLoginLogVoPageResult(page);
List<UserLoginLogVo> voList = page.getRecords().stream().map(userLoginLog -> {
UserLoginLogVo userLoginLogVo = new UserLoginLogVo();
BeanUtils.copyProperties(userLoginLog, userLoginLogVo);
return userLoginLogVo;
}).toList();
return PageResult.<UserLoginLogVo>builder()
.list(voList)
.pageNo(page.getCurrent())
.pageSize(page.getSize())
.total(page.getTotal())
.build();
}
/**

View File

@ -130,7 +130,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
Long userId = JwtHelper.getUserId(dto.getRefreshToken());
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
if (adminUser == null) throw new BunnyException(ResultCodeEnum.FAIL_REQUEST_NOT_AUTH);
if (adminUser == null) throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY);
if (adminUser.getStatus()) throw new BunnyException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED);
LoginVo buildUserVo = userFactory.buildLoginUserVo(adminUser, dto.getReadMeDay());

View File

@ -16,20 +16,20 @@ logging:
bunny:
master:
host: 192.168.3.98
host: 192.168.3.129
port: 3304
database: family_financial
username: root
password: "02120212"
redis:
host: 192.168.3.98
host: 192.168.3.129
port: 6379
database: 6
password: "123456"
minio:
endpointUrl: "http://192.168.3.98:9000"
endpointUrl: "http://192.168.3.129:9000"
accessKey: bunny
secretKey: "02120212"
bucket-name: financial

View File

@ -53,6 +53,24 @@
</where>
</select>
<!-- 账单收入和支出 -->
<select id="selectListByExpendWithIncomeDto" resultType="cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome">
select *
from t_bill b left join t_category tc on b.category_id = tc.id
<where>
<if test="dto.userId != null and dto.userId != ''">
and b.user_id = #{dto.userId}
</if>
<if test="dto.type != null">
and b.type = #{dto.type}
</if>
<if test="dto.startDate != null and dto.endDate != null">
and b.transaction_date between #{dto.startDate} and #{dto.endDate}
</if>
</where>
order by b.amount desc
</select>
<!-- 物理删除账单信息 -->
<delete id="deleteBatchIdsWithPhysics">
delete