wallet用户工资账户功能完善

This commit is contained in:
tianfeng 2025-11-18 15:45:45 +08:00
parent 63a0b87066
commit 6a4786e30c
27 changed files with 790 additions and 65 deletions

View File

@ -0,0 +1,13 @@
package com.red.circle.wallet.inner.endpoint.salary;
import com.red.circle.wallet.inner.endpoint.salary.api.UserSalaryAccountClientApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @author pengliang on 2023/5/26
*/
@FeignClient(name = "userSalaryAccountClient", url = "${feign.wallet.url}" +
UserSalaryAccountClientApi.API_PREFIX)
public interface UserSalaryAccountClient extends UserSalaryAccountClientApi {
}

View File

@ -0,0 +1,47 @@
package com.red.circle.wallet.inner.endpoint.salary.api;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 工资账户 Client API.
*/
public interface UserSalaryAccountClientApi {
String API_PREFIX = "/user-salary-account/client";
/**
* 查询余额.
*/
@GetMapping("/balance")
ResultResponse<SalaryAccountBalanceDTO> getBalance(@RequestParam("userId") Long userId);
/**
* 发放工资.
*/
@PostMapping("/issue")
ResultResponse<SalaryIssueResultDTO> issueSalary(@RequestBody SalaryIssueInnerCmd cmd);
/**
* 提现.
*/
@PostMapping("/withdraw")
ResultResponse<Void> withdrawSalary(@RequestBody SalaryWithdrawInnerCmd cmd);
/**
* 查询流水.
*/
@PostMapping("/running-water")
ResultResponse<PageResult<SalaryRunningWaterDTO>> queryRunningWater(
@RequestBody SalaryRunningWaterQueryInnerCmd cmd);
}

View File

@ -0,0 +1,83 @@
package com.red.circle.wallet.inner.model.cmd;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
/**
* 发放工资命令Inner.
*/
@Data
public class SalaryIssueInnerCmd implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID.
*/
@NotNull(message = "userId required.")
private Long userId;
/**
* 系统来源.
*/
private String sysOrigin;
/**
* 工资类型.
*/
@NotBlank(message = "salaryType required.")
private String salaryType;
/**
* 发放金额.
*/
@NotNull(message = "amount required.")
@DecimalMin(value = "0.01", message = "amount must > 0")
private BigDecimal amount;
/**
* 账单归属YYYYMM.
*/
@NotNull(message = "billBelong required.")
private Integer billBelong;
/**
* 业务单号.
*/
@NotBlank(message = "trackId required.")
private String trackId;
/**
* 团队ID.
*/
private Long teamId;
/**
* BD ID.
*/
private Long bdId;
/**
* 代理ID.
*/
private Long agentId;
/**
* 事件描述.
*/
private String eventDesc;
/**
* 备注.
*/
private String remark;
/**
* 操作用户ID.
*/
private Long opUserId;
}

View File

@ -0,0 +1,53 @@
package com.red.circle.wallet.inner.model.cmd;
import java.io.Serializable;
import lombok.Data;
/**
* 工资流水查询命令Inner.
*/
@Data
public class SalaryRunningWaterQueryInnerCmd implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID.
*/
private Long userId;
/**
* 工资类型.
*/
private String salaryType;
/**
* 收支类型 0.收入 1.支出.
*/
private Integer type;
/**
* 账单归属YYYYMM.
*/
private Integer billBelong;
/**
* 开始时间.
*/
private String startTime;
/**
* 结束时间.
*/
private String endTime;
/**
* 页码.
*/
private Integer pageNum = 1;
/**
* 页大小.
*/
private Integer pageSize = 10;
}

View File

@ -0,0 +1,56 @@
package com.red.circle.wallet.inner.model.cmd;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
/**
* 提现命令Inner.
*/
@Data
public class SalaryWithdrawInnerCmd implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID.
*/
@NotNull(message = "userId required.")
private Long userId;
/**
* 系统来源.
*/
private String sysOrigin;
/**
* 提现金额.
*/
@NotNull(message = "amount required.")
@DecimalMin(value = "0.01", message = "amount must > 0")
private BigDecimal amount;
/**
* 业务单号.
*/
@NotBlank(message = "trackId required.")
private String trackId;
/**
* 手续费比例千分比.
*/
private Long serviceCharge;
/**
* 备注.
*/
private String remark;
/**
* 操作用户ID.
*/
private Long opUserId;
}

View File

