Compare commits

22 Commits

Author SHA1 Message Date
782fd5a0e5 银收客 模板消息修改 2026-01-26 15:54:25 +08:00
4c65d3226a 异常 抛出 2026-01-26 09:29:26 +08:00
74156e207a 分销 2026-01-23 17:10:58 +08:00
b74367b9cd 更新分销上下级 2026-01-23 16:54:46 +08:00
1c7d3ac374 分销 2026-01-23 16:47:13 +08:00
1a18449d65 邀请问题 2026-01-23 16:35:56 +08:00
3b28287f22 会员等级不存在的问题 2026-01-23 14:14:19 +08:00
b9e768bd47 渠道 兼容 2026-01-23 10:15:53 +08:00
3dcc649224 添加支付信息 2026-01-23 10:09:43 +08:00
5cb95a31f1 事务结束后 2026-01-22 17:56:45 +08:00
f2ab7bdcd5 事务结束后 响应2 2026-01-22 17:41:31 +08:00
10cb6aa8cc 事务结束后 响应 2026-01-22 17:35:28 +08:00
ff95440732 绑定 响应 2026-01-22 17:23:08 +08:00
5fe6b48786 记得删除 /user/distribution/clean 2026-01-22 17:13:47 +08:00
6bd1959fc3 Merge remote-tracking branch 'origin/test' into test 2026-01-22 17:04:29 +08:00
c78b7a1ec3 记得删除 /user/distribution/clean 2026-01-22 17:04:19 +08:00
gong
bae925695a 查询 关联商品 sync_id bug 2026-01-22 15:57:30 +08:00
a94a9197b8 优惠券详情 2026-01-21 16:10:26 +08:00
3a1579d281 优惠券详情 2026-01-21 16:06:20 +08:00
f092fdc0e9 必填 2026-01-21 15:51:30 +08:00
bb673d805a 积分商品详情 2026-01-21 15:33:30 +08:00
0ba52b85b2 检查登录 2026-01-21 13:36:59 +08:00
26 changed files with 216 additions and 390 deletions

View File

