feat:多钱包、电子饭卡、饭卡充值

This commit is contained in:
dzc committed 2024-12-30 17:24:34 +08:00
1 parent d684f1bc97
commit 0f6da3a679
40 files changed
+1781 -225

No files matched your search

+16 -2
View File
@@ -26,7 +26,7 @@
<!--mybatis plus extension,包含了mybatis plus core-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<artifactId>mybatis-plus-spring</artifactId>
</dependency>
<!--feign 工具类-->
<dependency>
@@ -38,5 +38,19 @@
<groupId>com.bsd</groupId>
<artifactId>pjcloud-common-excel</artifactId>
</dependency>
</dependencies>
<!--字段审计注解-->
<dependency>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
</dependency>
<!-- 脱敏工具类-->
<dependency>
<groupId>com.bsd</groupId>
<artifactId>pjcloud-common-sensitive</artifactId>
</dependency>
<dependency>
<groupId>com.bsd</groupId>
<artifactId>pjcloud-upms-api</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,28 @@
package com.bsd.pjcloud.wallet.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum WalletBizEnum {
UPDATE("1", "更新余额"),
BATCH("2", "批量更新余额"),
RECHARGE("3", "充值"),
;
private final String code;
private final String desc;
WalletBizEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static WalletBizEnum descOf(String description) {
return Arrays.stream(WalletBizEnum.values())
.filter(v -> ObjectUtil.equal(v.getDesc(), description))
.findFirst().get();
}
}
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.wallet.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum WalletTypeCodeEnum {
SUPERMARKET("1", "超市"),
CANTEEN("2", "食堂"),
;
private final String code;
private final String desc;
WalletTypeCodeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static WalletTypeCodeEnum descOf(String description) {
return Arrays.stream(WalletTypeCodeEnum.values())
.filter(v -> ObjectUtil.equal(v.getDesc(), description))
.findFirst().get();
}
}
@@ -0,0 +1,29 @@
package com.bsd.pjcloud.wallet.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum WalletTypeEnum {
EAT("1", "饭卡钱包"),
PAY("2", "虚拟钱包"),
;
private final String code;
private final String desc;
WalletTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static WalletTypeEnum descOf(String description) {
return Arrays.stream(WalletTypeEnum.values())
.filter(v -> ObjectUtil.equal(v.getDesc(), description))
.findFirst().get();
}
}
@@ -0,0 +1,12 @@
package com.bsd.pjcloud.wallet.api.dto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class WalletManageDto extends WalletManageEntity {
}
@@ -0,0 +1,140 @@
package com.bsd.pjcloud.wallet.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 钱包管理
*
* @author dzc
* @date 2024-12-30 09:06:35
*/
@Data
@TenantTable
@TableName("wallet_manage")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "钱包管理")
public class WalletManageEntity extends Model<WalletManageEntity> {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
/**
* 饭卡绑定的用户id
*/
@Schema(description = "饭卡绑定的用户id")
private Long userId;
/**
* 饭卡类型id
*/
@Schema(description = "饭卡类型id")
private Long walletTypeId;
/**
* 部门id
*/
@Schema(description = "部门id")
private Long deptId;
/**
* 饭卡卡号
*/
@Schema(description = "饭卡卡号")
private String cardNumber;
/**
* 余额,单位分
*/
@Schema(description = "余额,单位分")
private Integer balance;
/**
* 累计支出,单位分
*/
@Schema(description = "累计支出,单位分")
private Integer totalExpense;
/**
* 累计充值,单位分
*/
@Schema(description = "累计充值,单位分")
private Integer totalRecharge;
/**
* 冻结金额,单位分
*/
@Schema(description = "冻结金额,单位分")
private Integer freezePrice;
/**
* 是否冻结饭卡
*/
@Schema(description = "是否冻结饭卡")
private Boolean isFreeze;
/**
* 绑定饭卡时间
*/
@Schema(description = "绑定饭卡时间")
private LocalDateTime activeBindTime;
/**
* 饭卡绑定状态
*/
@Schema(description = "饭卡绑定状态")
private Integer activeBindStatus;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -0,0 +1,70 @@
package com.bsd.pjcloud.wallet.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 会员钱包流水表
*
* @author pjcloud
* @date 2024-12-30 09:17:49
*/
@Data
@TableName("wallet_transaction")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "会员钱包流水表")
public class WalletTransactionEntity extends Model<WalletTransactionEntity> {
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="编号")
private Long id;
/**
* 会员钱包 id
*/
@Schema(description="会员钱包 id")
private Long walletId;
/**
* 关联类型
*/
@Schema(description="关联类型")
private String bizType;
/**
* 关联业务编号
*/
@Schema(description="关联业务编号")
private String bizId;
/**
* 流水号
*/
@Schema(description="流水号")
private String no;
/**
* 流水标题
*/
@Schema(description="流水标题")
private String title;
/**
* 交易金额, 单位分
*/
@Schema(description="交易金额, 单位分")
private Integer price;
/**
* 余额, 单位分
*/
@Schema(description="余额, 单位分")
private Integer balance;
}
@@ -0,0 +1,91 @@
package com.bsd.pjcloud.wallet.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 钱包类型
*
* @author dzc
* @date 2024-12-30 09:13:18
*/
@Data
@TenantTable
@TableName("wallet_type")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "钱包类型")
public class WalletTypeEntity extends Model<WalletTypeEntity> {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="主键")
private Long id;
/**
* 钱包名
*/
@Schema(description="钱包名")
private String name;
/**
* 钱包图标
*/
@Schema(description="钱包图标")
private String icon;
/**
* 饭卡code
*/
@Schema(description="饭卡code")
private String uniqueCode;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description="删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description="租户ID")
private Long tenantId;
}
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.wallet.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "remoteWalletService", value = ServiceNameConstants.WALLET_SERVICE)
public interface RemoteWalletService {
@NoToken
@GetMapping("/wallet-manage/get-or-create-wallet")
R<WalletManageEntity> getOrCreateWallet(@RequestParam Long userId, @RequestParam(required = false) WalletTypeCodeEnum walletTypeCode);
@NoToken
@GetMapping("/wallet-manage/get-wallet")
R<WalletManageEntity> getWallet(@RequestParam Long userId, @RequestParam WalletTypeCodeEnum walletTypeCode);
@NoToken
@GetMapping("/wallet-manage/create-wallet")
R<Object> createWallet(@RequestParam Long userId);
}
@@ -0,0 +1,32 @@
package com.bsd.pjcloud.wallet.api.vo;
import com.bsd.pjcloud.admin.api.vo.base.BaseDeptInterface;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserInterface;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import lombok.Data;
@Data
public class WalletManageVo extends WalletManageEntity implements BaseUserInterface, BaseDeptInterface {
/**
* 钱包类型名
*/
private String walletTypeName;
private String walletTypeUniqueCode;
/**
* 用户相关
*/
private String username;
private String userMobile;
private String userAvatar;
/**
* 部门相关
*/
private String deptName;
}
@@ -0,0 +1 @@
com.bsd.pjcloud.wallet.api.feign.RemoteWalletService
@@ -0,0 +1,170 @@
package com.bsd.pjcloud.wallet.controller;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.admin.api.entity.SysUser;
import com.bsd.pjcloud.common.core.exception.ErrorCodes;
import com.bsd.pjcloud.common.core.util.MsgUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletManageDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.service.WalletManageService;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 钱包管理
*
* @author dzc
* @date 2024-12-30 09:06:35
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/wallet-manage")
@Tag(description = "walletManage", name = "钱包管理管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class WalletManageController {
private final WalletManageService walletManageService;
/* ************************************* start 远程调用 start ************************************* */
@Inner
@GetMapping("/get-or-create-wallet")
public R getOrCreateWallet(@RequestParam Long userId, @RequestParam WalletTypeCodeEnum walletTypeCode) {
WalletManageEntity wallet = walletManageService.getOrCreateWallet(userId, walletTypeCode);
if (ObjectUtil.isEmpty(wallet)) {
return R.failed("用户钱包不存在");
}
return R.ok(wallet);
}
@Inner
@GetMapping("/create-wallet")
public R getWallet(@RequestParam Long userId) {
walletManageService.createWallet(userId);
return R.ok();
}
@Inner
@GetMapping("/get-wallet")
public R getWallet(@RequestParam Long userId, @RequestParam WalletTypeCodeEnum walletTypeCode) {
WalletManageEntity wallet = walletManageService.getWallet(userId, walletTypeCode);
if (ObjectUtil.isEmpty(wallet)) {
return R.failed("用户钱包不存在");
}
return R.ok(wallet);
}
/* ************************************* start 远程调用 start ************************************* */
/**
* 分页查询
*
* @param page 分页对象
* @param walletManage 钱包管理
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_view')")
public R getWalletManagePage(@ParameterObject Page page, @ParameterObject WalletManageEntity walletManage) {
LambdaQueryWrapper<WalletManageEntity> wrapper = Wrappers.lambdaQuery();
return R.ok(walletManageService.page(page, wrapper));
}
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page-join")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_view')")
public R getWalletManagePageJoin(@ParameterObject Page page, @ParameterObject WalletManageDto dto) {
return walletManageService.pageJoin(page, dto);
}
/**
* 通过id查询钱包管理
*
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_view')")
public R getById(@PathVariable("id") Long id) {
return R.ok(walletManageService.getById(id));
}
/**
* 新增钱包管理
*
* @param walletManage 钱包管理
* @return R
*/
@Operation(summary = "新增钱包管理", description = "新增钱包管理")
@SysLog("新增钱包管理")
@PostMapping
@PreAuthorize("@pms.hasPermission('wallet_walletManage_add')")
public R save(@RequestBody WalletManageEntity walletManage) {
return R.ok(walletManageService.save(walletManage));
}
/**
* 修改钱包管理
*
* @param walletManage 钱包管理
* @return R
*/
@Operation(summary = "修改钱包管理", description = "修改钱包管理")
@SysLog("修改钱包管理")
@PutMapping
@PreAuthorize("@pms.hasPermission('wallet_walletManage_edit')")
public R updateById(@RequestBody WalletManageEntity walletManage) {
return R.ok(walletManageService.updateById(walletManage));
}
/**
* 通过id删除钱包管理
*
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除钱包管理", description = "通过id删除钱包管理")
@SysLog("通过id删除钱包管理")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('wallet_walletManage_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(walletManageService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
*
* @param walletManage 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_export')")
public List<WalletManageEntity> export(WalletManageEntity walletManage, Long[] ids) {
return walletManageService.list(Wrappers.lambdaQuery(walletManage).in(ArrayUtil.isNotEmpty(ids), WalletManageEntity::getId, ids));
}
}
@@ -0,0 +1,118 @@
package com.bsd.pjcloud.wallet.controller;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.service.WalletTransactionService;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 会员钱包流水表
*
* @author pjcloud
* @date 2024-12-30 09:17:49
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/walletTransaction" )
@Tag(description = "walletTransaction" , name = "会员钱包流水表管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class WalletTransactionController {
private final WalletTransactionService walletTransactionService;
/**
* 分页查询
* @param page 分页对象
* @param walletTransaction 会员钱包流水表
* @return
*/
@Operation(summary = "分页查询" , description = "分页查询" )
@GetMapping("/page" )
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_view')" )
public R getWalletTransactionPage(@ParameterObject Page page, @ParameterObject WalletTransactionEntity walletTransaction) {
LambdaQueryWrapper<WalletTransactionEntity> wrapper = Wrappers.lambdaQuery();
return R.ok(walletTransactionService.page(page, wrapper));
}
/**
* 通过id查询会员钱包流水表
* @param id id
* @return R
*/
@Operation(summary = "通过id查询" , description = "通过id查询" )
@GetMapping("/{id}" )
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_view')" )
public R getById(@PathVariable("id" ) Long id) {
return R.ok(walletTransactionService.getById(id));
}
/**
* 新增会员钱包流水表
* @param walletTransaction 会员钱包流水表
* @return R
*/
@Operation(summary = "新增会员钱包流水表" , description = "新增会员钱包流水表" )
@SysLog("新增会员钱包流水表" )
@PostMapping
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_add')" )
public R save(@RequestBody WalletTransactionEntity walletTransaction) {
return R.ok(walletTransactionService.save(walletTransaction));
}
/**
* 修改会员钱包流水表
* @param walletTransaction 会员钱包流水表
* @return R
*/
@Operation(summary = "修改会员钱包流水表" , description = "修改会员钱包流水表" )
@SysLog("修改会员钱包流水表" )
@PutMapping
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_edit')" )
public R updateById(@RequestBody WalletTransactionEntity walletTransaction) {
return R.ok(walletTransactionService.updateById(walletTransaction));
}
/**
* 通过id删除会员钱包流水表
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除会员钱包流水表" , description = "通过id删除会员钱包流水表" )
@SysLog("通过id删除会员钱包流水表" )
@DeleteMapping
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_del')" )
public R removeById(@RequestBody Long[] ids) {
return R.ok(walletTransactionService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
* @param walletTransaction 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_export')" )
public List<WalletTransactionEntity> export(WalletTransactionEntity walletTransaction,Long[] ids) {
return walletTransactionService.list(Wrappers.lambdaQuery(walletTransaction).in(ArrayUtil.isNotEmpty(ids), WalletTransactionEntity::getId, ids));
}
}
@@ -0,0 +1,119 @@
package com.bsd.pjcloud.wallet.controller;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.service.WalletTypeService;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 钱包类型
*
* @author dzc
* @date 2024-12-30 09:13:18
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/walletType" )
@Tag(description = "walletType" , name = "钱包类型管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class WalletTypeController {
private final WalletTypeService walletTypeService;
/**
* 分页查询
* @param page 分页对象
* @param walletType 钱包类型
* @return
*/
@Operation(summary = "分页查询" , description = "分页查询" )
@GetMapping("/page" )
@PreAuthorize("@pms.hasPermission('wallet_walletType_view')" )
public R getWalletTypePage(@ParameterObject Page page, @ParameterObject WalletTypeEntity walletType) {
LambdaQueryWrapper<WalletTypeEntity> wrapper = Wrappers.lambdaQuery();
return R.ok(walletTypeService.page(page, wrapper));
}
/**
* 通过id查询钱包类型
* @param id id
* @return R
*/
@Operation(summary = "通过id查询" , description = "通过id查询" )
@GetMapping("/{id}" )
@PreAuthorize("@pms.hasPermission('wallet_walletType_view')" )
public R getById(@PathVariable("id" ) Long id) {
return R.ok(walletTypeService.getById(id));
}
/**
* 新增钱包类型
* @param walletType 钱包类型
* @return R
*/
@Operation(summary = "新增钱包类型" , description = "新增钱包类型" )
@SysLog("新增钱包类型" )
@PostMapping
@PreAuthorize("@pms.hasPermission('wallet_walletType_add')" )
public R save(@RequestBody WalletTypeEntity walletType) {
return R.ok(walletTypeService.save(walletType));
}
/**
* 修改钱包类型
* @param walletType 钱包类型
* @return R
*/
@Operation(summary = "修改钱包类型" , description = "修改钱包类型" )
@SysLog("修改钱包类型" )
@PutMapping
@PreAuthorize("@pms.hasPermission('wallet_walletType_edit')" )
public R updateById(@RequestBody WalletTypeEntity walletType) {
return R.ok(walletTypeService.updateById(walletType));
}
/**
* 通过id删除钱包类型
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除钱包类型" , description = "通过id删除钱包类型" )
@SysLog("通过id删除钱包类型" )
@DeleteMapping
@PreAuthorize("@pms.hasPermission('wallet_walletType_del')" )
public R removeById(@RequestBody Long[] ids) {
return R.ok(walletTypeService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
* @param walletType 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('wallet_walletType_export')" )
public List<WalletTypeEntity> export(WalletTypeEntity walletType,Long[] ids) {
return walletTypeService.list(Wrappers.lambdaQuery(walletType).in(ArrayUtil.isNotEmpty(ids), WalletTypeEntity::getId, ids));
}
}
@@ -0,0 +1,43 @@
package com.bsd.pjcloud.wallet.mapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.wallet.api.dto.WalletManageDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletManageVo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface WalletManageMapper extends PjcloudBaseMapper<WalletManageEntity> {
default int updateWhenConsumption(Long id, Integer price) {
LambdaUpdateWrapper<WalletManageEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<WalletManageEntity>()
.setSql(" balance = balance - " + price + ", total_expense = total_expense + " + price)
.eq(WalletManageEntity::getId, id)
.ge(WalletManageEntity::getBalance, price);
return update(null, lambdaUpdateWrapper);
}
default int updateWhenRecharge(Long id, Integer price) {
LambdaUpdateWrapper<WalletManageEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<WalletManageEntity>()
.setSql(" balance = balance + " + price + ", total_recharge = total_recharge + " + price)
.eq(WalletManageEntity::getId, id);
return update(null, lambdaUpdateWrapper);
}
default Page<WalletManageVo> pageJoin(Page<WalletManageVo> page, @Param("pa") WalletManageDto dto) {
MPJLambdaWrapper<WalletManageEntity> wrapper = new MPJLambdaWrapper<WalletManageEntity>()
.selectAll(WalletManageEntity.class)
.selectAs(WalletTypeEntity::getName, WalletManageVo::getWalletTypeName)
.selectAs(WalletTypeEntity::getUniqueCode, WalletManageVo::getWalletTypeUniqueCode)
.leftJoin(WalletTypeEntity.class, WalletTypeEntity::getId, WalletManageEntity::getWalletTypeId)
.eqIfExists(WalletManageEntity::getUserId, dto.getUserId())
.eqIfExists(WalletManageEntity::getWalletTypeId, dto.getWalletTypeId())
.eqIfExists(WalletManageEntity::getIsFreeze, dto.getIsFreeze())
.likeIfExists(WalletManageEntity::getCardNumber, dto.getCardNumber());
return selectJoinPage(page, WalletManageVo.class, wrapper);
}
}
@@ -0,0 +1,12 @@
package com.bsd.pjcloud.wallet.mapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WalletTransactionMapper extends PjcloudBaseMapper<WalletTransactionEntity> {
}
@@ -0,0 +1,11 @@
package com.bsd.pjcloud.wallet.mapper;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WalletTypeMapper extends PjcloudBaseMapper<WalletTypeEntity> {
}
@@ -0,0 +1,52 @@
package com.bsd.pjcloud.wallet.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletManageDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import jakarta.validation.constraints.NotNull;
public interface WalletManageService extends IService<WalletManageEntity> {
/**
* 创建钱包
*
* @param userId
* @param checkPermission
*/
void createWallet(@NotNull Long userId, @NotNull Boolean checkPermission);
/**
* 创建钱包
*
* @param userId
*/
void createWallet(@NotNull Long userId);
/**
* 获取钱包没有就创建用户钱包(没有缓存)
*
* @param userId
*/
WalletManageEntity getOrCreateWallet(@NotNull Long userId, @NotNull WalletTypeCodeEnum walletTypeCode);
/**
* 获取钱包(有缓存)
* @param userId
* @param walletTypeCode
* @return
*/
WalletManageEntity getWallet(@NotNull Long userId, @NotNull WalletTypeCodeEnum walletTypeCode);
/**
* 分页连表查询
*
* @param page
* @param dto
* @return
*/
R pageJoin(Page page, WalletManageDto dto);
}
@@ -0,0 +1,32 @@
package com.bsd.pjcloud.wallet.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
public interface WalletTransactionService extends IService<WalletTransactionEntity> {
/**
* 扣减钱包余额
*
* @param walletId 钱包 id
* @param price 扣减金额
* @param bizId 业务关联 id
* @param bizType 业务关联分类
* @return 钱包流水
*/
WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, Long bizId, WalletBizEnum bizType);
/**
* 增加钱包余额
*
* @param walletId 钱包 id
* @param price 增加金额
* @param bizId 业务关联 id
* @param bizType 业务关联分类
* @return 钱包流水
*/
WalletTransactionEntity addWalletBalance(Long walletId, Integer price, String bizId, WalletBizEnum bizType);
}
@@ -0,0 +1,13 @@
package com.bsd.pjcloud.wallet.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import java.io.Serializable;
public interface WalletTypeService extends IService<WalletTypeEntity> {
WalletTypeEntity getByUniqueCode(WalletTypeCodeEnum walletTypeCodeEnum);
}
@@ -0,0 +1,144 @@
package com.bsd.pjcloud.wallet.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
import com.bsd.pjcloud.admin.api.entity.SysDept;
import com.bsd.pjcloud.admin.api.entity.SysUser;
import com.bsd.pjcloud.admin.api.feign.RemoteDeptService;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.resolver.ParamResolver;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletManageDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletManageVo;
import com.bsd.pjcloud.wallet.mapper.WalletManageMapper;
import com.bsd.pjcloud.wallet.mapper.WalletTypeMapper;
import com.bsd.pjcloud.wallet.service.WalletManageService;
import com.bsd.pjcloud.wallet.service.WalletTypeService;
import com.bsd.pjcloud.wallet.utils.ConvertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import java.util.stream.Collectors;
/**
* 钱包管理
*
* @author dzc
* @date 2024-12-30 09:06:35
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class WalletManageServiceImpl extends ServiceImpl<WalletManageMapper, WalletManageEntity> implements WalletManageService {
static private final String TAG = "钱包管理";
private final WalletTypeMapper walletTypeMapper;
private final WalletTypeService walletTypeService;
private final RemoteUserService userService;
private final RemoteDeptService deptService;
@Override
@Transactional(rollbackFor = Exception.class)
public void createWallet(Long userId, Boolean checkPermission) {
UserInfo user = null;
if (checkPermission) {
user = userService.getByUserId(userId).getData();
if (ObjectUtil.isEmpty(user)) {
log.info("|{}|创建用户电子钱包失败,userId:{},用户id不存在", TAG, userId);
return;
}
String role = Arrays.stream(user.getRoleCodes()).filter(v -> ObjectUtil.equals(v, ParamResolver.getStr("WALLET_AUTO_CREATE"))).findFirst().get();
if (ObjectUtil.isEmpty(role)) {
log.info("|{}|创建用户电子钱包失败,userId:{},没有{}权限", TAG, userId, "WALLET_AUTO_CREATE");
return;
}
}
List<WalletTypeEntity> list = walletTypeMapper.selectList(new LambdaQueryWrapper<>());
if (ObjectUtil.isEmpty(list)) return;
if (ObjectUtil.isEmpty(user)) user = userService.getByUserId(userId).getData();
for (WalletTypeEntity v : list) {
WalletManageEntity wallet = baseMapper.selectOne(new LambdaQueryWrapper<WalletManageEntity>()
.eq(WalletManageEntity::getUserId, userId)
.eq(WalletManageEntity::getWalletTypeId, v.getId())
);
if (ObjectUtil.isNotEmpty(wallet)) continue;
WalletManageEntity insertObj = new WalletManageEntity();
insertObj.setUserId(userId);
insertObj.setWalletTypeId(v.getId());
insertObj.setDeptId(user.getSysUser().getDeptId());
baseMapper.insert(insertObj);
}
}
@Override
public void createWallet(Long userId) {
getSelf().createWallet(userId, true);
}
@Override
@CachePut(value = CacheConstants.WALLET_DETAIL, key = "#userId-#walletTypeCode.name()", unless = "#result == null ")
public WalletManageEntity getOrCreateWallet(Long userId, WalletTypeCodeEnum walletTypeCode) {
WalletTypeEntity walletType = walletTypeService.getByUniqueCode(walletTypeCode);
if (ObjectUtil.isEmpty(walletType)) return null;
LambdaQueryWrapper<WalletManageEntity> walletQuery = new LambdaQueryWrapper<WalletManageEntity>().eq(WalletManageEntity::getUserId, userId).eq(WalletManageEntity::getWalletTypeId, walletType.getId());
WalletManageEntity wallet = baseMapper.selectOne(walletQuery);
if (ObjectUtil.isEmpty(wallet)) createWallet(userId);
return baseMapper.selectOne(walletQuery);
}
@Override
@Cacheable(value = CacheConstants.WALLET_DETAIL, key = "#userId-#walletTypeCode.name()", unless = "#result == null ")
public WalletManageEntity getWallet(Long userId, WalletTypeCodeEnum walletTypeCode) {
WalletTypeEntity walletType = walletTypeService.getByUniqueCode(walletTypeCode);
if (ObjectUtil.isEmpty(walletType)) return null;
return baseMapper.selectOne(new LambdaQueryWrapper<WalletManageEntity>()
.eq(WalletManageEntity::getUserId, userId)
.eq(WalletManageEntity::getWalletTypeId, walletType.getId())
);
}
@Override
public R pageJoin(Page page, WalletManageDto dto) {
Page<WalletManageVo> list = baseMapper.pageJoin(page, dto);
if (ObjectUtil.isNotEmpty(list.getRecords())) {
// 用户
List<Long> userIds = list.getRecords().stream().map(WalletManageVo::getUserId).distinct().toList();
R<List<SysUser>> userList = userService.getUserById(new ArrayList<>(userIds));
if (ObjectUtil.isNotEmpty(userList.getData())) {
DataUtil.convertUserList(page.getRecords(), CollectionUtils.convertMap(userList.getData(), SysUser::getUserId));
}
// 部门
List<Long> deptIds = list.getRecords().stream().map(WalletManageVo::getDeptId).distinct().toList();
R<Map<Long, SysDept>> deptList = deptService.getDeptByDeptIds(deptIds);
if (ObjectUtil.isNotEmpty(deptList.getData())) {
DataUtil.convertDeptList(page.getRecords(), deptList.getData());
}
}
return R.ok(list);
}
private WalletManageServiceImpl getSelf() {
return SpringUtil.getBean(getClass());
}
}
@@ -0,0 +1,98 @@
package com.bsd.pjcloud.wallet.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.exception.CheckedException;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.mapper.WalletManageMapper;
import com.bsd.pjcloud.wallet.mapper.WalletTransactionMapper;
import com.bsd.pjcloud.wallet.service.WalletManageService;
import com.bsd.pjcloud.wallet.service.WalletTransactionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
/**
* 会员钱包流水表
*
* @author pjcloud
* @date 2024-12-30 09:17:49
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionMapper, WalletTransactionEntity> implements WalletTransactionService {
static private final String TAG = "会员钱包流水";
private final WalletManageService walletManageService;
private final WalletManageMapper walletManageMapper;
@Override
public boolean save(WalletTransactionEntity entity) {
return baseMapper.insert(entity) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, Long bizId, WalletBizEnum bizType) {
WalletManageEntity wallet = walletManageService.getById(walletId);
if (ObjectUtil.isEmpty(wallet)) {
log.error("|{}|,用户钱包id({})不存在.", TAG, walletId);
throw new CheckedException("扣款失败,用户钱包不存在");
}
int updateCounts = walletManageMapper.updateWhenConsumption(wallet.getId(), price);
if (updateCounts == 0) {
log.error("|{}|,用户钱包id({})余额不足.", TAG, walletId);
throw new CheckedException("钱包余额不足");
}
Integer afterBalance = wallet.getBalance() - price;
WalletTransactionEntity insetObj = new WalletTransactionEntity();
insetObj.setWalletId(walletId);
insetObj.setPrice(-price);
insetObj.setBalance(afterBalance);
insetObj.setBizId(String.valueOf(bizId));
insetObj.setBizType(bizType.getCode());
insetObj.setTitle(bizType.getDesc());
save(insetObj);
return insetObj;
}
@Override
@Transactional(rollbackFor = Exception.class)
public WalletTransactionEntity addWalletBalance(Long walletId, Integer price, String bizId, WalletBizEnum bizType) {
WalletManageEntity wallet = walletManageService.getById(walletId);
if (ObjectUtil.isEmpty(wallet)) {
log.error("|{}|,用户钱包id({})不存在.", TAG, walletId);
throw new CheckedException("扣款失败,用户钱包不存在");
}
switch (bizType) {
case UPDATE:
case BATCH:
case RECHARGE: {
walletManageMapper.updateWhenRecharge(wallet.getId(), price);
break;
}
default: {
log.error("|{}|,钱包id({})使用未实现的增加钱包余额的类型({}).", TAG, walletId, bizType.getDesc());
throw new UnsupportedOperationException("待实现");
}
}
WalletTransactionEntity insetObj = new WalletTransactionEntity();
insetObj.setWalletId(walletId);
insetObj.setPrice(-price);
insetObj.setBalance(wallet.getBalance() + price);
insetObj.setBizId(String.valueOf(bizId));
insetObj.setBizType(bizType.getCode());
insetObj.setTitle(bizType.getDesc());
save(insetObj);
return insetObj;
}
}
@@ -0,0 +1,37 @@
package com.bsd.pjcloud.wallet.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.mapper.WalletTypeMapper;
import com.bsd.pjcloud.wallet.service.WalletTypeService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.io.Serializable;
/**
* 钱包类型
*
* @author dzc
* @date 2024-12-30 09:13:18
*/
@Service
public class WalletTypeServiceImpl extends ServiceImpl<WalletTypeMapper, WalletTypeEntity> implements WalletTypeService {
@Override
public WalletTypeEntity getById(Serializable id) {
return super.getById(id);
}
@Override
public WalletTypeEntity getByUniqueCode(WalletTypeCodeEnum walletTypeCodeEnum) {
return baseMapper.selectOne(new LambdaQueryWrapper<WalletTypeEntity>()
.eq(WalletTypeEntity::getUniqueCode, walletTypeCodeEnum.getCode())
);
}
}
@@ -0,0 +1,11 @@
package com.bsd.pjcloud.wallet.utils;
import lombok.experimental.UtilityClass;
import java.util.List;
import java.util.Map;
@UtilityClass
public class ConvertUtil {
}
@@ -9,7 +9,7 @@ spring:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: 123.156.230.15:8848
server-addr: ${NACOS_HOST:pjcloud-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
@@ -0,0 +1,26 @@
<?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.WalletManageMapper">
<resultMap id="walletManageMap" type="com.bsd.pjcloud.wallet.api.entity.WalletManageEntity">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="walletTypeId" column="wallet_type_id"/>
<result property="cardNumber" column="card_number"/>
<result property="balance" column="balance"/>
<result property="totalExpense" column="total_expense"/>
<result property="totalRecharge" column="total_recharge"/>
<result property="freezePrice" column="freeze_price"/>
<result property="isFreeze" column="is_freeze"/>
<result property="activeBindTime" column="active_bind_time"/>
<result property="activeBindStatus" column="active_bind_status"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,16 @@
<?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.WalletTransactionMapper">
<resultMap id="walletTransactionMap" type="com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity">
<id property="id" column="id"/>
<result property="walletId" column="wallet_id"/>
<result property="bizType" column="biz_type"/>
<result property="bizId" column="biz_id"/>
<result property="no" column="no"/>
<result property="title" column="title"/>
<result property="price" column="price"/>
<result property="balance" column="balance"/>
</resultMap>
</mapper>
@@ -0,0 +1,18 @@
<?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.WalletTypeMapper">
<resultMap id="walletTypeMap" type="com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="icon" column="icon"/>
<result property="uniqueCode" column="unique_code"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>