@ -0,0 +1,50 @@
package com.red.circle.wallet.inner.model.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Data;
/**
* 工资账户余额 DTO.
*/
@Data
public class SalaryAccountBalanceDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID.
*/
private Long userId;
/**
* 累计收入.
*/
private BigDecimal earnPoints;
/**
* 累计支出.
*/
private BigDecimal consumptionPoints;
/**
* 当前余额.
*/
private BigDecimal balance;
/**
* 冻结金额.
*/
private BigDecimal frozenAmount;
/**
* 可用余额.
*/
private BigDecimal availableBalance;
/**
* 更新时间.
*/
private LocalDateTime updatedAt;
}

View File

@ -0,0 +1,34 @@
package com.red.circle.wallet.inner.model.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
/**
* 工资发放结果 DTO.
*/
@Data
public class SalaryIssueResultDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 流水记录ID.
*/
private Long recordId;
/**
* 发放金额.
*/
private BigDecimal amount;
/**
* 变动后余额.
*/
private BigDecimal balance;
/**
* 变动后可用余额.
*/
private BigDecimal availableBalance;
}

View File

@ -0,0 +1,100 @@
package com.red.circle.wallet.inner.model.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Data;
/**
* 工资流水 DTO.
*/
@Data
public class SalaryRunningWaterDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 流水ID.
*/
private Long id;
/**
* 用户ID.
*/
private Long userId;
/**
* 收支类型 0.收入 1.支出.
*/
private Integer type;
/**
* 工资类型.
*/
private String salaryType;
/**
* 工资类型名称.
*/
private String salaryTypeName;
/**
* 变动金额.
*/
private BigDecimal amount;
/**
* 变动后余额.
*/
private BigDecimal balance;
/**
* 变动后可用余额.
*/
private BigDecimal availableBalance;
/**
* 工资事件.
*/
private String salaryEvent;
/**
* 事件描述.
*/
private String eventDesc;
/**
* 业务单号.
*/
private String trackId;
/**
* 账单归属YYYYMM.
*/
private Integer billBelong;
/**
* 团队ID.
*/
private Long teamId;
/**
* BD ID.
*/
private Long bdId;
/**
* 代理ID.
*/
private Long agentId;
/**
* 备注.
*/
private String remark;
/**
* 创建时间.
*/
private LocalDateTime createdAt;
}

View File