@@ -15,8 +15,8 @@ import com.czg.resp.CzgResult;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.task.DistributionTask; import com.czg.task.DistributionTask;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.FunUtils;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import io.seata.core.exception.TransactionException;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NestedExceptionUtils; import org.springframework.core.NestedExceptionUtils;
@@ -46,7 +46,7 @@ public class UDistributionController {
private DistributionTask distributionTask; private DistributionTask distributionTask;
/** /**
* 分销员中心-获取配置 * 测试方法-分销流水入账
*/ */
@GetMapping("/task") @GetMapping("/task")
public CzgResult<String> task(@RequestParam Long shopId) { public CzgResult<String> task(@RequestParam Long shopId) {
@@ -137,11 +137,12 @@ public class UDistributionController {
* 分销员中心-无感-绑定邀请人 * 分销员中心-无感-绑定邀请人
*/ */
@PostMapping("/autoBindInviteUser") @PostMapping("/autoBindInviteUser")
public CzgResult<Map<String, Object>> autoBindInviteUser(@RequestBody MkDistributionUserDTO param) { public CzgResult<Map<String, Object>> autoBindInviteUser(@RequestBody MkDistributionUserDTO param) throws TransactionException {
AssertUtil.isNull(param.getId(), "店铺用户ID不能为空"); try {
AssertUtil.isNull(param.getShopId(), "店铺ID不能为空"); bindInviteUser(param);
AssertUtil.isNull(param.getInviteCode(), "邀请码不能为空"); } catch (Exception e) {
FunUtils.asyncSafeRunVoid(() -> distributionUserService.bindInviteUser(param), "无感绑定上级"); log.error("无感绑定邀请人失败:{}", param, e);
}
return CzgResult.success(); return CzgResult.success();
} }

View File

@@ -79,7 +79,7 @@ public class UPpPackageController {
* 取消订单 * 取消订单
*/ */
@GetMapping("/cancel") @GetMapping("/cancel")
public CzgResult<Boolean> cancelOrder(Long orderId) { public CzgResult<Boolean> cancelOrder(@RequestParam Long orderId) {
return CzgResult.success(ppPackageOrderService.cancelOrder(orderId)); return CzgResult.success(ppPackageOrderService.cancelOrder(orderId));
} }
@@ -95,7 +95,7 @@ public class UPpPackageController {
* 获取订单详情 * 获取订单详情
*/ */
@GetMapping("/order/detail") @GetMapping("/order/detail")
public CzgResult<PpPackageOrderDTO> getOrderDetail(Long orderId) { public CzgResult<PpPackageOrderDTO> getOrderDetail(@RequestParam Long orderId) {
return CzgResult.success(ppPackageOrderService.getOrderDetailById(orderId, StpKit.USER.getLoginIdAsLong())); return CzgResult.success(ppPackageOrderService.getOrderDetailById(orderId, StpKit.USER.getLoginIdAsLong()));
} }

View File

@@ -1,8 +1,11 @@
package com.czg.controller.user; package com.czg.controller.user;
import com.czg.market.entity.MkPointsGoods;
import com.czg.market.entity.MkPointsGoodsRecord; import com.czg.market.entity.MkPointsGoodsRecord;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.service.MkPointsGoodsRecordService; import com.czg.market.service.MkPointsGoodsRecordService;
import com.czg.market.service.MkPointsGoodsService; import com.czg.market.service.MkPointsGoodsService;
import com.czg.market.service.ShopCouponService;
import com.czg.order.dto.CommonRefundDTO; import com.czg.order.dto.CommonRefundDTO;
import com.czg.order.dto.LtPayOtherDTO; import com.czg.order.dto.LtPayOtherDTO;
import com.czg.order.service.PointsGoodPayService; import com.czg.order.service.PointsGoodPayService;
@@ -34,6 +37,8 @@ public class UPointGoodsController {
private MkPointsGoodsRecordService goodsRecordService; private MkPointsGoodsRecordService goodsRecordService;
@Resource @Resource
private PointsGoodPayService goodPayService; private PointsGoodPayService goodPayService;
@Resource
private ShopCouponService shopCouponService;
/** /**
* 商品列表 * 商品列表
@@ -51,6 +56,22 @@ public class UPointGoodsController {
return CzgResult.success(data); return CzgResult.success(data);
} }
/**
* 商品详情
*/
@GetMapping("/{id}")
public CzgResult<MkPointsGoods> getPointsGoodsSettingById(@PathVariable("id") Long id) {
MkPointsGoods goods = pointsGoodsService.getById(id);
if ("优惠券".equals(goods.getGoodsCategory())) {
ShopCoupon one = shopCouponService.getOne(QueryWrapper.create().eq(ShopCoupon::getId, goods.getCouponId())
.eq(ShopCoupon::getShopId, goods.getShopId())
.eq(ShopCoupon::getStatus, 1)
.eq(ShopCoupon::getIsDel, 0));
goods.setCouponInfo(one);
}
return CzgResult.success(goods);
}
/** /**
* 生成订单 * 生成订单
* 小程序支付 * 小程序支付

View File

@@ -21,7 +21,7 @@ wx:
appId: wx212769170d2c6b2a appId: wx212769170d2c6b2a
secrete: 8492a7e8d55bbb1b57f5c8276ea1add0 secrete: 8492a7e8d55bbb1b57f5c8276ea1add0
operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg
warnMsgTmpId: C08OUr80x6wGmUN1zpFhSQ3Sv7VF5vksdZigiEx2pD0 warnMsgTmpId: C08OUr80x6wGmUN1zpFhSZyFA2G6b9_jiZgEppzLB70

View File

@@ -43,7 +43,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
userConfig.setIsShare(true); userConfig.setIsShare(true);
// config2.setTimeout(2000); // config2.setTimeout(2000);
userConfig.setTokenStyle("simple-uuid"); userConfig.setTokenStyle("simple-uuid");
MyStpLogic.CLIENT_LOGIC.setConfig(userConfig); MyStpLogic.USER_LOGIC.setConfig(userConfig);
} }
@PostConstruct @PostConstruct
@@ -62,21 +62,25 @@ public class SaTokenConfigure implements WebMvcConfigurer {
// 重置根路径防止satoken切割根路径导致匹配不到路径 // 重置根路径防止satoken切割根路径导致匹配不到路径
ApplicationInfo.routePrefix = ""; ApplicationInfo.routePrefix = "";
SaRouter.match("/user/**").notMatch("/user/login", "/user/test", "/user/geo/**", "/user/home/**", "/user/home/**", "/user/dict/**", "/user/openId") SaRouter
.notMatch("/pay/**") // 完全开放的路径(不需要任何认证)
.notMatch("/notify/**") .match("/user/login", "/user/geo/**", "/user/home/**",
.check(r -> MyStpLogic.CLIENT_LOGIC.checkLogin()) "/user/dict/**", "/user/openId","/admin/auth/**",
.setHit(true) "/admin/shopMsgPush/subscribe/**",
// .match("/**") "/admin/coupon/grant",
.notMatch("/user/**") "/pay/**",
.notMatch("/pay/**") "/notify/**")
.notMatch("/notify/**") .stop() // 直接放行,不检查登录
.notMatch("/admin/auth/**")
.notMatch("/admin/shopMsgPush/subscribe/**") // 用户认证路径
.notMatch("/admin/coupon/grant") .match("/user/**")
.check(r -> MyStpLogic.USER_LOGIC.checkLogin())
// 管理端认证内网IP免认证
.match("/**")
.check(r -> { .check(r -> {
ServletRequestAttributes attributes = ServletRequestAttributes attributes = (ServletRequestAttributes)
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); RequestContextHolder.getRequestAttributes();
if (attributes == null || (!ServletUtil.getClientIP(attributes.getRequest()).contains("192.168") && !ServletUtil.getClientIP(attributes.getRequest()).contains("127.0.0.1"))) { if (attributes == null || (!ServletUtil.getClientIP(attributes.getRequest()).contains("192.168") && !ServletUtil.getClientIP(attributes.getRequest()).contains("127.0.0.1"))) {
MyStpLogic.ADMIN_LOGIC.checkLogin(); MyStpLogic.ADMIN_LOGIC.checkLogin();
} }

View File

@@ -27,7 +27,7 @@ import java.util.function.Consumer;
@Slf4j @Slf4j
@Getter @Getter
public class MyStpLogic { public class MyStpLogic {
public static final StpLogic CLIENT_LOGIC = new StpLogic("client"); public static final StpLogic USER_LOGIC = new StpLogic("user");
public static final StpLogic ADMIN_LOGIC = new StpLogic("admin"); public static final StpLogic ADMIN_LOGIC = new StpLogic("admin");
public Object isPC() { public Object isPC() {
@@ -42,7 +42,7 @@ public class MyStpLogic {
private StpLogic getLogic() { private StpLogic getLogic() {
boolean hit = SaRouter.match("/user/**").isHit(); boolean hit = SaRouter.match("/user/**").isHit();
if (hit) { if (hit) {
return CLIENT_LOGIC; return USER_LOGIC;
} }
return ADMIN_LOGIC; return ADMIN_LOGIC;
} }

View File

@@ -152,6 +152,23 @@ public class ShopUser implements Serializable {
private LocalDateTime nextDeliverTime; private LocalDateTime nextDeliverTime;
// 是否分销员 // 是否分销员
private String distributionShops; private String distributionShops;
/**
* 上级分销员id
*/
private Long parentUserId;
/**
* 上上级分销员id
*/
private Long gradeUserId;
/**
* 一级分销收入
*/
private BigDecimal oneIncome;
/**
* 二级分销收入
*/
private BigDecimal twoIncome;
private String memberCircleName; private String memberCircleName;
private Integer memberCircleReward; private Integer memberCircleReward;

View File

@@ -2,6 +2,7 @@ package com.czg.account.service;
import com.czg.account.entity.ShopConfig; import com.czg.account.entity.ShopConfig;
import com.czg.account.entity.ShopInfo; import com.czg.account.entity.ShopInfo;
import com.czg.exception.CzgException;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import java.io.Serializable; import java.io.Serializable;
@@ -15,7 +16,7 @@ import java.util.List;
*/ */
public interface ShopConfigService extends IService<ShopConfig> { public interface ShopConfigService extends IService<ShopConfig> {
ShopInfo getShopInfoAndConfig(Serializable id); ShopInfo getShopInfoAndConfig(Serializable id) throws CzgException;
void editStatusByShopIdList(Long mainShopId, Integer isEnable, boolean onyUpValid, String name, String useShopType, List<Long> shopIdList); void editStatusByShopIdList(Long mainShopId, Integer isEnable, boolean onyUpValid, String name, String useShopType, List<Long> shopIdList);

View File

@@ -110,8 +110,10 @@ public class MkDistributionFlow implements Serializable {
private String nickName; private String nickName;
/**
* 分成比例
*/
private BigDecimal commission; private BigDecimal commission;
private BigDecimal parentCommission;
private LocalDateTime deliverTime; private LocalDateTime deliverTime;
private Long userId; private Long userId;
} }

View File

@@ -62,12 +62,8 @@ public class MkDistributionLevelConfig implements Serializable {
/** /**
* 一级分销比例 * 一级分销比例
*/ */
private BigDecimal levelOneCommission; private BigDecimal commission;
/**
* 二级分销比例
*/
private BigDecimal levelTwoCommission;
/** /**
* 创建时间 * 创建时间

View File

@@ -1,74 +0,0 @@
package com.czg.market.entity;
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 ww
* @since 2025-11-06
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("tb_shop_user_invite")
public class ShopUserInvite implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* (随机)
*/
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 店铺ID
*/
private Long shopId;
/**
* 店铺用户ID
*/
private Long shopUserId;
/**
* 邀请人ID mk_distribution_user.id
*/
private Long distributionUserId;
/**
* 邀请人上级ID mk_distribution_user.id
*/
private Long distributionUserParentId;
/**
* 邀请人收益/一级分润
*/
private BigDecimal oneIncome;
/**
* 邀请人上级收益/二级分润
*/
private BigDecimal twoIncome;
/**
* 邀请时间
*/
private LocalDateTime inviteTime;
}

View File

@@ -1,22 +0,0 @@
package com.czg.market.service;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.ShopUserInvite;
/**
* 邀请与上级关联表 服务层。
*
* @author ww
* @since 2025-11-06
*/
public interface ShopUserInviteService extends IService<ShopUserInvite> {
/**
* 根据店铺ID和店铺用户ID查询邀请记录
*
* @param shopId 店铺ID
* @param shopUserId 店铺用户ID
* @return 邀请记录
*/
ShopUserInvite getOneByShopIdAndShopUserId(Long shopId, Long shopUserId);
}

View File

@@ -52,7 +52,6 @@ public class FunUtils {
/** /**
* 在事务提交后执行方法 * 在事务提交后执行方法
* 异步 执行
* *
* @param func 方法 * @param func 方法
*/ */

View File

@@ -18,7 +18,7 @@
and amount - #{money} >= 0 and amount - #{money} >= 0
</update> </update>
<update id="updateOneOrTwoAmount"> <update id="updateOneOrTwoAmount">
update tb_shop_user_invite update tb_shop_user
<set> <set>
<if test="isOne != null and isOne == 1"> <if test="isOne != null and isOne == 1">
one_income = one_income + #{amount} one_income = one_income + #{amount}
@@ -27,8 +27,7 @@
two_income = two_income + #{amount} two_income = two_income + #{amount}
</if> </if>
</set> </set>
where shop_user_id = #{shopUserId} where id = #{shopUserId}
and shop_id = #{shopId}
</update> </update>
@@ -257,10 +256,10 @@
</select> </select>
<select id="getInviteUser" resultType="com.czg.market.vo.InviteUserVO"> <select id="getInviteUser" resultType="com.czg.market.vo.InviteUserVO">
SELECT SELECT
u.id AS shopUserId, invite.id AS shopUserId,
u.head_img AS headImg, invite.head_img AS headImg,
u.nick_name AS shopUserName, invite.nick_name AS shopUserName,
u.phone AS shopUserPhone, invite.phone AS shopUserPhone,
invite.one_income AS oneIncome, invite.one_income AS oneIncome,
invite.invite_time AS inviteTime, invite.invite_time AS inviteTime,
dist.total_income AS totalIncome, dist.total_income AS totalIncome,
@@ -270,13 +269,12 @@
dist.status AS status, dist.status AS status,
dist.distribution_level_id AS levelId, dist.distribution_level_id AS levelId,
dist.distribution_level_name AS levelName, dist.distribution_level_name AS levelName,
u.distribution_shops AS distributionShops invite.distribution_shops AS distributionShops
FROM tb_shop_user_invite invite FROM tb_shop_user invite
left join tb_shop_user u on invite.shop_user_id = u.id left join mk_distribution_user dist on invite.id = dist.id and dist.shop_id = #{shopId}
left join mk_distribution_user dist on u.id = dist.id and dist.shop_id = #{shopId} WHERE invite.`parent_user_id` = #{distributionUserId}
WHERE invite.`distribution_user_id` = #{distributionUserId} and invite.shop_id = #{shopId}
<if test="distributionLevelId != null">and dist.distribution_level_id = #{distributionLevelId}</if> <if test="distributionLevelId != null">and dist.distribution_level_id = #{distributionLevelId}</if>
<if test="shopUserId != null">and invite.shop_user_id = #{shopUserId}</if> <if test="shopUserId != null">and invite.id = #{shopUserId}</if>
ORDER BY invite.`invite_time` DESC ORDER BY invite.`invite_time` DESC
</select> </select>
</mapper> </mapper>

View File

@@ -1,14 +0,0 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.ShopUserInvite;
/**
* 邀请与上级关联表 映射层。
*
* @author ww
* @since 2025-11-06
*/
public interface ShopUserInviteMapper extends BaseMapper<ShopUserInvite> {
}

View File

@@ -73,12 +73,8 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
private MkDistributionWithdrawFlowService withdrawFlowService; private MkDistributionWithdrawFlowService withdrawFlowService;
@Resource @Resource
private MkDistributionDeliverService distributionDeliverService; private MkDistributionDeliverService distributionDeliverService;
@Resource
private ShopUserInviteService shopUserInviteService;
@Resource @Resource
private AppWxServiceImpl appWxService; private AppWxServiceImpl appWxService;
@DubboReference @DubboReference
private ShopUserService shopUserService; private ShopUserService shopUserService;
@DubboReference @DubboReference
@@ -150,9 +146,9 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
AssertUtil.isNull(shopUser, "店铺用户不存在"); AssertUtil.isNull(shopUser, "店铺用户不存在");
UserInfo userInfo = userInfoService.getById(shopUser.getUserId()); UserInfo userInfo = userInfoService.getById(shopUser.getUserId());
result.put("cashOutAmount", userInfo.getDistributionAmount() == null ? 0.0 : userInfo.getDistributionAmount()); result.put("cashOutAmount", userInfo.getDistributionAmount() == null ? 0.0 : userInfo.getDistributionAmount());
ShopUserInvite shopUserInvite = shopUserInviteService.getOneByShopIdAndShopUserId(shopId, shopUser.getId());
if (shopUserInvite != null && shopUserInvite.getDistributionUserId() != null) { if (shopUser.getParentUserId() != null) {
MkDistributionUser mkDistributionUser = getMkDistributionUserByIdAndShopId(shopUserInvite.getDistributionUserId(), shopId); MkDistributionUser mkDistributionUser = getMkDistributionUserByIdAndShopId(shopUser.getParentUserId(), shopId);
AssertUtil.isNull(mkDistributionUser, "上级分销员不存在"); AssertUtil.isNull(mkDistributionUser, "上级分销员不存在");
ShopUser shopUserParent = shopUserService.getById(mkDistributionUser.getId()); ShopUser shopUserParent = shopUserService.getById(mkDistributionUser.getId());
result.put("parentName", shopUserParent.getNickName()); result.put("parentName", shopUserParent.getNickName());
@@ -181,7 +177,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
if (levelConfig.getId().equals(mkDistributionUser.getDistributionLevelId())) { if (levelConfig.getId().equals(mkDistributionUser.getDistributionLevelId())) {
distributionUser.put("level", levelConfig.getLevel()); distributionUser.put("level", levelConfig.getLevel());
distributionUser.put("levelName", levelConfig.getName()); distributionUser.put("levelName", levelConfig.getName());
distributionUser.put("levelOneCommission", levelConfig.getLevelOneCommission()); distributionUser.put("levelOneCommission", levelConfig.getCommission());
isNextLevel = true; isNextLevel = true;
} }
} }
@@ -234,8 +230,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
public void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException { public void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException {
ShopUser shopUser = shopUserService.getById(param.getId()); ShopUser shopUser = shopUserService.getById(param.getId());
AssertUtil.isNull(shopUser, "店铺用户不存在"); AssertUtil.isNull(shopUser, "店铺用户不存在");
ShopUserInvite shopUserInvite = shopUserInviteService.getOneByShopIdAndShopUserId(param.getShopId(), shopUser.getId()); if (shopUser.getParentUserId() != null) {
if (shopUserInvite != null && shopUserInvite.getDistributionUserId() != null) {
throw new CzgException("店铺用户已绑定分销员"); throw new CzgException("店铺用户已绑定分销员");
} }
MkDistributionUser parent = getOne(QueryWrapper.create().eq(MkDistributionUser::getInviteCode, param.getInviteCode())); MkDistributionUser parent = getOne(QueryWrapper.create().eq(MkDistributionUser::getInviteCode, param.getInviteCode()));
@@ -251,26 +246,28 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
} }
ShopUser parentShopUser = shopUserService.getById(parent.getId()); ShopUser parentShopUser = shopUserService.getById(parent.getId());
AssertUtil.isNull(parentShopUser, "邀请人不存在"); AssertUtil.isNull(parentShopUser, "邀请人不存在");
ShopUserInvite parentShopUserInvite = shopUserInviteService.getOneByShopIdAndShopUserId(param.getShopId(), parentShopUser.getId());
if (parentShopUserInvite != null && parentShopUserInvite.getDistributionUserId() != null && parentShopUserInvite.getDistributionUserId().equals(shopUser.getId())) { if (parentShopUser.getParentUserId() != null && parentShopUser.getParentUserId().equals(shopUser.getId())) {
throw new CzgException("存在绑定关系,不可绑定"); throw new CzgException("存在绑定关系,不可绑定");
} }
if (parentShopUserInvite != null && parentShopUserInvite.getDistributionUserParentId() != null && parentShopUserInvite.getDistributionUserParentId().equals(shopUser.getId())) { if (parentShopUser.getGradeUserId() != null && parentShopUser.getGradeUserId().equals(shopUser.getId())) {
throw new CzgException("存在绑定关系,不可绑定"); throw new CzgException("存在绑定关系,不可绑定");
} }
//更新自己的上级 //更新自己的上级
ShopUserInvite newShopUserInvite = new ShopUserInvite(); shopUser.setParentUserId(parentShopUser.getId());
newShopUserInvite.setShopId(param.getShopId()); shopUser.setGradeUserId(parentShopUser.getParentUserId());
newShopUserInvite.setShopUserId(shopUser.getId());
newShopUserInvite.setDistributionUserId(parentShopUser.getId()); //更新自己的下级 的上级的上级 为自己的上级
newShopUserInvite.setDistributionUserParentId(parentShopUserInvite == null ? null : parentShopUserInvite.getDistributionUserParentId()); ShopUser upShopUser1 = new ShopUser();
newShopUserInvite.setInviteTime(LocalDateTime.now()); upShopUser1.setParentUserId(parentShopUser.getId());
shopUserInviteService.save(newShopUserInvite); upShopUser1.setGradeUserId(parentShopUser.getParentUserId());
if (parentShopUserInvite != null && parentShopUserInvite.getDistributionUserParentId() != null) { shopUserService.update(upShopUser1, QueryWrapper.create().eq(ShopUser::getId, shopUser.getId()));
if (shopUser.getParentUserId() != null) {
//更新自己的下级 的上级的上级 为自己的上级 //更新自己的下级 的上级的上级 为自己的上级
ShopUserInvite childShopUserInvite = new ShopUserInvite(); ShopUser upShopUser = new ShopUser();
childShopUserInvite.setDistributionUserParentId(parentShopUser.getId()); upShopUser.setGradeUserId(shopUser.getParentUserId());
shopUserInviteService.update(childShopUserInvite, QueryWrapper.create().eq(ShopUserInvite::getDistributionUserId, shopUser.getId())); shopUserService.update(upShopUser, QueryWrapper.create().eq(ShopUser::getParentUserId, shopUser.getId()));
} }
MkDistributionUser newDistributionUser = new MkDistributionUser(); MkDistributionUser newDistributionUser = new MkDistributionUser();
@@ -318,9 +315,8 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
public void costUpgradeLevelBefore(Long userId, Long shopId) { public void costUpgradeLevelBefore(Long userId, Long shopId) {
ShopUser shopUser = shopUserService.getShopUserInfo(shopId, userId); ShopUser shopUser = shopUserService.getShopUserInfo(shopId, userId);
costUpgradeLevel(shopUser.getId(), shopId); costUpgradeLevel(shopUser.getId(), shopId);
ShopUserInvite shopUserInvite = shopUserInviteService.getOneByShopIdAndShopUserId(shopId, shopUser.getId()); if (shopUser.getParentUserId() != null) {
if (shopUserInvite != null && shopUserInvite.getDistributionUserId() != null) { costUpgradeLevel(shopUser.getParentUserId(), shopId);
costUpgradeLevel(shopUserInvite.getDistributionUserId(), shopId);
} }
} }
@@ -569,70 +565,40 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
@GlobalTransactional @GlobalTransactional
protected void deepReward(ShopUser orderSourceShopUser, MkDistributionLevelConfig parentLevel, MkDistributionConfigVO config, protected boolean deepReward(ShopUser orderSourceShopUser, BigDecimal commission, MkDistributionConfigVO config,
MkDistributionUser currentDistributionUser, BigDecimal amount, Long sourceId, String type, String orderNo, Integer currentLevel) { MkDistributionUser currentDistributionUser, BigDecimal amount, Long sourceId,
if (currentLevel > 2) { String type, String orderNo, Integer currentLevel) {
return;
}
// 当前分销员 // 当前分销员
AssertUtil.isNull(currentDistributionUser, "分销员不存在"); AssertUtil.isNull(currentDistributionUser, "分销员不存在");
AssertUtil.isTrue(currentDistributionUser.getStatus() != 1, "分销员未开启"); AssertUtil.isTrue(currentDistributionUser.getStatus() != 1, "分销员未开启");
if (commission.compareTo(BigDecimal.ZERO) <= 0) {
// ShopUser currentShopUser = shopUserService.getById(currentDistributionUser.getId()); return false;
ShopUserInvite currentShopUser = shopUserInviteService.getOneByShopIdAndShopUserId(config.getShopId(), currentDistributionUser.getId());
MkDistributionLevelConfig level = levelConfigService.getById(currentDistributionUser.getDistributionLevelId());
// 校验剩余分成比例
BigDecimal finalCommission = parentLevel == null ? level.getLevelOneCommission() : level.getLevelOneCommission().subtract(parentLevel.getLevelOneCommission());
if (finalCommission.compareTo(BigDecimal.ZERO) <= 0) {
log.info("当前分销员: {}, 分销等级: {}, 剩余比例: {}, 不参与分销", currentDistributionUser.getId(), level.getId(), finalCommission);
return;
} }
// 金额
// 上上级分销员 BigDecimal rewardAmount = amount.multiply(commission.divide(BigDecimal.valueOf(100))).setScale(2, RoundingMode.FLOOR);
if (currentShopUser != null && currentShopUser.getDistributionUserId() != null) { if (rewardAmount.compareTo(new BigDecimal("0.01")) < 0) {
MkDistributionUser parent = getMkDistributionUserByIdAndShopId(currentShopUser.getDistributionUserId(), config.getShopId()); return false;
try {
deepReward(orderSourceShopUser, level, config, parent, amount, sourceId, type, orderNo, currentLevel + 1);
} catch (Exception e) {
log.warn("分销奖励失败: {}", e.getMessage());
}
} }
AssertUtil.isNull(level, "分销等级不存在");
log.info("当前分销员: {}, 上级分销员: {}, 分销等级: {}", currentDistributionUser.getId(), currentShopUser == null ? null : currentShopUser.getDistributionUserId(), level.getId());
if (config.getRewardCount() != null && config.getRewardCount() > 0) { if (config.getRewardCount() != null && config.getRewardCount() > 0) {
long count = distributionFlowService.count(new QueryWrapper() long count = distributionFlowService.count(new QueryWrapper()
.eq(MkDistributionFlow::getShopId, config.getShopId()).eq(MkDistributionFlow::getShopUserId, currentDistributionUser.getId())); .eq(MkDistributionFlow::getShopId, config.getShopId()).eq(MkDistributionFlow::getShopUserId, currentDistributionUser.getId()));
if (count >= config.getRewardCount()) { if (count >= config.getRewardCount()) {
log.info("分销员{}已达到奖励次数上限, 次数: {}", currentDistributionUser.getId(), config.getRewardCount()); log.info("分销员{}已达到奖励次数上限, 次数: {}", currentDistributionUser.getId(), config.getRewardCount());
return; return false;
} else {
log.info("分销员奖励次数: {}", count);
} }
} }
// 店铺信息
BigDecimal rewardAmount;
// if (currentLevel == 1) {
// rewardAmount = amount.multiply(level.getLevelOneCommission().divide(BigDecimal.valueOf(100), RoundingMode.DOWN));
// } else {
// rewardAmount = amount.multiply(level.getLevelTwoCommission().divide(BigDecimal.valueOf(100), RoundingMode.DOWN));
// }
rewardAmount = amount.multiply(finalCommission.divide(BigDecimal.valueOf(100), RoundingMode.DOWN));
// 延时发放时间 // 延时发放时间
LocalDateTime delayTime = config.getSettlementDay() == null || config.getSettlementDay() == 0 ? null : DateUtil.offsetDay(DateUtil.date(), config.getSettlementDay()).toLocalDateTime(); LocalDateTime delayTime = config.getSettlementDay() == null || config.getSettlementDay() == 0 ? null : DateUtil.offsetDay(DateUtil.date(), config.getSettlementDay()).toLocalDateTime();
// 用户分账明细 // 用户分账明细
ShopUser shopUser = shopUserService.getById(currentDistributionUser.getId()); ShopUser shopUser = shopUserService.getById(currentDistributionUser.getId());
MkDistributionFlow mkDistributionFlow = new MkDistributionFlow().setShopUserId(currentDistributionUser.getId()) MkDistributionFlow mkDistributionFlow = new MkDistributionFlow().setShopUserId(currentDistributionUser.getId())
.setShopId(currentDistributionUser.getShopId()).setDistributionUserId(currentDistributionUser.getId()) .setShopId(currentDistributionUser.getShopId()).setDistributionUserId(currentDistributionUser.getId())
.setUserId(shopUser.getUserId()) .setUserId(shopUser.getUserId())
.setNickName(shopUser.getNickName()).setSourceShopUserId(orderSourceShopUser.getId()).setSourceNickName(orderSourceShopUser.getNickName()) .setNickName(shopUser.getNickName()).setSourceShopUserId(orderSourceShopUser.getId()).setSourceNickName(orderSourceShopUser.getNickName())
.setCommission(finalCommission).setParentCommission(parentLevel != null ? parentLevel.getLevelOneCommission() : null) .setCommission(commission)
.setLevelId(currentDistributionUser.getDistributionLevelId()).setLevel(currentLevel == 1 ? 1 : 2).setOrderNo(orderNo) .setLevelId(currentDistributionUser.getDistributionLevelId()).setLevel(currentLevel).setOrderNo(orderNo)
.setSourceId(sourceId).setAmount(amount).setType(type) .setSourceId(sourceId).setAmount(amount).setType(type)
.setRewardAmount(rewardAmount).setBillNo(IdUtil.simpleUUID()); .setRewardAmount(rewardAmount).setBillNo(IdUtil.simpleUUID());
@@ -655,6 +621,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
log.info("延时分销开始"); log.info("延时分销开始");
updateIncome(rewardAmount, BigDecimal.ZERO, BigDecimal.ZERO, currentDistributionUser.getId(), shopUser.getUserId(), shopUser.getId(), config.getShopId(), currentLevel == 1 ? 1 : 2); updateIncome(rewardAmount, BigDecimal.ZERO, BigDecimal.ZERO, currentDistributionUser.getId(), shopUser.getUserId(), shopUser.getId(), config.getShopId(), currentLevel == 1 ? 1 : 2);
} }
return true;
} }
@Override @Override
@@ -712,19 +679,24 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
AssertUtil.isTrue(amount.compareTo(BigDecimal.ZERO) == 0, "分销金额不能为0"); AssertUtil.isTrue(amount.compareTo(BigDecimal.ZERO) == 0, "分销金额不能为0");
MkDistributionConfigVO config = mkDistributionConfigService.detail(shopId); MkDistributionConfigVO config = mkDistributionConfigService.detail(shopId);
AssertUtil.isTrue(config.getIsEnable() != 1, "分销未开启"); AssertUtil.isTrue(config.getIsEnable() != 1, "分销未开启");
// 当前用户上级分销员 // 产生消费的用户
ShopUser sourceShopUserInfo = shopUserService.getShopUserInfo(shopId, sourceUserId); ShopUser curUser = shopUserService.getShopUserInfo(shopId, sourceUserId);
if (sourceShopUserInfo == null) { if (curUser == null || curUser.getParentUserId() == null) {
return; return;
} }
ShopUserInvite sourceInviteUser = shopUserInviteService.getOneByShopIdAndShopUserId(shopId, sourceShopUserInfo.getId());
if (sourceInviteUser.getDistributionUserId() == null) {
return;
}
log.info("开始分销, 当前来源用户: {}, shopId: {}, 邀请人id: {}", sourceUserId, shopId, sourceInviteUser.getDistributionUserId());
MkDistributionUser distributionUser = getMkDistributionUserByIdAndShopId(sourceInviteUser.getDistributionUserId(), shopId); log.info("开始分销, 当前来源用户: {}, shopId: {}, 邀请人id: {}", sourceUserId, shopId, curUser.getParentUserId());
deepReward(sourceShopUserInfo, null, config, distributionUser, amount, sourceId, type, orderNo, 1);
MkDistributionUser distributionUser = getMkDistributionUserByIdAndShopId(curUser.getParentUserId(), shopId);
MkDistributionLevelConfig level = levelConfigService.getById(distributionUser.getDistributionLevelId());
deepReward(curUser, level.getCommission(), config, distributionUser,
amount, sourceId, type, orderNo, 1);
if (curUser.getGradeUserId() != null) {
MkDistributionUser parentDis = getMkDistributionUserByIdAndShopId(curUser.getGradeUserId(), shopId);
MkDistributionLevelConfig parentDisLevel = levelConfigService.getById(parentDis.getDistributionLevelId());
deepReward(curUser, parentDisLevel.getCommission().subtract(level.getCommission()), config, parentDis,
amount, sourceId, type, orderNo, 2);
}
}); });
distributionDeliverService.save(deliver); distributionDeliverService.save(deliver);
} }

View File

@@ -1,25 +0,0 @@
package com.czg.service.market.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.ShopUserInvite;
import com.czg.market.service.ShopUserInviteService;
import com.czg.service.market.mapper.ShopUserInviteMapper;
import org.springframework.stereotype.Service;
/**
* 邀请与上级关联表 服务层实现。
*
* @author ww
* @since 2025-11-06
*/
@Service
public class ShopUserInviteServiceImpl extends ServiceImpl<ShopUserInviteMapper, ShopUserInvite> implements ShopUserInviteService {
@Override
public ShopUserInvite getOneByShopIdAndShopUserId(Long shopId, Long shopUserId) {
return getOne(QueryWrapper.create()
.eq(ShopUserInvite::getShopId, shopId)
.eq(ShopUserInvite::getShopUserId, shopUserId));
}
}

View File

@@ -296,6 +296,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
} }
if (shopUser.getMemberLevelId() == null) { if (shopUser.getMemberLevelId() == null) {
log.warn("会员等级不存在, 店铺id: {}, 用户id: {}", shopUser.getMainShopId(), shopUser.getUserId()); log.warn("会员等级不存在, 店铺id: {}, 用户id: {}", shopUser.getMainShopId(), shopUser.getUserId());
return false;
} }
MemberConfigVO memberConfig = detail(shopUser.getMainShopId()); MemberConfigVO memberConfig = detail(shopUser.getMainShopId());
if (memberConfig == null) { if (memberConfig == null) {

View File

@@ -4,17 +4,15 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.czg.market.dto.MemberLevelDTO; import com.czg.market.dto.MemberLevelDTO;
import com.czg.market.entity.MemberLevelConfig;
import com.czg.market.service.MemberLevelConfigService;
import com.czg.market.service.ShopCouponService; import com.czg.market.service.ShopCouponService;
import com.czg.market.vo.MemberLevelVO; import com.czg.market.vo.MemberLevelVO;
import com.czg.service.market.mapper.TbMemberLevelConfigMapper; import com.czg.service.market.mapper.TbMemberLevelConfigMapper;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MemberLevelConfig;
import com.czg.market.service.MemberLevelConfigService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -33,20 +31,16 @@ public class TbMemberLevelConfigServiceImpl extends ServiceImpl<TbMemberLevelCon
@Override @Override
public ArrayList<MemberLevelVO> listInfo(Long shopId) { public ArrayList<MemberLevelVO> listInfo(Long shopId) {
List<MemberLevelConfig> levelConfigs = list(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)); List<MemberLevelConfig> levelConfigs = list(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId));
ArrayList<MemberLevelVO> memberLevelVOS = new ArrayList<>(); ArrayList<MemberLevelVO> memberLevels = new ArrayList<>();
levelConfigs.forEach(memberLevelConfig -> { levelConfigs.forEach(memberLevelConfig -> memberLevels.add(transVO(memberLevelConfig)));
memberLevelVOS.add(transVO(memberLevelConfig)); return memberLevels;
});
return memberLevelVOS;
} }
private MemberLevelVO transVO(MemberLevelConfig memberLevelConfig) { private MemberLevelVO transVO(MemberLevelConfig memberLevelConfig) {
MemberLevelVO levelVO = BeanUtil.copyProperties(memberLevelConfig, MemberLevelVO.class, "cycleRewardCouponList"); MemberLevelVO levelVO = BeanUtil.copyProperties(memberLevelConfig, MemberLevelVO.class, "cycleRewardCouponList");
if (StrUtil.isNotBlank(memberLevelConfig.getCycleRewardCouponList())) { if (StrUtil.isNotBlank(memberLevelConfig.getCycleRewardCouponList())) {
List<MemberLevelDTO.ConfigCoupon> coupons = JSONArray.parseArray(memberLevelConfig.getCycleRewardCouponList()).toList(MemberLevelDTO.ConfigCoupon.class); List<MemberLevelDTO.ConfigCoupon> coupons = JSONArray.parseArray(memberLevelConfig.getCycleRewardCouponList()).toList(MemberLevelDTO.ConfigCoupon.class);
coupons.forEach(item -> { coupons.forEach(item -> item.setCoupon(shopCouponService.getById(item.getCoupon().getId())));
item.setCoupon(shopCouponService.getById(item.getCoupon().getId()));
});
levelVO.setCycleRewardCouponList(coupons); levelVO.setCycleRewardCouponList(coupons);
} }
return levelVO; return levelVO;
@@ -54,6 +48,7 @@ public class TbMemberLevelConfigServiceImpl extends ServiceImpl<TbMemberLevelCon
@Override @Override
public MemberLevelVO detail(Long memberLevelId) { public MemberLevelVO detail(Long memberLevelId) {
MemberLevelConfig memberLevelConfig = getById(memberLevelId); MemberLevelConfig memberLevelConfig = getById(memberLevelId);
if (memberLevelConfig == null) { if (memberLevelConfig == null) {
return null; return null;

View File

@@ -65,15 +65,13 @@
<select id="getOrderConsumeAmountByList" resultType="java.math.BigDecimal"> <select id="getOrderConsumeAmountByList" resultType="java.math.BigDecimal">
SELECT IFNULL(SUM(ord.pay_amount), 0) AS totalAmount SELECT IFNULL(SUM(ord.pay_amount), 0) AS totalAmount
FROM tb_shop_user_invite invite FROM tb_shop_user invite
INNER JOIN tb_shop_user su on invite.shop_user_id = su.id INNER JOIN tb_order_info ord ON invite.user_id = ord.user_id
INNER JOIN tb_order_info ord ON su.user_id = ord.user_id
and invite.shop_id = #{shopId}
AND ord.shop_id = #{shopId} AND ord.shop_id = #{shopId}
AND ord.STATUS = 'done' AND ord.STATUS = 'done'
AND ord.pay_type NOT IN ('vip_pay', 'credit_pay') AND ord.pay_type NOT IN ('vip_pay', 'credit_pay')
AND ord.paid_time >= invite.invite_time AND ord.paid_time >= invite.invite_time
WHERE invite.distribution_user_id = #{inviterId} WHERE invite.parent_user_id = #{inviterId}
</select> </select>
<select id="getOrderConsumeAmountById" resultType="java.math.BigDecimal"> <select id="getOrderConsumeAmountById" resultType="java.math.BigDecimal">

View File

@@ -1,7 +0,0 @@
<?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.market.mapper.ShopUserInviteMapper">
</mapper>

View File

@@ -14,7 +14,6 @@ import com.czg.pay.PolyMerchantDTO;
import com.czg.service.order.mapper.ShopMerchantMapper; import com.czg.service.order.mapper.ShopMerchantMapper;
import com.czg.service.order.service.ShopDirectMerchantService; import com.czg.service.order.service.ShopDirectMerchantService;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.CzgStrUtils;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@@ -81,10 +80,12 @@ public class ShopMerchantServiceImpl extends ServiceImpl<ShopMerchantMapper, Sho
} }
shopMerchant.setShopId(shopMerchantParam.getShopId()); shopMerchant.setShopId(shopMerchantParam.getShopId());
if (isUp) { if (isUp) {
shopMerchant.setChannel(CzgStrUtils.getStrOrNull(shopMerchantParam.getChannel())); if (StrUtil.isNotBlank(shopMerchantParam.getChannel())) {
shopMerchant.setChannel(shopMerchantParam.getChannel());
}
shopMerchant.setRelatedId(shopMerchantParam.getRelatedId()); shopMerchant.setRelatedId(shopMerchantParam.getRelatedId());
if (shopMerchantParam.getRelatedId() == null || !shopMerchantParam.getRelatedId().equals(shopMerchant.getRelatedId())) { if (shopMerchant.getRelatedId() != null && !shopMerchantParam.getRelatedId().equals(shopMerchant.getRelatedId())) {
ShopDirectMerchant shopDirectMerchant = shopDirectMerchantService.getById(shopMerchantParam.getRelatedId()); ShopDirectMerchant shopDirectMerchant = shopDirectMerchantService.getById(shopMerchant.getRelatedId());
if (shopDirectMerchant != null) { if (shopDirectMerchant != null) {
NativeMerchantDTO nativeMerchantDTO = new NativeMerchantDTO(); NativeMerchantDTO nativeMerchantDTO = new NativeMerchantDTO();
nativeMerchantDTO.setWechatMerchantId(shopDirectMerchant.getWechatMerchantId()); nativeMerchantDTO.setWechatMerchantId(shopDirectMerchant.getWechatMerchantId());

View File

@@ -53,18 +53,6 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
@Resource @Resource
private WxAccountUtil wxAccountUtil; private WxAccountUtil wxAccountUtil;
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
/*if (StrUtil.isNotEmpty(param.getName())) {
queryWrapper.like(ConsStockFlow::getName, param.getName());
}*/
Long shopId = StpKit.USER.getShopId(0L);
queryWrapper.eq(ConsStockFlow::getShopId, shopId);
queryWrapper.orderBy(ConsStockFlow::getId, false);
return queryWrapper;
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param) { public ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param) {
@@ -72,7 +60,6 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
Long createUserId = StpKit.USER.getLoginIdAsLong(); Long createUserId = StpKit.USER.getLoginIdAsLong();
String createUserName = StpKit.USER.getAccount(); String createUserName = StpKit.USER.getAccount();
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class); ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
List<ConsStockFlow> insertList = new ArrayList<>(); List<ConsStockFlow> insertList = new ArrayList<>();
List<ConsInfo> updateStockList = new ArrayList<>(); List<ConsInfo> updateStockList = new ArrayList<>();
for (ConsInOutStockBodyParam entity : param.getBodyList()) { for (ConsInOutStockBodyParam entity : param.getBodyList()) {
@@ -251,15 +238,7 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
Long shopId = entity.getShopId(); Long shopId = entity.getShopId();
BigDecimal afterNumber = entity.getAfterNumber(); BigDecimal afterNumber = entity.getAfterNumber();
ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId()); ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId());
String shopName = ""; String shopName = productMapper.getShopName(shopId);
try {
shopName = StpKit.USER.getShopName();
} catch (Exception e) {
log.error("获取店铺名称失败");
}
if (StrUtil.isEmpty(shopName)) {
shopName = productMapper.getShopName(shopId);
}
BigDecimal conWarning = consInfo.getConWarning(); BigDecimal conWarning = consInfo.getConWarning();
// 库存小于警告值,发送消息提醒 // 库存小于警告值,发送消息提醒
if (NumberUtil.isLess(afterNumber, conWarning)) { if (NumberUtil.isLess(afterNumber, conWarning)) {
@@ -268,12 +247,8 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
return; return;
} }
String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning); String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning);
String finalShopName = shopName; ThreadUtil.execAsync(() -> openIdList.parallelStream().forEach(openId ->
ThreadUtil.execAsync(() -> { wxAccountUtil.sendStockMsg("耗材库存预警", shopName, conName, afterNumber, openId)));
openIdList.parallelStream().forEach(openId -> {
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
});
});
} }
} }
} }

View File

@@ -53,12 +53,8 @@ public class ProductStockFlowServiceImpl extends ServiceImpl<ProductStockFlowMap
} }
String productName = StrUtil.sub(product.getName(), 0, 10).concat("..."); String productName = StrUtil.sub(product.getName(), 0, 10).concat("...");
String conName = StrUtil.format("{}数量<预警值{}", productName, warnLine); String conName = StrUtil.format("{}数量<预警值{}", productName, warnLine);
String finalShopName = shopName; ThreadUtil.execAsync(() -> openIdList.parallelStream().forEach(openId ->
ThreadUtil.execAsync(() -> { wxAccountUtil.sendStockMsg("商品库存预警", shopName, conName, afterNumber, openId)));
openIdList.parallelStream().forEach(openId -> {
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
});
});
} }
} }
} }

