多店铺需求
This commit is contained in:
parent
c424f3613f
commit
c4cdc83ec3
|
|
@ -51,9 +51,7 @@ public class ShopBranchController {
|
|||
public CzgResult<Void> settingDataSyncMethod(@RequestParam String dataSyncMethod) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
shopBranchService.settingDataSyncMethod(shopId, dataSyncMethod);
|
||||
CzgResult<Void> ret = CzgResult.success();
|
||||
ret.setMsg("设置成功,数据正在后台同步中...");
|
||||
return ret;
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,7 +63,9 @@ public class ShopBranchController {
|
|||
@OperationLog("分店管理-同步启用")
|
||||
public CzgResult<Void> dataSyncEnable(@RequestParam Long branchShopId) {
|
||||
shopBranchService.dataSyncEnable(branchShopId);
|
||||
return CzgResult.success();
|
||||
CzgResult<Void> ret = CzgResult.success();
|
||||
ret.setMsg("启用成功,数据正在后台同步中...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -125,4 +125,17 @@ public class ShopUser implements Serializable {
|
|||
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 是否已经合并数据到主店 1-是 0-否 默认0
|
||||
*/
|
||||
private Integer isMergedToHead;
|
||||
/**
|
||||
* 已经合并过来的用户信息,jsonArray格式,[{"id":1,"shopId":2,...},{"id":1,"shopId":2,...}]
|
||||
*/
|
||||
private String mergedUsers;
|
||||
/**
|
||||
* 适用门店id集合,逗号分隔,例如:0,1,2,3,...查询的时候 all_shop_ids like '%,1,%';
|
||||
*/
|
||||
private String allShopIds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package com.czg.account.service;
|
||||
|
||||
/**
|
||||
* 店铺用户同步Service
|
||||
* @author tankaikai
|
||||
* @since 2025-04-08 10:17
|
||||
*/
|
||||
public interface ShopUserSyncService {
|
||||
|
||||
/**
|
||||
* 同步合并主分店会员信息
|
||||
*
|
||||
* @param headShopId 主店id
|
||||
* @param branchShopId 分店id
|
||||
*/
|
||||
void syncMergeShopUser(Long headShopId, Long branchShopId);
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package com.czg.product.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author ww
|
||||
* @description
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.czg.service.account.service.impl;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.czg.account.dto.ShopBranchDTO;
|
||||
import com.czg.account.entity.ShopConfig;
|
||||
|
|
@ -8,8 +9,11 @@ import com.czg.account.enums.BranchDataSyncMethodEnum;
|
|||
import com.czg.account.enums.ShopTypeEnum;
|
||||
import com.czg.account.param.ShopBranchParam;
|
||||
import com.czg.account.service.ShopBranchService;
|
||||
import com.czg.account.service.ShopUserSyncService;
|
||||
import com.czg.account.service.SyncNoticeService;
|
||||
import com.czg.enums.YesNoEnum;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.product.service.ShopSyncService;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.account.mapper.ShopConfigMapper;
|
||||
import com.czg.service.account.mapper.ShopInfoMapper;
|
||||
|
|
@ -34,9 +38,15 @@ public class ShopBranchServiceImpl implements ShopBranchService {
|
|||
|
||||
@Resource
|
||||
private ShopConfigMapper shopConfigMapper;
|
||||
|
||||
@Resource
|
||||
private ShopInfoMapper shopInfoMapper;
|
||||
@Resource
|
||||
private ShopSyncService shopSyncService;
|
||||
@Resource
|
||||
private ShopUserSyncService shopUserSyncService;
|
||||
@Resource
|
||||
private SyncNoticeService syncNoticeService;
|
||||
|
||||
|
||||
@Override
|
||||
public Page<ShopBranchDTO> findPage(ShopBranchParam param) {
|
||||
|
|
@ -98,7 +108,14 @@ public class ShopBranchServiceImpl implements ShopBranchService {
|
|||
branchConfig.setIsEnableConsSync(YesNoEnum.YES.value());
|
||||
branchConfig.setIsEnableVipSync(YesNoEnum.YES.value());
|
||||
shopConfigMapper.update(branchConfig);
|
||||
// TODO 异步事务同步商品数据、会员数据、耗材数据
|
||||
ThreadUtil.execAsync(() -> {
|
||||
// 同步商品和耗材
|
||||
shopSyncService.sync(shopId, branchShop.getId());
|
||||
});
|
||||
ThreadUtil.execAsync(() -> {
|
||||
// 同步会员信息
|
||||
shopUserSyncService.syncMergeShopUser(shopId, branchShop.getId());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
package com.czg.service.account.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopUserSyncService;
|
||||
import com.czg.enums.YesNoEnum;
|
||||
import com.czg.service.account.mapper.ShopUserMapper;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 店铺用户同步Service实现类
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-04-08 10:18
|
||||
*/
|
||||
@Service
|
||||
public class ShopUserSyncServiceImpl implements ShopUserSyncService {
|
||||
|
||||
@Resource
|
||||
private ShopUserMapper shopUserMapper;
|
||||
|
||||
/**
|
||||
* 同步合并主分店会员信息
|
||||
*
|
||||
* @param headShopId 主店id
|
||||
* @param branchShopId 分店id
|
||||
*/
|
||||
@Override
|
||||
public synchronized void syncMergeShopUser(Long headShopId, Long branchShopId) {
|
||||
// 合并前置逻辑:查询主店、分店手机号码不为空的会员信息,分店和主店手机号码进行匹配
|
||||
// 合并逻辑1:如果手机号码一致,则把分店会员信息中的 积分、余额、消费金额、消费次数合并到主店会员信息中,把分店这些信息清零,is_merged_to_head的意思是是否已经合并数据到主店 set is_merged_to_head = 1
|
||||
// 合并逻辑2:分店手机号码在主店中不存在,则在主店创建新的会员,把分店分店会员信息中的 积分、余额、消费金额、消费次数合并到主店会员信息中,把分店这些信息清零,set is_merged_to_head = 1
|
||||
// 合并逻辑3:主店没有分店有,把分店会员信息copy到主店,更改shop_id,all_shop_ids,把分店这些信息清零, 把分店会员信息jsonArray格式化存储至merged_users字段中,便于后续查询合并前会员信息,新增字段,适用门店id(用英文逗号隔开,如:0,1,2,3, 查询时用适用门店id like %,1,% and is_merged_to_head = 0)
|
||||
// 合并逻辑4:当用户补充了手机号码或则修改了手机号码,则需要按照手机号码进行会员信息合并,把逻辑1,2,3重新执行一遍
|
||||
// 查询逻辑:在下单时选择会员信息时,查询时用适用门店id like %,1,% and is_merged_to_head = 0
|
||||
List<ShopUser> headShopUserList = shopUserMapper.selectListByQuery(QueryWrapper.create().eq(ShopUser::getShopId, headShopId).isNotNull(ShopUser::getPhone));
|
||||
List<ShopUser> branchShopUserList = shopUserMapper.selectListByQuery(QueryWrapper.create().eq(ShopUser::getShopId, branchShopId).isNotNull(ShopUser::getPhone));
|
||||
// 如果分店没有符合条件的会员,则不进行合并
|
||||
if (CollUtil.isEmpty(branchShopUserList)) {
|
||||
return;
|
||||
}
|
||||
Map<String, ShopUser> headShopUserKv = headShopUserList.stream().collect(Collectors.toMap(ShopUser::getPhone, shopUser -> shopUser));
|
||||
Map<String, ShopUser> branchShopUserKv = branchShopUserList.stream().collect(Collectors.toMap(ShopUser::getPhone, shopUser -> shopUser));
|
||||
|
||||
Set<String> headShopPhoneList = headShopUserList.stream().map(ShopUser::getPhone).collect(Collectors.toSet());
|
||||
Set<String> branchShopPhoneList = branchShopUserList.stream().map(ShopUser::getPhone).collect(Collectors.toSet());
|
||||
|
||||
Set<String> phoneSet = new HashSet<>();
|
||||
phoneSet.addAll(headShopPhoneList);
|
||||
phoneSet.addAll(branchShopPhoneList);
|
||||
|
||||
// 执行合并逻辑
|
||||
for (String phone : phoneSet) {
|
||||
ShopUser headShopUser = headShopUserKv.get(phone);
|
||||
ShopUser branchShopUser = branchShopUserKv.get(phone);
|
||||
// 1.如果都有
|
||||
if (ObjUtil.isNotNull(headShopUser) && ObjUtil.isNotNull(branchShopUser)) {
|
||||
toMergeCase1(headShopUser, branchShopUser);
|
||||
// 2.如果主店有,分店没有
|
||||
} else if (ObjUtil.isNotNull(headShopUser) && ObjUtil.isNull(branchShopUser)) {
|
||||
toMergeCase2(headShopUser, branchShopId);
|
||||
// 3.如果主店没有,分店有
|
||||
} else if (ObjUtil.isNull(headShopUser) && ObjUtil.isNotNull(branchShopUser)) {
|
||||
toMergeCase3(headShopId, branchShopUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并会员信息 1.如果都有
|
||||
*
|
||||
* @param headShopUser 主店会员
|
||||
* @param branchShopUser 分店会员
|
||||
*/
|
||||
public void toMergeCase1(ShopUser headShopUser, ShopUser branchShopUser) {
|
||||
headShopUser.setAccountPoints(NumberUtil.nullToZero(headShopUser.getAccountPoints()) + (NumberUtil.nullToZero(branchShopUser.getAccountPoints())));
|
||||
headShopUser.setAmount(NumberUtil.nullToZero(headShopUser.getAmount()).add(NumberUtil.nullToZero(branchShopUser.getAmount())));
|
||||
headShopUser.setConsumeCount(NumberUtil.nullToZero(headShopUser.getConsumeCount()) + (NumberUtil.nullToZero(branchShopUser.getConsumeCount())));
|
||||
headShopUser.setConsumeAmount(NumberUtil.nullToZero(headShopUser.getConsumeAmount()).add(NumberUtil.nullToZero(branchShopUser.getConsumeAmount())));
|
||||
headShopUser.setUpdateTime(LocalDateTime.now());
|
||||
String mergedUsers = StrUtil.emptyToDefault(headShopUser.getMergedUsers(), "[]");
|
||||
JSONArray objects = JSON.parseArray(mergedUsers);
|
||||
objects.add(JSONObject.from(branchShopUser));
|
||||
headShopUser.setMergedUsers(JSON.toJSONString(objects));
|
||||
String allShopIds = StrUtil.emptyToDefault(headShopUser.getAllShopIds(), "0,".concat(headShopUser.getShopId() + ","));
|
||||
List<String> split = StrUtil.split(allShopIds, ",", true, true);
|
||||
String branchShopIdStr = Convert.toStr(branchShopUser.getShopId());
|
||||
if (!split.contains(branchShopIdStr)) {
|
||||
split.add(branchShopIdStr);
|
||||
}
|
||||
headShopUser.setAllShopIds(CollUtil.join(split, ",").concat(","));
|
||||
shopUserMapper.update(headShopUser);
|
||||
toZero(branchShopUser);
|
||||
shopUserMapper.update(branchShopUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并会员信息 2.如果主店有,分店没有
|
||||
*
|
||||
* @param headShopUser 主店会员
|
||||
* @param branchShopId 分店id
|
||||
*/
|
||||
public void toMergeCase2(ShopUser headShopUser, Long branchShopId) {
|
||||
headShopUser.setUpdateTime(LocalDateTime.now());
|
||||
String allShopIds = StrUtil.emptyToDefault(headShopUser.getAllShopIds(), "0,".concat(headShopUser.getShopId() + ","));
|
||||
List<String> split = StrUtil.split(allShopIds, ",", true, true);
|
||||
String branchShopIdStr = Convert.toStr(branchShopId);
|
||||
if (!split.contains(branchShopIdStr)) {
|
||||
split.add(branchShopIdStr);
|
||||
}
|
||||
headShopUser.setAllShopIds(CollUtil.join(split, ",").concat(","));
|
||||
shopUserMapper.update(headShopUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并会员信息 3.如果主店没有,分店有
|
||||
*
|
||||
* @param headShopId 主店id
|
||||
* @param branchShopUser 分店会员信息
|
||||
*/
|
||||
public void toMergeCase3(Long headShopId, ShopUser branchShopUser) {
|
||||
ShopUser headShopUser = BeanUtil.copyProperties(branchShopUser, ShopUser.class, "id", "shopId","allShopIds");
|
||||
headShopUser.setShopId(headShopId);
|
||||
String mergedUsers = StrUtil.emptyToDefault(headShopUser.getMergedUsers(), "[]");
|
||||
JSONArray objects = JSON.parseArray(mergedUsers);
|
||||
objects.add(JSONObject.from(branchShopUser));
|
||||
headShopUser.setMergedUsers(JSON.toJSONString(objects));
|
||||
String allShopIds = StrUtil.emptyToDefault(headShopUser.getAllShopIds(), "0,".concat(headShopUser.getShopId() + ","));
|
||||
List<String> split = StrUtil.split(allShopIds, ",", true, true);
|
||||
String branchShopIdStr = Convert.toStr(branchShopUser.getShopId());
|
||||
if (!split.contains(branchShopIdStr)) {
|
||||
split.add(branchShopIdStr);
|
||||
}
|
||||
headShopUser.setAllShopIds(CollUtil.join(split, ",").concat(","));
|
||||
shopUserMapper.insert(headShopUser);
|
||||
toZero(branchShopUser);
|
||||
shopUserMapper.update(branchShopUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员数据归零
|
||||
*
|
||||
* @param shopUser 会员信息
|
||||
*/
|
||||
public void toZero(ShopUser shopUser) {
|
||||
shopUser.setAccountPoints(0);
|
||||
shopUser.setAmount(BigDecimal.ZERO);
|
||||
shopUser.setConsumeAmount(BigDecimal.ZERO);
|
||||
shopUser.setConsumeCount(0);
|
||||
shopUser.setUpdateTime(LocalDateTime.now());
|
||||
shopUser.setIsMergedToHead(YesNoEnum.YES.value());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
|
|||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.account.service.SyncNoticeService;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.product.entity.*;
|
||||
|
|
@ -58,6 +59,8 @@ public class ShopSyncServiceImpl implements ShopSyncService {
|
|||
@Resource
|
||||
private ProdConsRelationService prodConsRelationService;
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
@Resource
|
||||
private SyncNoticeService syncNoticeService;
|
||||
|
||||
private void checkShopInfo(Long sourceShopId, Long targetShopId) {
|
||||
|
|
@ -73,7 +76,6 @@ public class ShopSyncServiceImpl implements ShopSyncService {
|
|||
|| targetShop.getIsHeadShop() == null || targetShop.getIsHeadShop().equals(1)) {
|
||||
throw new CzgException("同步失败,目标店铺是主店铺或目标店铺是单店");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
-- ----------------------------
|
||||
-- tb_shop_user表扩展字段
|
||||
-- ----------------------------
|
||||
ALTER TABLE `tb_shop_user`
|
||||
ADD COLUMN `is_merged_to_head` tinyint NULL DEFAULT 0 COMMENT '是否已经合并数据到主店 1-是 0-否 默认0',
|
||||
ADD COLUMN `merged_users` text NULL COMMENT '已经合并过来的用户信息,jsonArray格式,[{\"id\":1,\"shopId\":2,...},{\"id\":1,\"shopId\":2,...}]',
|
||||
ADD COLUMN `all_shop_ids` varchar(1200) NULL COMMENT '适用门店id集合,逗号分隔,例如:0,1,2,3,...查询的时候 all_shop_ids like \'%,1,%\';';
|
||||
|
||||
-- ----------------------------
|
||||
-- 处理历史数据
|
||||
-- ----------------------------
|
||||
update tb_shop_user set is_merged_to_head = 0;
|
||||
update tb_shop_user set all_shop_ids = concat('0,', shop_id, ',');
|
||||
Loading…
Reference in New Issue