@ -1,5 +1,6 @@
package com.red.circle.wallet.adapter.app;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.web.controller.BaseController;
import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO;
@ -32,8 +33,8 @@ public class SalaryAccountRestController extends BaseController {
* 查询余额.
*/
@GetMapping("/balance")
public SalaryAccountBalanceCO getBalance(@RequestParam Long userId) {
return salaryAccountService.getBalance(userId);
public SalaryAccountBalanceCO getBalance(AppExtCommand cmd) {
return salaryAccountService.getBalance(cmd.getReqUserId());
}
/**

View File

@ -1,5 +1,7 @@
package com.red.circle.wallet.app.command.salary.query;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.wallet.app.convertor.SalaryAccountConvertor;
import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance;
@ -20,9 +22,9 @@ public class SalaryAccountBalanceQryExe {
private final SalaryAccountConvertor salaryAccountConvertor;
public SalaryAccountBalanceCO execute(Long userId) {
SalaryAccountBalance balance = salaryAccountBalanceService.lambdaQuery()
.eq(SalaryAccountBalance::getUserId, userId)
.one();
LambdaQueryWrapper<SalaryAccountBalance> eq = Wrappers.lambdaQuery(SalaryAccountBalance.class)
.eq(SalaryAccountBalance::getUserId, userId);
SalaryAccountBalance balance = salaryAccountBalanceService.getOne(eq);
if (Objects.isNull(balance)) {
// 账户不存在返回空余额

View File

@ -92,9 +92,6 @@ public class SalaryAccountConvertor {
co.setBalance(entity.getBalance());
co.setFrozenAmount(entity.getFrozenAmount());
co.setAvailableBalance(entity.getAvailableBalance());
co.setUpdatedAt(TimeConvertUtils.toLocalDateTime(entity.getUpdateTime()));
return co;
}

View File

@ -39,9 +39,4 @@ public class SalaryAccountBalanceCO {
* 可用余额.
*/
private BigDecimal availableBalance;
/**
* 更新时间.
*/
private LocalDateTime updatedAt;
}

View File

@ -1,6 +1,7 @@
package com.red.circle.wallet.infra.database.rds.dao.salary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -8,8 +9,7 @@ import org.apache.ibatis.annotations.Param;
/**
* 工资账户余额 Mapper.
*/
@Mapper
public interface SalaryAccountBalanceMapper extends BaseMapper<SalaryAccountBalance> {
public interface SalaryAccountBalanceDAO extends BaseDAO<SalaryAccountBalance> {
/**
* 增加收入累计.

View File

@ -0,0 +1,11 @@
package com.red.circle.wallet.infra.database.rds.dao.salary;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
/**
* 工资账户流水 Mapper.
*/
public interface SalaryAccountRunningWaterDAO extends BaseDAO<SalaryAccountRunningWater> {
}

View File

@ -1,13 +0,0 @@
package com.red.circle.wallet.infra.database.rds.dao.salary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
import org.apache.ibatis.annotations.Mapper;
/**
* 工资账户流水 Mapper.
*/
@Mapper
public interface SalaryAccountRunningWaterMapper extends BaseMapper<SalaryAccountRunningWater> {
}

View File

@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.Version;
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@ -19,10 +21,7 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_salary_account_balance")
public class SalaryAccountBalance extends TimestampBaseEntity {
@Serial
private static final long serialVersionUID = 1L;
public class SalaryAccountBalance {
/**
* 主键标识.
@ -78,4 +77,9 @@ public class SalaryAccountBalance extends TimestampBaseEntity {
@Version
@TableField("version")
private Integer version;
private Timestamp createTime;
private Timestamp updateTime;
}

View File

@ -1,9 +1,6 @@
package com.red.circle.wallet.infra.database.rds.entity.salary;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.io.Serial;
import java.math.BigDecimal;

View File

@ -1,12 +1,12 @@
package com.red.circle.wallet.infra.database.rds.service.salary;
import com.baomidou.mybatisplus.extension.service.IService;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance;
/**
* 工资账户余额服务.
*/
public interface SalaryAccountBalanceService extends IService<SalaryAccountBalance> {
public interface SalaryAccountBalanceService extends BaseService<SalaryAccountBalance> {
/**
* 初始化账户.

View File

@ -1,11 +1,12 @@
package com.red.circle.wallet.infra.database.rds.service.salary;
import com.baomidou.mybatisplus.extension.service.IService;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
/**
* 工资账户流水服务.
*/
public interface SalaryAccountRunningWaterService extends IService<SalaryAccountRunningWater> {
public interface SalaryAccountRunningWaterService extends BaseService<SalaryAccountRunningWater> {
}

View File

@ -1,8 +1,11 @@
package com.red.circle.wallet.infra.database.rds.service.salary.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountBalanceMapper;
import com.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountBalanceDAO;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance;
import com.red.circle.wallet.infra.database.rds.service.salary.SalaryAccountBalanceService;
import java.math.BigDecimal;
@ -16,9 +19,11 @@ import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class SalaryAccountBalanceServiceImpl
extends ServiceImpl<SalaryAccountBalanceMapper, SalaryAccountBalance>
extends BaseServiceImpl<SalaryAccountBalanceDAO, SalaryAccountBalance>
implements SalaryAccountBalanceService {
private final SalaryAccountBalanceDAO salaryAccountBalanceDAO;
@Override
public void init(String sysOrigin, Long userId) {
SalaryAccountBalance balance = new SalaryAccountBalance()
@ -36,9 +41,9 @@ public class SalaryAccountBalanceServiceImpl
@Override
public Long getBalance(Long userId) {
SalaryAccountBalance balance = lambdaQuery()
.eq(SalaryAccountBalance::getUserId, userId)
.one();
LambdaQueryWrapper<SalaryAccountBalance> eq = Wrappers.lambdaQuery(SalaryAccountBalance.class)
.eq(SalaryAccountBalance::getUserId, userId);
SalaryAccountBalance balance = getOne(eq);
if (Objects.isNull(balance)) {
return 0L;
}
@ -47,9 +52,9 @@ public class SalaryAccountBalanceServiceImpl
@Override
public Long getAvailableBalance(Long userId) {
SalaryAccountBalance balance = lambdaQuery()
.eq(SalaryAccountBalance::getUserId, userId)
.one();
LambdaQueryWrapper<SalaryAccountBalance> eq = Wrappers.lambdaQuery(SalaryAccountBalance.class)
.eq(SalaryAccountBalance::getUserId, userId);
SalaryAccountBalance balance = getOne(eq);
if (Objects.isNull(balance)) {
return 0L;
}
@ -58,21 +63,21 @@ public class SalaryAccountBalanceServiceImpl
@Override
public boolean incrIncome(Long userId, Long amount) {
return baseMapper.incrIncome(userId, amount) > 0;
return salaryAccountBalanceDAO.incrIncome(userId, amount) > 0;
}
@Override
public boolean incrExpenditure(Long userId, Long amount) {
return baseMapper.incrExpenditure(userId, amount) > 0;
return salaryAccountBalanceDAO.incrExpenditure(userId, amount) > 0;
}
@Override
public boolean freezeAmount(Long userId, Long amount, Integer version) {
return baseMapper.freezeAmount(userId, amount, version) > 0;
return salaryAccountBalanceDAO.freezeAmount(userId, amount, version) > 0;
}
@Override
public boolean unfreezeAmount(Long userId, Long amount, Integer version) {
return baseMapper.unfreezeAmount(userId, amount, version) > 0;
return salaryAccountBalanceDAO.unfreezeAmount(userId, amount, version) > 0;
}
}

View File

@ -1,7 +1,7 @@
package com.red.circle.wallet.infra.database.rds.service.salary.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountRunningWaterMapper;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountRunningWaterDAO;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
import com.red.circle.wallet.infra.database.rds.service.salary.SalaryAccountRunningWaterService;
import org.springframework.stereotype.Service;
@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
*/
@Service
public class SalaryAccountRunningWaterServiceImpl
extends ServiceImpl<SalaryAccountRunningWaterMapper, SalaryAccountRunningWater>
extends BaseServiceImpl<SalaryAccountRunningWaterDAO, SalaryAccountRunningWater>
implements SalaryAccountRunningWaterService {
}

View File

@ -1,5 +1,7 @@
package com.red.circle.wallet.infra.gateway;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.common.business.core.enums.ReceiptType;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.web.util.ValidatorUtils;
@ -52,15 +54,14 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway {
}
// 检查账户是否存在不存在则初始化
SalaryAccountBalance balance = salaryAccountBalanceService.lambdaQuery()
.eq(SalaryAccountBalance::getUserId, receipt.getUserId())
.one();
LambdaQueryWrapper<SalaryAccountBalance> eq = Wrappers.<SalaryAccountBalance>lambdaQuery()
.eq(SalaryAccountBalance::getUserId, receipt.getUserId());
SalaryAccountBalance balance = salaryAccountBalanceService.getOne(eq);
if (Objects.isNull(balance)) {
salaryAccountBalanceService.init(receipt.getSysOrigin(), receipt.getUserId());
balance = salaryAccountBalanceService.lambdaQuery()
.eq(SalaryAccountBalance::getUserId, receipt.getUserId())
.one();
balance = salaryAccountBalanceService.getOne(new LambdaQueryWrapper<>(SalaryAccountBalance.class)
.eq(SalaryAccountBalance::getUserId, receipt.getUserId()));
}
// 更新余额
@ -91,9 +92,9 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway {
salaryAccountRunningWaterService.save(runningWater);
} catch (DuplicateKeyException e) {
// 幂等性trackId重复查询已有记录
SalaryAccountRunningWater existingWater = salaryAccountRunningWaterService.lambdaQuery()
.eq(SalaryAccountRunningWater::getTrackId, receipt.getTrackId())
.one();
SalaryAccountRunningWater existingWater = salaryAccountRunningWaterService.getOne(
new LambdaQueryWrapper<>(SalaryAccountRunningWater.class)
.eq(SalaryAccountRunningWater::getTrackId, receipt.getTrackId()));
if (Objects.nonNull(existingWater)) {
return SalaryReceiptRes.of(
existingWater.getId(),

View File

@ -1,6 +1,6 @@
<?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.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountBalanceMapper">
<mapper namespace="com.red.circle.wallet.infra.database.rds.dao.salary.SalaryAccountBalanceDAO">
<update id="incrIncome">
UPDATE user_salary_account_balance

View File

@ -0,0 +1,132 @@
package com.red.circle.wallet.inner.convertor;
import com.red.circle.framework.core.dto.ReqSysOrigin;
import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO;
import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO;
import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO;
import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import java.util.Objects;
import org.springframework.stereotype.Component;
/**
* 工资账户 Inner 转换器.
*/
@Component
public class SalaryAccountInnerConvertor {
public SalaryIssueCmd toIssueCmd(SalaryIssueInnerCmd innerCmd) {
if (Objects.isNull(innerCmd)) {
return null;
}
SalaryIssueCmd cmd = new SalaryIssueCmd();
cmd.setUserId(innerCmd.getUserId());
cmd.setSalaryType(innerCmd.getSalaryType());
cmd.setAmount(innerCmd.getAmount());
cmd.setBillBelong(innerCmd.getBillBelong());
cmd.setTrackId(innerCmd.getTrackId());
cmd.setTeamId(innerCmd.getTeamId());
cmd.setBdId(innerCmd.getBdId());
cmd.setAgentId(innerCmd.getAgentId());
cmd.setEventDesc(innerCmd.getEventDesc());
cmd.setRemark(innerCmd.getRemark());
// 设置请求来源信息
cmd.setReqSysOrigin(ReqSysOrigin.of(innerCmd.getSysOrigin()));
cmd.setReqUserId(innerCmd.getOpUserId());
return cmd;
}
public SalaryWithdrawCmd toWithdrawCmd(SalaryWithdrawInnerCmd innerCmd) {
if (Objects.isNull(innerCmd)) {
return null;
}
SalaryWithdrawCmd cmd = new SalaryWithdrawCmd();
cmd.setUserId(innerCmd.getUserId());
cmd.setAmount(innerCmd.getAmount());
cmd.setTrackId(innerCmd.getTrackId());
cmd.setServiceCharge(innerCmd.getServiceCharge());
cmd.setRemark(innerCmd.getRemark());
// 设置请求来源信息
cmd.setReqSysOrigin(ReqSysOrigin.of(innerCmd.getSysOrigin()));
cmd.setReqUserId(innerCmd.getOpUserId());
return cmd;
}
public SalaryRunningWaterQueryCmd toRunningWaterQueryCmd(SalaryRunningWaterQueryInnerCmd innerCmd) {
if (Objects.isNull(innerCmd)) {
return null;
}
SalaryRunningWaterQueryCmd cmd = new SalaryRunningWaterQueryCmd();
cmd.setUserId(innerCmd.getUserId());
cmd.setSalaryType(innerCmd.getSalaryType());
cmd.setType(innerCmd.getType());
cmd.setBillBelong(innerCmd.getBillBelong());
cmd.setStartTime(innerCmd.getStartTime());
cmd.setEndTime(innerCmd.getEndTime());
cmd.setCurrent(innerCmd.getPageNum().longValue());
cmd.setSize(innerCmd.getPageSize().longValue());
return cmd;
}
public SalaryAccountBalanceDTO toBalanceDTO(SalaryAccountBalanceCO co) {
if (Objects.isNull(co)) {
return null;
}
SalaryAccountBalanceDTO dto = new SalaryAccountBalanceDTO();
dto.setUserId(co.getUserId());
dto.setEarnPoints(co.getEarnPoints());
dto.setConsumptionPoints(co.getConsumptionPoints());
dto.setBalance(co.getBalance());
dto.setFrozenAmount(co.getFrozenAmount());
dto.setAvailableBalance(co.getAvailableBalance());
return dto;
}
public SalaryIssueResultDTO toIssueResultDTO(SalaryIssueResultCO co) {
if (Objects.isNull(co)) {
return null;
}
SalaryIssueResultDTO dto = new SalaryIssueResultDTO();
dto.setRecordId(co.getRecordId());
dto.setAmount(co.getAmount());
dto.setBalance(co.getBalance());
dto.setAvailableBalance(co.getAvailableBalance());
return dto;
}
public SalaryRunningWaterDTO toRunningWaterDTO(SalaryRunningWaterCO co) {
if (Objects.isNull(co)) {
return null;
}
SalaryRunningWaterDTO dto = new SalaryRunningWaterDTO();
dto.setId(co.getId());
dto.setUserId(co.getUserId());
dto.setType(co.getType());
dto.setSalaryType(co.getSalaryType());
dto.setSalaryTypeName(co.getSalaryTypeName());
dto.setAmount(co.getAmount());
dto.setBalance(co.getBalance());
dto.setAvailableBalance(co.getAvailableBalance());
dto.setSalaryEvent(co.getSalaryEvent());
dto.setEventDesc(co.getEventDesc());
dto.setTrackId(co.getTrackId());
dto.setBillBelong(co.getBillBelong());
dto.setTeamId(co.getTeamId());
dto.setBdId(co.getBdId());
dto.setAgentId(co.getAgentId());
dto.setRemark(co.getRemark());
dto.setCreatedAt(co.getCreatedAt());
return dto;
}
}

View File

@ -0,0 +1,51 @@
package com.red.circle.wallet.inner.endpoint.salary;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.wallet.inner.endpoint.salary.api.UserSalaryAccountClientApi;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import com.red.circle.wallet.inner.service.salary.UserSalaryAccountClientService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 工资账户 Client Endpoint.
*/
@Validated
@RestController
@RequestMapping(value = UserSalaryAccountClientApi.API_PREFIX, produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class UserSalaryAccountClientEndpoint implements UserSalaryAccountClientApi {
private final UserSalaryAccountClientService userSalaryAccountClientService;
@Override
public ResultResponse<SalaryAccountBalanceDTO> getBalance(Long userId) {
return ResultResponse.success(userSalaryAccountClientService.getBalance(userId));
}
@Override
public ResultResponse<SalaryIssueResultDTO> issueSalary(SalaryIssueInnerCmd cmd) {
return ResultResponse.success(userSalaryAccountClientService.issueSalary(cmd));
}
@Override
public ResultResponse<Void> withdrawSalary(SalaryWithdrawInnerCmd cmd) {
userSalaryAccountClientService.withdrawSalary(cmd);
return ResultResponse.success();
}
@Override
public ResultResponse<PageResult<SalaryRunningWaterDTO>> queryRunningWater(
SalaryRunningWaterQueryInnerCmd cmd) {
return ResultResponse.success(userSalaryAccountClientService.queryRunningWater(cmd));
}
}

View File

@ -0,0 +1,35 @@
package com.red.circle.wallet.inner.service.salary;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
/**
* 工资账户 Inner Service.
*/
public interface UserSalaryAccountClientService {
/**
* 查询余额.
*/
SalaryAccountBalanceDTO getBalance(Long userId);
/**
* 发放工资.
*/
SalaryIssueResultDTO issueSalary(SalaryIssueInnerCmd cmd);
/**
* 提现.
*/
void withdrawSalary(SalaryWithdrawInnerCmd cmd);
/**
* 查询流水.
*/
PageResult<SalaryRunningWaterDTO> queryRunningWater(SalaryRunningWaterQueryInnerCmd cmd);
}

View File

@ -0,0 +1,70 @@
package com.red.circle.wallet.inner.service.salary.impl;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO;
import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO;
import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO;
import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd;
import com.red.circle.wallet.app.service.SalaryAccountService;
import com.red.circle.wallet.inner.convertor.SalaryAccountInnerConvertor;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import com.red.circle.wallet.inner.service.salary.UserSalaryAccountClientService;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 工资账户 Inner Service 实现.
*/
@Service
@RequiredArgsConstructor
public class UserSalaryAccountClientServiceImpl implements UserSalaryAccountClientService {
private final SalaryAccountService salaryAccountService;
private final SalaryAccountInnerConvertor salaryAccountInnerConvertor;
@Override
public SalaryAccountBalanceDTO getBalance(Long userId) {
SalaryAccountBalanceCO co = salaryAccountService.getBalance(userId);
return salaryAccountInnerConvertor.toBalanceDTO(co);
}
@Override
public SalaryIssueResultDTO issueSalary(SalaryIssueInnerCmd innerCmd) {
SalaryIssueCmd cmd = salaryAccountInnerConvertor.toIssueCmd(innerCmd);
SalaryIssueResultCO co = salaryAccountService.issueSalary(cmd);
return salaryAccountInnerConvertor.toIssueResultDTO(co);
}
@Override
public void withdrawSalary(SalaryWithdrawInnerCmd innerCmd) {
SalaryWithdrawCmd cmd = salaryAccountInnerConvertor.toWithdrawCmd(innerCmd);
salaryAccountService.withdrawSalary(cmd);
}
@Override
public PageResult<SalaryRunningWaterDTO> queryRunningWater(SalaryRunningWaterQueryInnerCmd innerCmd) {
SalaryRunningWaterQueryCmd cmd = salaryAccountInnerConvertor.toRunningWaterQueryCmd(innerCmd);
PageResult<SalaryRunningWaterCO> coPageResult = salaryAccountService.queryRunningWater(cmd);
List<SalaryRunningWaterDTO> collect = coPageResult.getRecords().stream()
.map(salaryAccountInnerConvertor::toRunningWaterDTO)
.collect(Collectors.toList());
PageResult<SalaryRunningWaterDTO> pageResult = new PageResult<>();
pageResult.setTotal(coPageResult.getTotal());
pageResult.setRecords(collect);
pageResult.setSize(coPageResult.getSize());
pageResult.setCurrent(coPageResult.getCurrent());
return pageResult;
}
}