View File

@@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.czg.exception.CzgException;
import com.czg.service.RedisService; import com.czg.service.RedisService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.Data; import lombok.Data;
@@ -16,7 +17,6 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -32,6 +32,7 @@ import java.util.Map;
@Component @Component
public class WxAccountUtil { public class WxAccountUtil {
//银收客公众号推送
@Value("${wx.ysk.appId}") @Value("${wx.ysk.appId}")
private String appId = "wx212769170d2c6b2a"; private String appId = "wx212769170d2c6b2a";
@Value("${wx.ysk.secrete}") @Value("${wx.ysk.secrete}")
@@ -59,84 +60,73 @@ public class WxAccountUtil {
linkedHashMap.put("47003", "参数错误"); linkedHashMap.put("47003", "参数错误");
} }
public String getAccessToken() {
String accessToken = Convert.toStr(redisService.get("accessToken"));
if (StrUtil.isNotEmpty(accessToken)) {
return accessToken;
}
String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appId, secrete));
JSONObject respInfo = JSONObject.parseObject(resp);
if (!respInfo.containsKey("access_token")) {
log.warn("公众号获取token失败, 响应内容: {}", resp);
throw new RuntimeException(resp);
}
accessToken = respInfo.getString("access_token");
int expiresIn = respInfo.getInteger("expires_in");
redisService.set("accessToken", accessToken, expiresIn - 10);
return accessToken;
}
public JSONObject sendTemplateMsg(String templateId, String toUserOpenId, Map<String, Object> data) {
log.info("开始发送微信模板消息, 接收用户openId: {}, 消息数据: {}", toUserOpenId, data);
String accessToken = getAccessToken();
JSONObject object1 = new JSONObject();
object1.put("template_id", templateId);
object1.put("touser", toUserOpenId);
object1.put("data", data);
String response = HttpRequest.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".concat(accessToken)).body(object1.toString()).execute().body();
log.info("微信模板消息发送成功,响应内容:{}", response);
JSONObject resObj = JSONObject.parseObject(response);
if (ObjectUtil.isNotEmpty(resObj) && ObjectUtil.isNotNull(resObj) && "0".equals(resObj.get("errcode") + "")) {
return resObj;
}
throw new RuntimeException(linkedHashMap.getOrDefault(resObj.get("errcode") + "", "未知错误"));
}
public void sendOperationMsg(List<String> openIdList, String userName, String operationDesc) { public void sendOperationMsg(List<String> openIdList, String userName, String operationDesc) {
openIdList.forEach(openId -> { openIdList.forEach(openId -> {
Map<String, Object> data = new HashMap<String, Object>() {{ Map<String, Object> data = Map.of(
put("thing19", new HashMap<String, Object>() {{ "thing19", Map.of("value", userName),
put("value", userName); "thing8", Map.of("value", StrUtil.sub(operationDesc, 0, 20)),
}}); "time21", Map.of("value", DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"))
put("thing8", new HashMap<String, Object>() {{ );
put("value", StrUtil.sub(operationDesc,0,20));
}});
put("time21", new HashMap<String, Object>() {{
put("value", DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
}});
}};
log.info("开始发送敏感操作消息, 接收用户openId: {}, 操作用户: {}, 操作描述: {}", openId, userName, operationDesc);
try { try {
sendTemplateMsg(operationMsgTmpId, openId, data); sendTemplateMsg("敏感操作", operationMsgTmpId, openId, data);
} catch (Exception e) { } catch (Exception e) {
log.error("发送失败, openId: {}, 响应: {}", openId, e.getMessage()); log.error("发送失败, openId: {}, 响应: {}", openId, e.getMessage());
} }
}); });
} }
public void sendStockMsg(String shopName, String productName, BigDecimal stockNum, String openId) { public void sendStockMsg(String typeName, String shopName, String productName, BigDecimal stockNum, String openId) {
String stockNumStr = stockNum.toPlainString(); String stockNumStr = stockNum.toPlainString();
Map<String, Object> data = new HashMap<String, Object>() {{ Map<String, Object> data = Map.of(
put("thing22", new HashMap<String, Object>() {{ //品名
put("value", shopName); "thing34", Map.of("value", typeName),
}}); //商品名称
put("thing4", new HashMap<String, Object>() {{ "thing4", Map.of("value", productName),
put("value", productName); //商品数量
}}); "number5", Map.of("value", stockNumStr),
put("number5", new HashMap<String, Object>() {{ //商家名称
put("value", stockNumStr); "thing22", Map.of("value", shopName)
}}); );
}};
log.info("开始发送库存预警消息, 接收用户openId: {}, 消息数据: {}", openId, data);
try { try {
sendTemplateMsg(warnMsgTmpId, openId, data); sendTemplateMsg("库存预警", warnMsgTmpId, openId, data);
} catch (Exception e) { } catch (Exception e) {
log.error("发送失败, openId:{}, msg: {}", openId, e.getMessage()); log.error("发送失败, openId:{}, msg: {}", openId, e.getMessage());
} }
} }
public String getAccessToken() {
synchronized (this) {
String accessToken = Convert.toStr(redisService.get("accessToken"));
if (StrUtil.isNotEmpty(accessToken)) {
return accessToken;
}
String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appId, secrete));
JSONObject respInfo = JSONObject.parseObject(resp);
if (!respInfo.containsKey("access_token")) {
log.warn("公众号获取token失败, 响应内容: {}", resp);
throw new RuntimeException(resp);
}
accessToken = respInfo.getString("access_token");
int expiresIn = respInfo.getInteger("expires_in");
redisService.set("accessToken", accessToken, expiresIn - 10);
return accessToken;
}
}
public JSONObject sendTemplateMsg(String detail, String templateId, String toUserOpenId, Map<String, Object> data) {
log.info("银收客公众号消息推送,消息类型:{} 接收用户openId: {}, 消息数据: {}", detail, toUserOpenId, data);
String accessToken = getAccessToken();
JSONObject object1 = new JSONObject();
object1.put("template_id", templateId);
object1.put("touser", toUserOpenId);
object1.put("data", data);
String response = HttpRequest.post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".concat(accessToken)).body(object1.toString()).execute().body();
log.info("银收客公众号消息推送,响应内容:{}", response);
JSONObject resObj = JSONObject.parseObject(response);
if (ObjectUtil.isNotEmpty(resObj) && ObjectUtil.isNotNull(resObj) && "0".equals(resObj.get("errcode") + "")) {
return resObj;
}
throw new CzgException(linkedHashMap.getOrDefault(resObj.get("errcode") + "", "未知错误"));
}
} }

View File

@@ -149,7 +149,7 @@
and t1.shop_id = #{shopId} and t1.shop_id = #{shopId}
</where> </where>
<if test="idList != null"> <if test="idList != null">
and t1.id in and (t1.id in
<foreach item="item" collection="idList" separator="," open="(" close=")"> <foreach item="item" collection="idList" separator="," open="(" close=")">
#{item} #{item}
</foreach> </foreach>
@@ -157,6 +157,7 @@
<foreach item="item" collection="idList" separator="," open="(" close=")"> <foreach item="item" collection="idList" separator="," open="(" close=")">
#{item} #{item}
</foreach> </foreach>
)
</if> </if>
order by t1.sort desc,t1.id desc order by t1.sort desc,t1.id desc
</select> </select>