找回密码
 立即注册
首页 业界区 业界 商品中心—9.商品卖家系统的技术文档

商品中心—9.商品卖家系统的技术文档

县挫伪 2025-6-20 14:48:30
大纲
1.卖家和卖家组模型以及业务流程
2.卖家系统数据库表模型与缓存结构设计
3.卖家系统核心接口与代码实现
 
1.卖家和卖家组模型以及业务流程
(1)卖家模型
(2)卖家组模型
(3)业务流程详解
 
(1)卖家模型
卖家类型分为:⾃营卖家和POP卖家。
 
⾃营卖家:类似于京东⾃营卖家。其商品由平台采购,建⽴仓储系统存储,平台⾃⾏上架商品。其最⼩维度为⻔店,如北京市-东城区-⽣鲜⻔店。
 
POP卖家:第三⽅供货商接⼊平台作为⼀个卖家。其最⼩维度为区域,如北京市-东城区卖家。
 
卖家树模型可以看成是类目树模型。卖家节点也分为叶子节点和非叶子节点。非叶子节点的卖家节点可以看成是卖家所属的分类,叶子节点的卖家节点才是具体的某一个卖家。所以创建卖家节点之前,必须先根据全国地区编码初始化一次卖家树。初始化完之后,后续创建卖家节点就不需要再初始化卖家树了。
 
一.自营卖家树体系
1.webp
二.POP卖家树体系
2.webp
(2)卖家组模型
卖家组:⼀组具有相同供应属性的卖家组合。注意:POP类型的卖家和⾃营类型的卖家不能同属⼀个卖家组。在⼀个卖家组中,要么全都是⾃营卖家,要么全都是POP卖家。
3.webp
(3)业务流程详解
一.建立卖家体系
⾃营卖家:根据国家的地区编码建⽴卖家树。其⾮叶⼦节点为虚拟卖家,叶⼦节点为实体卖家,例如东城区⻔店1。
 
POP卖家:根据国家的地区编码建⽴卖家树。其⾮叶⼦节点为虚拟卖家,叶⼦节点为实体卖家,例如东城区卖家。
 
二.建立卖家组
⾃营:例如根据地域关系划分,东城区卖家组,⻄城区卖家组。
 
POP:例如根据地域关系划分,上海卖家组,北京卖家组。
 
三.绑定卖家与卖家组关系
运营将⼀组卖家与卖家组绑定。注意:绑定时卖家与卖家组类型必须⼀致才可以绑定,否则不能绑定。而且卖家组与卖家是多对多关系,即⼀个卖家组能同时添加多个同⼀⾃营类型卖家或者POP类型卖家,⼀个卖家也可以被添加到多个同⼀类型的卖家组中。
 
卖家组与卖家建⽴绑定关系后,即可对外提供卖家能⼒。只有当卖家与卖家组绑定关系后,才可以对外提供售卖商品的能⼒。商品需要划分到卖家,⽽卖家也必须⾄少在⼀个卖家组中。
4.webp
 
2.卖家系统数据库表模型与缓存结构设计
(1)卖家信息表
(2)卖家组表
(3)卖家与卖家组关系表
(4)卖家账户表
(5)卖家系统ID表
(6)国家⾏政编号信息表
(7)缓存结构设计
 
