Merge remote-tracking branch 'origin/master'

This commit is contained in:
Tankaikai 2025-02-13 16:28:49 +08:00
commit 021fa1c2c8
16 changed files with 504 additions and 0 deletions

View File

@ -0,0 +1,70 @@
package com.czg.controller.admin;
import com.czg.account.dto.shopuser.ShopUserEditDTO;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.dto.shopuser.ShopUserSummaryDTO;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopUserService;
import com.czg.annotation.SaAdminCheckPermission;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 店铺用户管理
* @author Administrator
*/
@RestController
@RequestMapping("/admin/shopUser")
public class ShopUserController {
@Resource
private ShopUserService shopUserService;
/**
* 获取店铺用户概述信息
* @param isVip 0 非vip 1 vip
* @return 概述信息
*/
@SaAdminCheckPermission("shopUser:summary")
@GetMapping("/summary")
public CzgResult<ShopUserSummaryDTO> summary(Integer isVip) {
return CzgResult.success(shopUserService.getSummary(StpKit.USER.getShopId(), isVip));
}
/**
* 获取店铺用户列表
* @param key 昵称或手机号
* @param isVip 0 非vip 1 vip
* @return 用户列表
*/
@SaAdminCheckPermission("shopUser:list")
@GetMapping
public CzgResult<Page<ShopUser>> list(String key, Integer isVip) {
return CzgResult.success(shopUserService.getPage(key, isVip));
}
/**
* 店铺用户信息修改
* @return 是否成功
*/
@SaAdminCheckPermission("shopUser:edit")
@PutMapping
public CzgResult<Boolean> edit(@RequestBody @Validated ShopUserEditDTO shopUserEditDTO) {
return CzgResult.success(shopUserService.updateInfo(StpKit.USER.getShopId(), shopUserEditDTO));
}
/**
* 店铺用户余额修改
* @return 是否成功
*/
@SaAdminCheckPermission("shopUser:editFlow")
@PutMapping("/money")
public CzgResult<Boolean> editMoney(@RequestBody @Validated ShopUserMoneyEditDTO shopUserMoneyEditDTO) {
return CzgResult.success(shopUserService.updateMoney(StpKit.USER.getShopId(), shopUserMoneyEditDTO));
}
}

View File

@ -0,0 +1,59 @@
package com.czg.account.dto.flow;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户余额流水 实体类
*
* @author zs
* @since 2025-02-13
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ShopUserFlowDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
private Long userId;
private Long shopId;
private BigDecimal amount;
private BigDecimal balance;
/**
* 类型cashIn 会员充值awardIn 充值奖励wechatIn 微信小程序充值alipayIn 支付宝小程序充值orderPay 订单消费orderRefund 订单退款rechargeRefund 充值退款 adminOp 管理员手动增减
*/
private String bizCode;
/**
* 加减号
*/
private String type;
private String remark;
/**
* 关联订单编号支付单号退款单号
*/
private String relationOrderNo;
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,28 @@
package com.czg.account.dto.shopuser;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* @author Administrator
*/
@Data
public class ShopUserEditDTO {
/**
* 对应shopUserid
*/
@NotNull
private Long id;
/**
* 昵称
*/
private String nickName;
/**
* 性别 0女 1男
*/
private Integer sex;
/**
* 生日
*/
private String birthDay;
}

View File

@ -0,0 +1,38 @@
package com.czg.account.dto.shopuser;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Administrator
*/
@Data
public class ShopUserMoneyEditDTO {
/**
* 对应shopUserid
*/
@NotNull
private Long id;
/**
* 0减少 1增加
*/
@NotNull
private Integer type;
/**
* 浮动金额
*/
@NotNull
@DecimalMin("0.01")
@DecimalMax("9999")
private BigDecimal money;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,15 @@
package com.czg.account.dto.shopuser;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Administrator
*/
@Data
public class ShopUserSummaryDTO {
private Integer userTotal;
private Integer chargeTotal;
private BigDecimal balanceTotal;
}

View File

@ -36,6 +36,31 @@ public class ShopUser implements Serializable {
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 用户头像
*/
private String headImg;
/**
* 用户昵称
*/
private String nickName;
/**
* 电话号码
*/
private String phone;
/**
* 会员生日
*/
private String birthDay;
/**
* 0- 1男
*/
private Integer sex;
/**
* 店铺Id
*/

View File

@ -0,0 +1,65 @@
package com.czg.account.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户余额流水 实体类
*
* @author zs
* @since 2025-02-13
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("tb_shop_user_flow")
public class ShopUserFlow implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
private Long userId;
private Long shopId;
private BigDecimal amount;
private BigDecimal balance;
/**
* 类型cashIn 会员充值awardIn 充值奖励wechatIn 微信小程序充值alipayIn 支付宝小程序充值orderPay 订单消费orderRefund 订单退款rechargeRefund 充值退款 adminOp 管理员手动增减
*/
private String bizCode;
/**
* 加减号
*/
private String type;
private String remark;
/**
* 关联订单编号支付单号退款单号
*/
private String relationOrderNo;
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,14 @@
package com.czg.account.service;
import com.mybatisflex.core.service.IService;
import com.czg.account.entity.ShopUserFlow;
/**
* 用户余额流水 服务层
*
* @author zs
* @since 2025-02-13
*/
public interface ShopUserFlowService extends IService<ShopUserFlow> {
}

View File

@ -1,6 +1,10 @@
package com.czg.account.service;
import com.czg.account.dto.shopuser.ShopUserEditDTO;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.dto.shopuser.ShopUserSummaryDTO;
import com.czg.account.entity.ShopUser;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
/**
@ -11,4 +15,11 @@ import com.mybatisflex.core.service.IService;
*/
public interface ShopUserService extends IService<ShopUser> {
Page<ShopUser> getPage(String key, Integer isVip);
Boolean updateInfo(Long shopId, ShopUserEditDTO shopUserEditDTO);
Boolean updateMoney(Long shopId, ShopUserMoneyEditDTO shopUserEditDTO);
ShopUserSummaryDTO getSummary(Long shopId, Integer isVip);
}

View File

@ -0,0 +1,25 @@
package com.czg.enums;
import lombok.Getter;
/**
* @author Administrator
*/
@Getter
public enum ShopUserFlowBizEnum {
// 会员充值
CASH_IN("cashIn"),
AWARD_IN("awardIn"),
WECHAT_IN("wechatIn"),
ALIPAY_IN("alipayIn"),
ORDER_PAY("orderPay"),
ORDER_REFUND("orderRefund"),
RECHARGE_REFUND("rechargeRefund"),
ADMIN_IN("adminIn");
private final String code;
ShopUserFlowBizEnum(String code) {
this.code = code;
}
}

View File

@ -0,0 +1,14 @@
package com.czg.service.account.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.account.entity.ShopUserFlow;
/**
* 用户余额流水 映射层
*
* @author zs
* @since 2025-02-13
*/
public interface ShopUserFlowMapper extends BaseMapper<ShopUserFlow> {
}

View File

@ -1,7 +1,13 @@
package com.czg.service.account.mapper;
import com.czg.account.dto.shopuser.ShopUserSummaryDTO;
import com.czg.account.entity.ShopUser;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.paginate.Page;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商户储值会员 映射层
@ -11,4 +17,11 @@ import com.mybatisflex.core.BaseMapper;
*/
public interface ShopUserMapper extends BaseMapper<ShopUser> {
Page<ShopUser> selectPageByKeyAndIsVip(Page<Object> objectPage, @Param("key") String key, @Param("isVip") Integer isVip,
@Param("shopId") Long shopId);
int incrAccount(@Param("shopId") long shopId, @Param("id") Long id, @Param("time") LocalDateTime time, @Param("money") BigDecimal money);
int decrAccount(@Param("shopId") long shopId, @Param("id") Long id, @Param("time") LocalDateTime time, @Param("money") BigDecimal money);
ShopUserSummaryDTO selectUserSummary(@Param("shopId") Long shopId, @Param("isVip") Integer isVip);
}

View File

@ -0,0 +1,18 @@
package com.czg.service.account.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.account.entity.ShopUserFlow;
import com.czg.account.service.ShopUserFlowService;
import com.czg.service.account.mapper.ShopUserFlowMapper;
import org.springframework.stereotype.Service;
/**
* 用户余额流水 服务层实现
*
* @author zs
* @since 2025-02-13
*/
@Service
public class ShopUserFlowServiceImpl extends ServiceImpl<ShopUserFlowMapper, ShopUserFlow> implements ShopUserFlowService{
}

View File

@ -1,11 +1,26 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.czg.account.dto.shopuser.ShopUserEditDTO;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.dto.shopuser.ShopUserSummaryDTO;
import com.czg.account.entity.ShopUser;
import com.czg.account.entity.ShopUserFlow;
import com.czg.account.service.ShopUserFlowService;
import com.czg.account.service.ShopUserService;
import com.czg.enums.ShopUserFlowBizEnum;
import com.czg.exception.ApiNotPrintException;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.ShopUserMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.RoundingMode;
/**
* 商户储值会员 服务层实现
*
@ -14,5 +29,58 @@ import org.springframework.stereotype.Service;
*/
@Service
public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> implements ShopUserService {
@Resource
private ShopUserFlowService shopUserFlowService;
private ShopUser getUserInfo(Long shopUserId, Long shopId) {
ShopUser shopUser = queryChain().eq(ShopUser::getShopId, shopId).eq(ShopUser::getId, shopUserId).one();
if (shopUser == null) {
throw new ApiNotPrintException("用户信息不存在");
}
return shopUser;
}
@Override
public Page<ShopUser> getPage(String key, Integer isVip) {
return mapper.selectPageByKeyAndIsVip(PageUtil.buildPage(), key, isVip, StpKit.USER.getShopId());
}
@Override
public Boolean updateInfo(Long shopId, ShopUserEditDTO shopUserEditDTO) {
ShopUser shopUser = getUserInfo(shopId, shopUserEditDTO.getId());
BeanUtil.copyProperties(shopUserEditDTO, shopUser);
return updateById(shopUser);
}
@Override
public Boolean updateMoney(Long shopId, ShopUserMoneyEditDTO shopUserEditDTO) {
shopUserEditDTO.setMoney(shopUserEditDTO.getMoney().setScale(2, RoundingMode.DOWN));
ShopUser userInfo = getUserInfo(shopId, shopUserEditDTO.getId());
ShopUserFlow userFlow = new ShopUserFlow();
int flag = 0;
if (shopUserEditDTO.getType() == 0) {
flag = mapper.decrAccount(shopId, shopUserEditDTO.getId(), DateUtil.date().toLocalDateTime(), shopUserEditDTO.getMoney());
}else {
flag = mapper.incrAccount(shopId, shopUserEditDTO.getId(), DateUtil.date().toLocalDateTime(), shopUserEditDTO.getMoney());
}
if (flag == 0) {
throw new ApiNotPrintException("增减用户余额操作失败");
}
userFlow.setUserId(userInfo.getUserId());
userFlow.setShopId(userInfo.getShopId());
userFlow.setAmount(shopUserEditDTO.getMoney());
userFlow.setBalance(shopUserEditDTO.getType() == 0 ? userInfo.getAmount().subtract(shopUserEditDTO.getMoney()) : userInfo.getAmount().add(shopUserEditDTO.getMoney()));
userFlow.setBizCode(ShopUserFlowBizEnum.ADMIN_IN.getCode());
userFlow.setType(shopUserEditDTO.getType() == 0 ? "-" : "+");
userFlow.setRemark(shopUserEditDTO.getRemark());
return shopUserFlowService.save(userFlow);
}
@Override
public ShopUserSummaryDTO getSummary(Long shopId, Integer isVip) {
return mapper.selectUserSummary(shopId, isVip);
}
}

View File

@ -0,0 +1,7 @@
<?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.czg.service.account.mapper.ShopUserFlowMapper">
</mapper>

View File

@ -3,5 +3,39 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.account.mapper.ShopUserMapper">
<update id="incrAccount">
update tb_shop_user
set amount=amount + #{money},
update_time=#{time}
where id = #{id}
and shop_id = #{shopId}
</update>
<update id="decrAccount">
update tb_shop_user
set amount=amount - #{money},
update_time=#{time}
where id = #{id}
and shop_id = #{shopId}
and amount - #{money} >= 0
</update>
<select id="selectPageByKeyAndIsVip" resultType="com.czg.account.entity.ShopUser">
select a.* from tb_user_info as a
left join tb_shop_user as b on a.id=b.user_id
where b.shop_id=#{shopId}
<if test="key != null and key != ''">
and (a.nick_name like %#{key}% or a.phone like %#{key}%)
</if>
<if test="isVip != null">
and b.is_vip=#{isVip}
</if>
</select>
<select id="selectUserSummary" resultType="com.czg.account.dto.shopuser.ShopUserSummaryDTO">
select count(a.id) userTotal, sum(IFNULL(a.amount, 0)) balanceTotal,sum(IFNULL(b.amount,0)) chargeTotal from tb_shop_user as a
left join tb_shop_user_flow as b on a.id=b.user_id and b.type='+' and b.biz_code in ('cashIn', 'wechatIn', 'alipayIn')
where a.shop_id = #{shopId}
<if test="isVip !=null">
and a.is_vip=#{isVip}
</if>
</select>
</mapper>