(1)卖家信息表
  1. CREATE TABLE `seller_info` (
  2.     `id` bigint(40) NOT NULL AUTO_INCREMENT COMMENT '主键',
  3.     `seller_id` int(10) NOT NULL COMMENT '卖家ID:20开头 + 6位随机数',
  4.     `seller_code` varchar(64) NOT NULL COMMENT '卖家编码:⾃营指微仓编码(WJ-1001),POP指区域编码(国标编码)',
  5.     `seller_name` varchar(128) NOT NULL COMMENT '卖家名称',
  6.     `seller_desc` varchar(512) DEFAULT NULL COMMENT '卖家描述',
  7.     `seller_type` tinyint(3) NOT NULL COMMENT '卖家类型:1-⾃营,2-POP ',
  8.     `seller_position` SMALLINT(3) NOT NULL COMMENT '卖家位置:100-全国,200-⼤区,300-省/直辖市,400-城市,500-地区,600-微仓',
  9.     `seller_status` tinyint(3) NOT NULL COMMENT '卖家状态:1-开店,2-闭店,3-删除',
  10.     `store_label_list` varchar(10) comment '存储标签(1-常温,2-冷藏,3-冷冻,4-⽔产)',
  11.     `trial_sale_label` tinyint(1) comment '是否有试销标签(1-试销,0-⾮试销)',
  12.     `parent_id` bigint(40) DEFAULT '0' COMMENT '⽗卖家ID',
  13.     `last_node` tinyint(3) NOT NULL DEFAULT '0' COMMENT '叶⼦节点标识:1-是,0-否',
  14.     `del_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标记(1-有效,0-删除)',
  15.     `create_user` int(10) NOT NULL DEFAULT '0' COMMENT '创建⼈',
  16.     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  17.     `update_user` int(10) NOT NULL DEFAULT '0' COMMENT '更新⼈',
  18.     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  19.     PRIMARY KEY (`id`)
  20. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='卖家信息表';
复制代码
(2)卖家组表
  1. create table `seller_group` (
  2.     `id` bigint(40) primary key AUTO_INCREMENT COMMENT '主键',
  3.     `seller_group_id` int(10) not null comment '卖家组ID:30开头 + 4位随机数',
  4.     `seller_group_name` varchar(64) not null comment '卖家组名称',
  5.     `seller_group_type` tinyint(3) not null comment '卖家组类型:1-⾃营,2-POP',
  6.     `seller_group_status` tinyint(3) NOT NULL COMMENT '卖家组状态:1-⽣效,2-⽆效',
  7.     `del_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标记(1-有效,0-删除)',
  8.     `create_user` int(10) NOT NULL DEFAULT '0' COMMENT '创建⼈',
  9.     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  10.     `update_user` int(10) NOT NULL DEFAULT '0' COMMENT '更新⼈',
  11.     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
  12. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='卖家组表';
复制代码
(3)卖家与卖家组关系表
  1. create table seller_group_relation(
  2.     `id` bigint(40) primary key AUTO_INCREMENT COMMENT '主键',
  3.     `seller_group_id` int(10) not null comment '卖家组ID:30开头 + 4位随机数',
  4.     `seller_id` int(10) not null comment '卖家ID:20开头 + 6位随机数',
  5.     `del_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标记(1-有效,0-删除)',
  6.     `create_user` int(10) NOT NULL DEFAULT '0' COMMENT '创建⼈',
  7.     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  8.     `update_user` int(10) NOT NULL DEFAULT '0' COMMENT '更新⼈',
  9.     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
  10. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='卖家与卖家组关系表';
复制代码
(4)卖家账户表
  1. create table seller_account (
  2.     `id` bigint(40) primary key AUTO_INCREMENT COMMENT '主键',
  3.     `seller_id` int(10) not null comment '卖家ID:20开头+6位随机数',
  4.     `pay_channel` tinyint(3) not null comment '⽀付渠道:1-银联,2-微信,3-⽀付宝',
  5.     `account_no` varchar(64) not null comment '卖家结算账户,最终收款账号',
  6.     `del_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标记(1-有效,0-删除)',
  7.     `create_user` int(10) NOT NULL DEFAULT '0' COMMENT '创建⼈',
  8.     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  9.     `update_user` int(10) NOT NULL DEFAULT '0' COMMENT '更新⼈',
  10.     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
  11. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='卖家账户表';
复制代码
(5)卖家系统ID表
  1. create table seller_auto_no(
  2.     `id` bigint(20) primary key auto_increment comment '主键',
  3.     `create_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  4.     `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
  5. ) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8mb4 COMMENT='卖家系统ID表';
复制代码
(6)国家⾏政编号信息表
  1. CREATE TABLE `national_code` (
  2.     `id` int(7) NOT NULL COMMENT '主键',
  3.     `name` varchar(40) DEFAULT NULL COMMENT '省市区名称',
  4.     `parent_id` int(7) DEFAULT NULL COMMENT '上级ID',
  5.     `short_name` varchar(40) DEFAULT NULL COMMENT '简称',
  6.     `level_type` tinyint(2) DEFAULT NULL COMMENT '级别:0-中国,1-⼤区,2-省/直辖市,3-市,4-区/县',
  7.     `city_code` varchar(7) DEFAULT NULL COMMENT '城市代码',
  8.     `zip_code` varchar(7) DEFAULT NULL COMMENT '邮编',
  9.     `lng` varchar(20) DEFAULT NULL COMMENT '经度',
  10.     `lat` varchar(20) DEFAULT NULL COMMENT '纬度',
  11.     `pinyin` varchar(40) DEFAULT NULL COMMENT '拼⾳',
  12.     `status` enum('0','1') DEFAULT '1'
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='国家⾏政编号信息表';
复制代码
(7)缓存结构设计
5.webp
 
3.卖家系统核心接口与代码实现
(1)卖家接口
(2)卖家组接口
(3)卖家与卖家组关系
(4)卖家账户
 
(1)卖家接口
一.初始化卖家树接口
二.新增卖家接口
三.更新卖家接口
四.删除卖家接口
五.查询卖家接口
六.查询卖家RPC接口
 
一.初始化卖家树接口
向接口传⼊卖家类型,然后根据国标数据初始化全国卖家树。卖家树层级为:全国、⼤区、省/直辖市、城市、区/县。
 
卖家树模型可以看成是类目树模型。卖家节点也分为叶子节点和非叶子节点,非叶子节点的卖家节点可以看成是卖家所属的分类,叶子节点的卖家节点才是具体的某一个卖家。所以创建卖家节点之前,必须先根据全国地区编码初始化一次卖家树。初始化完之后,后续创建卖家节点就不需要再初始化卖家树了。
  1. @Service
  2. public class SellerInfoServiceImpl implements SellerInfoService {
  3.     @Autowired
  4.     private SellerRepository sellerRepository;
  5.     ...
  6.    
  7.     //卖家树信息初始化接口
  8.     @Override
  9.     @Transactional(rollbackFor = Exception.class)
  10.     public SellerInfoResultDTO initSellerTreeInfo(Integer sellerType) {
  11.         //1.生成全国卖家
  12.         Long nationwideSellerId = initNationwideSeller(sellerType);
  13.         //2.生成大区卖家
  14.         Map<String, Long> districtMap = initDistrictSeller(nationwideSellerId, sellerType);
  15.         //3.生成省/直辖市卖家
  16.         Map<String, Long> provinceMap = initDiffParentSeller(districtMap, sellerType, NationalCodeLevelEnum.PROVINCE, SellerPositionEnum.PROVINCE);
  17.         //4.生成城市卖家
  18.         Map<String, Long> cityMap = initDiffParentSeller(provinceMap, sellerType, NationalCodeLevelEnum.CITY, SellerPositionEnum.CITY);
  19.         //5.生成地区卖家
  20.         initDiffParentSeller(cityMap, sellerType, NationalCodeLevelEnum.REGION, SellerPositionEnum.REGION);
  21.         return new SellerInfoResultDTO(Boolean.TRUE);
  22.     }
  23.    
  24.     //1.生成全国卖家
  25.     private Long initNationwideSeller(Integer sellerType) {
  26.         //查询出国家层级数据
  27.         List<NationalCodeDO> nationalCodeList = getNationalCode(NationalCodeLevelEnum.NATIONWIDE);
  28.         //只有一个全国卖家
  29.         NationalCodeDO nationalCode = nationalCodeList.get(0);
  30.         //生成sellerId
  31.         Long sellerId = sellerRepository.generateSellerId(SkuSellerRelationConstants.SELLER_PREFIX_NO, SELLER_ID_WIDTH);
  32.         SellerInfoDO sellerInfo = buildSellerInfoDO(sellerType, nationalCode, sellerId);
  33.         //保存全国卖家
  34.         sellerRepository.savelSellerInfoBatch(Collections.singletonList(sellerInfo));
  35.         return sellerId;
  36.     }
  37.    
  38.     //查询某地区层级的国标数据
  39.     private List<NationalCodeDO> getNationalCode(NationalCodeLevelEnum province) {
  40.         NationalCodeRequest nationalRequest = new NationalCodeRequest();
  41.         nationalRequest.setLevelType(province.getCode());
  42.         return nationalCodeRepository.queryNationalCode(nationalRequest);
  43.     }
  44.    
  45.     //构造卖家树节点数据
  46.     private SellerInfoDO buildSellerInfoDO(Integer sellerType, NationalCodeDO nationalCode, Long parentId, SellerPositionEnum province) {
  47.         SellerInfoDO sellerInfo = new SellerInfoDO();
  48.         //生成sellerId
  49.         Long sellerId = sellerRepository.generateSellerId(SkuSellerRelationConstants.SELLER_PREFIX_NO, SELLER_ID_WIDTH);
  50.         sellerInfo.setSellerId(sellerId);
  51.         sellerInfo.setSellerCode(String.valueOf(nationalCode.getId()));
  52.         sellerInfo.setSellerName(nationalCode.getName() + SkuSellerRelationConstants.SELLER_NAME_SUFFIX);
  53.         sellerInfo.setSellerPosition(province.getCode());
  54.         sellerInfo.setSellerType(sellerType);
  55.         sellerInfo.setSellerStatus(SellerInfoStatusEnum.OPEN_STATUS.getCode());
  56.         sellerInfo.setParentId(parentId);
  57.         sellerInfo.setLastNode(YesOrNoEnum.NO.getCode());
  58.         sellerInfo.initCommon();
  59.         return sellerInfo;
  60.     }
  61.    
  62.     //2.生成地区卖家
  63.     private Map<String, Long> initDistrictSeller(Long nationwideSellerId, Integer sellerType) {
  64.         //查询出地区层级数据
  65.         List<NationalCodeDO> nationalCodeList = getNationalCode(NationalCodeLevelEnum.DISTRICT);
  66.         //国家以下层级有多个
  67.         List<SellerInfoDO> sellerInfoList = nationalCodeList.stream()
  68.             .map(nationalCode -> buildSellerInfoDO(sellerType, nationalCode, nationwideSellerId, SellerPositionEnum.DISTRICT))
  69.             .collect(Collectors.toList());
  70.         //批量保存
  71.         sellerRepository.savelSellerInfoBatch(sellerInfoList);
  72.         //转换为Map,key为卖家编码、value为卖家ID
  73.         return sellerInfoList.stream().collect(Collectors.toMap(SellerInfoDO::getSellerCode, SellerInfoDO::getSellerId));
  74.     }
  75.    
  76.     //省/直辖市、城市、区县卖家都使用该接口生成
  77.     private Map<String, Long> initDiffParentSeller(Map<String, Long> districtMap, Integer sellerType, NationalCodeLevelEnum codeLevelEnum, SellerPositionEnum sellerPositionEnum) {
  78.         //查询出地区层级数据
  79.         List<NationalCodeDO> provinceCodeList = getNationalCode(codeLevelEnum);
  80.         //需要保存的卖家集合
  81.         List<SellerInfoDO> sellerInfoList = provinceCodeList.stream().map(nationalCode -> {
  82.             //获取该国标的上级卖家ID
  83.             Long parentId = districtMap.get(String.valueOf(nationalCode.getParentId()));
  84.             return buildSellerInfoDO(sellerType, nationalCode, parentId, sellerPositionEnum);
  85.         }).collect(Collectors.toList());
  86.         //批量保存
  87.         sellerRepository.savelSellerInfoBatch(sellerInfoList);
  88.         //转换为Map,key为卖家编码、value为卖家ID
  89.         return sellerInfoList.stream().collect(Collectors.toMap(SellerInfoDO::getSellerCode, SellerInfoDO::getSellerId));
  90.     }
  91.     ...
  92. }
  93. @Repository
  94. public class SellerRepository {
  95.     ...
  96.     //生成卖家或卖家组ID,即sellerId、sellerGroupId生成
  97.     //sellerId格式:20开头,6位随机数
  98.     //sellerGroupId格式:30开头,4位随机数
  99.     public Long generateSellerId(String prefix, Integer width) {
  100.         return Long.parseLong(generateSellerNo(prefix, width));
  101.     }
  102.    
  103.     //自营卖家叶子结点sellerCode生成
  104.     //格式:父卖家(区县)的首拼-4位随机数,如:西湖区 -> XH-1001
  105.     //@param prefix 前缀
  106.     //@param width  位数
  107.     public String generateSellerNo(String prefix, Integer width) {
  108.         SellerAutoNoDO sellerAutoNoDO = new SellerAutoNoDO();
  109.         sellerAutoNoMapper.insert(sellerAutoNoDO);
  110.         Long autoNo = sellerAutoNoDO.getId();
  111.         if (Objects.isNull(autoNo)) {
  112.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  113.         }
  114.         return prefix + IDUtils.genId(autoNo, width);
  115.     }
  116.    
  117.     //批量新增卖家
  118.     public void savelSellerInfoBatch(List<SellerInfoDO> sellerInfoList) {
  119.         List<Long> sellerIdList = sellerInfoList.stream().map(SellerInfoDO::getSellerId).collect(Collectors.toList());
  120.         //是否存在该记录
  121.         LambdaQueryWrapper<SellerInfoDO> queryWrapper = Wrappers.lambdaQuery();
  122.         queryWrapper.in(SellerInfoDO::getSellerId, sellerIdList);
  123.         int count = sellerInfoMapper.selectCount(queryWrapper);
  124.         if (count > 0) {
  125.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  126.         }
  127.         //批量插入
  128.         count = sellerInfoMapper.insertBatch(sellerInfoList);
  129.         if (count != sellerInfoList.size()) {
  130.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  131.         }
  132.     }
  133.     ...
  134. }
复制代码
二.新增卖家接口
新增微仓卖家节点,卖家分为⾃营卖家和POP卖家,只有⾃营卖家才有微仓层级。
  1. @Service
  2. public class SellerInfoServiceImpl implements SellerInfoService {
  3.     //卖家ID,6位序列号
  4.     private static final int SELLER_ID_WIDTH = 6;
  5.    
  6.     //自营卖家编码,4位序列号
  7.     private static final int SELLER_CODE_WIDTH = 4;
  8.    
  9.     @Autowired
  10.     private SellerRepository sellerRepository;
  11.     ...
  12.    
  13.     //新增卖家
  14.     @Override
  15.     @Transactional(rollbackFor = Exception.class)
  16.     public SellerInfoResultDTO saveSellerInfo(SellerInfoRequest request) {
  17.         //1.校验参数完整性
  18.         checkSaveSellerInfoRequest(request);
  19.         //2.父卖家是否存在
  20.         SellerInfoDO sellerInfo = checkParentSellerExists(request);
  21.         //3.sellerId生成
  22.         Long sellerId = sellerRepository.generateSellerId(SkuSellerRelationConstants.SELLER_PREFIX_NO, SELLER_ID_WIDTH);
  23.         request.setSellerId(sellerId);
  24.         //新增卖家的父卖家的sellerCode是国标,找到国标前缀
  25.         String sellerCodePrefix = getSellerCodePrefix(sellerInfo);
  26.         //4.sellerCode生成
  27.         String sellerCode = sellerRepository.generateSellerNo(sellerCodePrefix, SELLER_CODE_WIDTH);
  28.         request.setSellerCode(sellerCode);
  29.         //5.新增卖家数据
  30.         sellerRepository.saveSellerInfo(request);
  31.         return new SellerInfoResultDTO(request.getSellerId(), Boolean.TRUE);
  32.     }
  33.    
  34.     //获取自营卖家叶子结点的sellerCode前缀
  35.     private String getSellerCodePrefix(SellerInfoDO parentSellerInfo) {
  36.         //父卖家编码
  37.         Integer sellerCode;
  38.         try {
  39.             sellerCode = Integer.parseInt(parentSellerInfo.getSellerCode());
  40.         } catch (NumberFormatException e) {
  41.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  42.         }
  43.         NationalCodeRequest request = new NationalCodeRequest();
  44.         request.setId(sellerCode);
  45.         List<NationalCodeDO> nationalCodeList = nationalCodeRepository.queryNationalCode(request);
  46.   
  47.         NationalCodeDO nationalCode = nationalCodeList.get(0);
  48.         if (Objects.isNull(nationalCode) || StringUtils.isEmpty(nationalCode.getShortName())) {
  49.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  50.         }
  51.         //转换为拼音首字母简写
  52.         return BopomofoUtil.initialsTransfer(nationalCode.getShortName()) + SkuSellerRelationConstants.SELF_SELLER_CODE_SEPARATOR;
  53.     }
  54.     ...
  55. }
  56. //卖家信息入参
  57. @Data
  58. @Builder
  59. @AllArgsConstructor
  60. @NoArgsConstructor
  61. public class SellerInfoRequest extends PageRequest implements Serializable {
  62.     //卖家ID集合(限制100个)
  63.     List<Long> sellerIdList;
  64.     //卖家ID
  65.     private Long sellerId;
  66.     //卖家名称
  67.     private String sellerName;
  68.     //卖家编码 自营指微仓编码(WJ-1001),POP指区域编码(国标编码),上级编码用的是一套国标编码
  69.     private String sellerCode;
  70.     //卖家描述
  71.     private String sellerDesc;
  72.     //卖家位置:100-全国,200-大区,300-省(直辖市),400-城市,500-地区,600-微仓
  73.     private Integer sellerPosition;
  74.     //自营:1,pop:2
  75.     private Integer sellerType;
  76.     //卖家状态:1-开店,2-闭店,3-删除
  77.     private Integer sellerStatus;
  78.     //父卖家ID
  79.     private Integer parentId;
  80.     //是否叶子节点
  81.     private Integer lastNode;
  82.     //存储标签(1-常温,2-冷藏,3-冷冻,4-水产)
  83.     private List<Integer> storeLabelList;
  84.     //是否有试销标签(1-试销,0-非试销)
  85.     private Integer trialSaleLabel;
  86. }
  87. @Repository
  88. public class SellerRepository {
  89.     ...
  90.     //生成卖家或卖家组ID,即sellerId、sellerGroupId生成
  91.     //sellerId格式:20开头,6位随机数
  92.     //sellerGroupId格式:30开头,4位随机数
  93.     public Long generateSellerId(String prefix, Integer width) {
  94.         return Long.parseLong(generateSellerNo(prefix, width));
  95.     }
  96.    
  97.     //自营卖家叶子结点sellerCode生成
  98.     //格式:父卖家(区县)的首拼-4位随机数,如:西湖区 -> XH-1001
  99.     //@param prefix 前缀
  100.     //@param width  位数
  101.     public String generateSellerNo(String prefix, Integer width) {
  102.         SellerAutoNoDO sellerAutoNoDO = new SellerAutoNoDO();
  103.         sellerAutoNoMapper.insert(sellerAutoNoDO);
  104.         Long autoNo = sellerAutoNoDO.getId();
  105.         if (Objects.isNull(autoNo)) {
  106.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  107.         }
  108.         return prefix + IDUtils.genId(autoNo, width);
  109.     }
  110.    
  111.     //新增卖家
  112.     public void saveSellerInfo(SellerInfoRequest request) {
  113.         //是否存在该记录
  114.         LambdaQueryWrapper<SellerInfoDO> queryWrapper = Wrappers.lambdaQuery();
  115.         queryWrapper.eq(SellerInfoDO::getSellerId, request.getSellerId());
  116.         int count = sellerInfoMapper.selectCount(queryWrapper);
  117.         if (count > 0) {
  118.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  119.         }
  120.         //DO对象初始化
  121.         SellerInfoDO sellerInfo = initSellerInfoDO(request);
  122.         //保存到缓存
  123.         redisCache.set(SellerRedisKeyConstants.SELLER_INFO_LIST + sellerInfo.getSellerId(), JSON.toJSONString(sellerInfo), -1);
  124.         //新卖家落库
  125.         count = sellerInfoMapper.insert(sellerInfo);
  126.         if (count <= 0) {
  127.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  128.         }
  129.     }
  130.    
  131.     //新增卖家时初始化卖家信息
  132.     private SellerInfoDO initSellerInfoDO(SellerInfoRequest request) {
  133.         SellerInfoDO sellerInfo = sellerInfoConverter.requestToEntity(request);
  134.         sellerInfo.setSellerPosition(SellerPositionEnum.STORAGE.getCode());
  135.         sellerInfo.setSellerType(SellerTypeEnum.SELF.getCode());
  136.         sellerInfo.setLastNode(YesOrNoEnum.YES.getCode());
  137.         sellerInfo.initCommon();
  138.         return sellerInfo;
  139.     }
  140.     ...
  141. }
复制代码
六.查询卖家RPC接口
提供给其他服务调⽤的RPC接⼝,仅允许通过卖家ID集合或卖家类型查询。
 
情况一:如果仅传⼊卖家ID集合,则根据ID查询
情况二:如果同时传⼊卖家ID集合与卖家类型,则根据卖家类型过滤查询到的类型不⼀致的卖家数据
情况三:如果仅传⼊卖家类型,则先查出2⻚卖家ID集合数据,再根据查出的卖家ID查询卖家集合
 
Redis缓存结构中1⻚存放100条卖家ID,这里也使用了简化版的缓存DB读写逻辑。
  1. @Service
  2. public class SellerInfoServiceImpl implements SellerInfoService {
  3.     ...
  4.     //更新卖家信息
  5.     //允许修改卖家名、卖家描述和卖家状态字段
  6.     //变更卖家状态后,所有子卖家状态也要变更,但仅允许修改城市及以下层级的卖家状态
  7.     @Override
  8.     @Transactional(rollbackFor = Exception.class)
  9.     public SellerInfoResultDTO updateSellerInfo(SellerInfoRequest request) {
  10.         //1.校验参数完整性
  11.         checkUpdateSellerInfoRequest(request);
  12.         //2.修改卖家数据
  13.         sellerRepository.updateSellerInfo(request);
  14.         //sellerStatus是否变更
  15.         if (Objects.nonNull(request.getSellerStatus())) {
  16.             //查询出所有的子卖家的sellerId
  17.             List<Long> sellerIdList = getChildSellerIdList(Collections.singletonList(request.getSellerId()), request.getSellerType());
  18.             //批量修改状态
  19.             sellerRepository.batchUpdateSellerInfo(sellerIdList, request.getSellerStatus());
  20.         }
  21.         return new SellerInfoResultDTO(request.getSellerId(), Boolean.TRUE);
  22.     }
  23.    
  24.     //获取子卖家的sellerId
  25.     private List<Long> getChildSellerIdList(List<Long> parentIdList, Integer sellerType) {
  26.         if (Objects.isNull(sellerType)) {
  27.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  28.         }
  29.         List<Long> sellerIdList = Lists.newArrayList();
  30.         List<Long> sellerIds = sellerRepository.getSellerIdListByParentId(parentIdList, sellerType);
  31.         if (CollectionUtils.isNotEmpty(sellerIds)) {
  32.             sellerIdList.addAll(sellerIds);
  33.             sellerIdList.addAll(getChildSellerIdList(sellerIds, sellerType));
  34.         }
  35.         return sellerIdList;
  36.     }
  37.     ...
  38. }
  39. @Repository
  40. public class SellerRepository {
  41.     ...
  42.     //修改卖家
  43.     public void updateSellerInfo(SellerInfoRequest request) {
  44.         //查询出数据库卖家信息
  45.         LambdaQueryWrapper<SellerInfoDO> queryWrapper = Wrappers.lambdaQuery();
  46.         queryWrapper.eq(SellerInfoDO::getSellerId, request.getSellerId());
  47.         SellerInfoDO sellerInfo = sellerInfoMapper.selectOne(queryWrapper);
  48.         if (Objects.isNull(sellerInfo)) {
  49.             throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());
  50.         }
  51.         //更新到缓存
  52.         updateSellerInfoFromCache(request, sellerInfo);
  53.         //更新到数据库
  54.         updateSellerInfoFromDB(request);
  55.     }
  56.    
  57.     //更新卖家信息到数据库
  58.     private void updateSellerInfoFromDB(SellerInfoRequest request) {
  59.         SellerInfoDO requestInfo = sellerInfoConverter.requestToEntity(request);
  60.         LambdaUpdateWrapper<SellerInfoDO> updateWrapper = Wrappers.lambdaUpdate();
  61.         updateWrapper.eq(SellerInfoDO::getSellerId, request.getSellerId());
  62.         int count = sellerInfoMapper.update(requestInfo, updateWrapper);
  63.         if (count <= 0) {
  64.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  65.         }
  66.     }
  67.    
  68.     //更新卖家信息到缓存
  69.     private void updateSellerInfoFromCache(SellerInfoRequest request, SellerInfoDO sellerInfo) {
  70.         String redisKey = SellerRedisKeyConstants.SELLER_INFO_LIST + request.getSellerId();
  71.         if (StringUtils.isNotEmpty(request.getSellerName())) {
  72.             sellerInfo.setSellerName(request.getSellerName());
  73.         }
  74.         if (StringUtils.isNotEmpty(request.getSellerDesc())) {
  75.             sellerInfo.setSellerDesc(request.getSellerDesc());
  76.         }
  77.         if (Objects.nonNull(SellerInfoStatusEnum.getByCode(request.getSellerStatus()))) {
  78.             sellerInfo.setSellerStatus(request.getSellerStatus());
  79.         }
  80.         redisCache.set(redisKey, JSON.toJSONString(sellerInfo), -1);
  81.     }
  82.    
  83.     //批量修改卖家状态
  84.     public void batchUpdateSellerInfo(List<Long> sellerIdList, Integer sellerStatus) {
  85.         LambdaUpdateWrapper<SellerInfoDO> updateWrapper = Wrappers.lambdaUpdate();
  86.         updateWrapper.in(Objects.nonNull(sellerIdList), SellerInfoDO::getSellerId, sellerIdList);
  87.         updateWrapper.set(SellerInfoDO::getSellerStatus, sellerStatus);
  88.         int count = sellerInfoMapper.update(null, updateWrapper);
  89.         if (count <= 0) {
  90.             throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);
  91.         }
  92.     }
  93.     ...
  94. }
复制代码
(2)卖家组接口
一.新增卖家组接口
二.更新卖家组接口
三.查询卖家组接口
四.删除卖家组接口
 
一.新增卖家组接口
新增⼀个卖家组,⼀个卖家组原则上不允许圈定不同区域的卖家,卖家组只限定其下的卖家类型要与卖家组保持⼀致。
[code]@Servicepublic class SellerGroupServiceImpl implements SellerGroupService {    //卖家组,4位序列号    private static final int GROUP_WIDTH = 4;        @Autowired    private SellerRepository sellerRepository;    ...        //新增卖家组    @Override    @Transactional(rollbackFor = Exception.class)    public SellerGroupResultDTO saveSellerGroupInfo(SellerGroupRequest request) {        //1.参数检查        checkSaveSellerGroupRequest(request);        //2.sellerGroupId生成        Long sellerGroupId = sellerRepository.generateSellerId(SkuSellerRelationConstants.SELLER_GROUP_PREFIX_NO, GROUP_WIDTH);        request.setSellerGroupId(sellerGroupId);        //3.新增卖家组数据        sellerRepository.saveSellerGroup(request);        return new SellerGroupResultDTO(request.getSellerGroupId(), Boolean.TRUE);    }    ...}//卖家组入参@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class SellerGroupRequest extends PageRequest implements Serializable {    //卖家组ID    private Long sellerGroupId;    //卖家组名称    private String sellerGroupName;    //卖家组类型:1-自营,2-POP    private Integer sellerGroupType;    //卖家组ID集合(限制100个)    private List sellerGroupIdList;    //卖家组状态:1-有效,0-无效    private Integer sellerGroupStatus;    //是否需要卖家信息    private Boolean needSellerInfo = false;}@Repositorypublic class SellerRepository {    ...    //生成卖家或卖家组ID,即sellerId、sellerGroupId生成    //sellerId格式:20开头,6位随机数    //sellerGroupId格式:30开头,4位随机数    public Long generateSellerId(String prefix, Integer width) {        return Long.parseLong(generateSellerNo(prefix, width));    }        //自营卖家叶子结点sellerCode生成    //格式:父卖家(区县)的首拼-4位随机数,如:西湖区 -> XH-1001    //@param prefix 前缀    //@param width  位数    public String generateSellerNo(String prefix, Integer width) {        SellerAutoNoDO sellerAutoNoDO = new SellerAutoNoDO();        sellerAutoNoMapper.insert(sellerAutoNoDO);        Long autoNo = sellerAutoNoDO.getId();        if (Objects.isNull(autoNo)) {            throw new BaseBizException(CommonErrorCodeEnum.SQL_ERROR);        }        return prefix + IDUtils.genId(autoNo, width);    }    //新增卖家组    public void saveSellerGroup(SellerGroupRequest request) {        //是否存在该记录        LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery();        queryWrapper.eq(SellerGroupDO::getSellerGroupId, request.getSellerGroupId());        int count = sellerGroupMapper.selectCount(queryWrapper);        if (count > 0) {            throw new BaseBizException(ProductErrorCodeEnum.PARAM_CHECK_ERROR, ProductErrorCodeEnum.PARAM_CHECK_ERROR.getErrorCode());        }          //DO对象初始化        SellerGroupDO sellerGroup = sellerGroupConverter.requestToEntity(request);        sellerGroup.initCommon();        //新卖家落库        count = sellerGroupMapper.insert(sellerGroup);        if (count  !existSellerIds.contains(sellerId)).collect(Collectors.toList());        log.info("filteredSellerIds:{}", JSON.toJSONString(filteredSellerIds));        return SellerGroupRelationRequest.builder().sellerGroupId(request.getSellerGroupId()).sellerIdList(filteredSellerIds).build();    }    ...}//卖家与卖家组关系入参@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class SellerGroupRelationRequest extends PageRequest implements Serializable {    //卖家组ID    @NotNull(message = "sellerGroupId不能为空")    private Long sellerGroupId;        //卖家id列表    @Size(min = 1, max = 100, message = "sellerIdList不能为空,且最多同时操作200个")    private List sellerIdList;       //卖家组ID集合    private List sellerGroupIdList;}@Repositorypublic class SellerRepository {    ...    //根据卖家组id列表,卖家组类型查询卖家与卖家关系    public List querySellerGroupRelationInfo(SellerGroupRelationRequest request) {        LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery();        queryWrapper.eq(Objects.nonNull(request.getSellerGroupId()), SellerGroupRelationDO::getSellerGroupId, request.getSellerGroupId());        //分页查询存放数据的总集合        List results = new ArrayList();        Page page = new Page(request.getPageNo(), request.getPageSize());        //查询分页数据        Page pageResult = sellerGroupRelationMapper.selectPage(page, queryWrapper);        results.addAll(pageResult.getRecords());        return sellerGroupRelationConverter.convertAccountsTODTO(results);    }        //批量保存卖家与卖家组信息    public void saveSellerGroupRelationInfo(SellerGroupRelationRequest request) {        //经过前置sellerId过滤,sellerId为空说明本批次的relation关系已经保存过        //直接返回即可        if (CollectionUtils.isEmpty(request.getSellerIdList())) {            return;        }        List relationList = request.getSellerIdList().stream().map(sellerId -> {            SellerGroupRelationDO relation = new SellerGroupRelationDO();            relation.setSellerGroupId(request.getSellerGroupId());            relation.setSellerId(sellerId);            relation.initCommon();            return relation;        }).collect(Collectors.toList());          Integer count = sellerGroupRelationMapper.insertBatch(relationList);        if (Objects.isNull(count) || count
您需要登录后才可以回帖 登录 | 立即注册