记得上下班打卡 | git大法好,push需谨慎

Commit fc3794cd authored by 姜秀龙's avatar 姜秀龙

收钱吧 商品同步相关逻辑整理修改

parent 111223e2
...@@ -6,8 +6,8 @@ CREATE TABLE `goblin_sqb_mall_info` ( ...@@ -6,8 +6,8 @@ CREATE TABLE `goblin_sqb_mall_info` (
`signature` VARCHAR(256) NOT NULL COMMENT '商城密钥', `signature` VARCHAR(256) NOT NULL COMMENT '商城密钥',
`store_id` VARCHAR(64) NOT NULL COMMENT '关联我方店铺ID', `store_id` VARCHAR(64) NOT NULL COMMENT '关联我方店铺ID',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '0-禁用 1-启用', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '0-禁用 1-启用',
`created_at` DATETIME NOT NULL, `created_at` timestamp NULL DEFAULT NULL,
`updated_at` DATETIME NOT NULL, `updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`mid`), PRIMARY KEY (`mid`),
UNIQUE KEY `uk_mall_sn` (`mall_sn`) UNIQUE KEY `uk_mall_sn` (`mall_sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收钱吧商城信息'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收钱吧商城信息';
...@@ -20,8 +20,8 @@ CREATE TABLE `goblin_sqb_goods_ext` ( ...@@ -20,8 +20,8 @@ CREATE TABLE `goblin_sqb_goods_ext` (
`sqb_product_id` VARCHAR(64) NOT NULL COMMENT '收钱吧商品ID', `sqb_product_id` VARCHAR(64) NOT NULL COMMENT '收钱吧商品ID',
`sqb_product_sn` VARCHAR(64) NOT NULL COMMENT '收钱吧商品编号', `sqb_product_sn` VARCHAR(64) NOT NULL COMMENT '收钱吧商品编号',
`sqb_sku_id` VARCHAR(64) COMMENT '收钱吧SKU ID', `sqb_sku_id` VARCHAR(64) COMMENT '收钱吧SKU ID',
`created_at` DATETIME NOT NULL, `created_at` timestamp NULL DEFAULT NULL,
`updated_at` DATETIME NOT NULL, `updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`mid`), PRIMARY KEY (`mid`),
UNIQUE KEY `uk_spu_sku` (`spu_id`, `sku_id`), UNIQUE KEY `uk_spu_sku` (`spu_id`, `sku_id`),
KEY `idx_mall_sn` (`mall_sn`) KEY `idx_mall_sn` (`mall_sn`)
...@@ -34,8 +34,8 @@ CREATE TABLE `goblin_sqb_performance_goods` ( ...@@ -34,8 +34,8 @@ CREATE TABLE `goblin_sqb_performance_goods` (
`sku_id` VARCHAR(64) NOT NULL COMMENT 'SKU ID', `sku_id` VARCHAR(64) NOT NULL COMMENT 'SKU ID',
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序权重', `sort` INT NOT NULL DEFAULT 0 COMMENT '排序权重',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '0-禁用 1-启用', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '0-禁用 1-启用',
`created_at` DATETIME NOT NULL, `created_at` timestamp NULL DEFAULT NULL,
`updated_at` DATETIME NOT NULL, `updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`mid`), PRIMARY KEY (`mid`),
UNIQUE KEY `uk_perf_sku` (`performances_id`, `sku_id`), UNIQUE KEY `uk_perf_sku` (`performances_id`, `sku_id`),
KEY `idx_performances_id` (`performances_id`) KEY `idx_performances_id` (`performances_id`)
...@@ -59,8 +59,8 @@ CREATE TABLE `goblin_sqb_order` ( ...@@ -59,8 +59,8 @@ CREATE TABLE `goblin_sqb_order` (
`coupon_expire_time` DATETIME COMMENT '券码过期时间', `coupon_expire_time` DATETIME COMMENT '券码过期时间',
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败',
`refund_reason` VARCHAR(256) COMMENT '退款原因', `refund_reason` VARCHAR(256) COMMENT '退款原因',
`created_at` DATETIME NOT NULL, `created_at` timestamp NULL DEFAULT NULL,
`updated_at` DATETIME NOT NULL, `updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`mid`), PRIMARY KEY (`mid`),
UNIQUE KEY `uk_order_id` (`order_id`), UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_user_id` (`user_id`), KEY `idx_user_id` (`user_id`),
......
package com.liquidnet.service.goblin.param.shouqianba.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 收钱吧商品同步单项参数
*/
@Data
public class GoblinSqbGoodsSyncParam implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank(message = "收钱吧商品 ID 不能为空")
@ApiModelProperty(value = "收钱吧商品 ID (对应 spuId)", required = true)
private String sqbProductId;
@ApiModelProperty(value = "收钱吧商品编码 (非必填)")
private String sqbProductSn;
@NotBlank(message = "商城编号不能为空")
@ApiModelProperty(value = "收钱吧商城编号", required = true)
private String mallSn;
@NotBlank(message = "商城签名不能为空")
@ApiModelProperty(value = "收钱吧商城签名", required = true)
private String mallSignature;
}
...@@ -2,9 +2,9 @@ package com.liquidnet.service.goblin.service; ...@@ -2,9 +2,9 @@ package com.liquidnet.service.goblin.service;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import com.liquidnet.service.goblin.param.shouqianba.request.GoblinSqbGoodsSyncParam;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 收钱吧商品同步服务接口 * 收钱吧商品同步服务接口
...@@ -20,13 +20,22 @@ public interface IGoblinSqbGoodsService { ...@@ -20,13 +20,22 @@ public interface IGoblinSqbGoodsService {
ResponseDto<List<GoblinSqbPerfGoodsVo>> getAllMallProducts(); ResponseDto<List<GoblinSqbPerfGoodsVo>> getAllMallProducts();
/** /**
* 批量同步商品到 goblin 系统 * 批量新增商品到 goblin 系统(不存在则新增)
* 已存在则更新,不存在则新增(spuType=33)
* *
* @param items 待同步商品列表,每项包含 mallSn、sqbProductId、sqbProductSn * @param storeId 门店ID
* @return 同步结果 * @param items 待新增商品列表
* @return 结果
*/ */
ResponseDto<String> syncGoods(List<Map<String, String>> items); ResponseDto<String> addGoods(String storeId, List<GoblinSqbGoodsSyncParam> items);
/**
* 批量更新商品到 goblin 系统(仅更新已存在)
*
* @param storeId 门店ID
* @param items 待更新商品列表
* @return 结果
*/
ResponseDto<String> updateGoods(String storeId, List<GoblinSqbGoodsSyncParam> items);
/** /**
* 查询演出关联商品列表(先查 Redis 缓存,未命中则查 MySQL 并写入缓存) * 查询演出关联商品列表(先查 Redis 缓存,未命中则查 MySQL 并写入缓存)
......
...@@ -7,6 +7,7 @@ import lombok.Data; ...@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime;
/** /**
* <p> * <p>
...@@ -56,8 +57,8 @@ public class GoblinSqbGoodsExt implements Serializable { ...@@ -56,8 +57,8 @@ public class GoblinSqbGoodsExt implements Serializable {
*/ */
private String sqbSkuId; private String sqbSkuId;
private String createdAt; private LocalDateTime createdAt;
private String updatedAt; private LocalDateTime updatedAt;
} }
package com.liquidnet.service.goblin.controller; package com.liquidnet.service.goblin.controller;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import com.liquidnet.service.goblin.service.IGoblinSqbGoodsService; import com.liquidnet.service.goblin.service.IGoblinSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import com.liquidnet.service.goblin.param.shouqianba.request.GoblinSqbGoodsSyncParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 收钱吧商品同步 Controller * 收钱吧商品同步 Controller
...@@ -24,6 +27,9 @@ public class GoblinSqbGoodsController { ...@@ -24,6 +27,9 @@ public class GoblinSqbGoodsController {
@Autowired @Autowired
IGoblinSqbGoodsService goblinSqbGoodsService; IGoblinSqbGoodsService goblinSqbGoodsService;
@Autowired
GoblinRedisUtils goblinRedisUtils;
/** /**
* 查询所有商城及商品列表 * 查询所有商城及商品列表
* 后端自动拉取所有商城,循环获取每个商城的商品列表,聚合返回前端 * 后端自动拉取所有商城,循环获取每个商城的商品列表,聚合返回前端
...@@ -35,13 +41,33 @@ public class GoblinSqbGoodsController { ...@@ -35,13 +41,33 @@ public class GoblinSqbGoodsController {
} }
/** /**
* 批量同步商品到 goblin 系统 * 批量新增收钱吧商品
* 已存在则更新,不存在则新增(spuType=33) */
@PostMapping("/add")
@ApiOperation("批量新增收钱吧商品")
public ResponseDto<String> addGoods(@RequestParam("storeId") String storeId,
@RequestBody @Validated List<GoblinSqbGoodsSyncParam> items) {
String currentUid = CurrentUtil.getCurrentUid();
if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
log.warn("[收钱吧商品同步] 批量新增: 无权操作该店铺, uid={}, storeId={}", currentUid, storeId);
return ResponseDto.failure("无权操作该店铺");
}
return goblinSqbGoodsService.addGoods(storeId, items);
}
/**
* 批量更新收钱吧商品
*/ */
@PostMapping("/sync") @PostMapping("/update")
@ApiOperation("批量同步收钱吧商品") @ApiOperation("批量更新收钱吧商品")
public ResponseDto<String> sync(@RequestBody List<Map<String, String>> items) { public ResponseDto<String> updateGoods(@RequestParam("storeId") String storeId,
return goblinSqbGoodsService.syncGoods(items); @RequestBody @Validated List<GoblinSqbGoodsSyncParam> items) {
String currentUid = CurrentUtil.getCurrentUid();
if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
log.warn("[收钱吧商品同步] 批量更新: 无权操作该店铺, uid={}, storeId={}", currentUid, storeId);
return ResponseDto.failure("无权操作该店铺");
}
return goblinSqbGoodsService.updateGoods(storeId, items);
} }
/** /**
......
package com.liquidnet.service.goblin.service.impl; package com.liquidnet.service.goblin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo; import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo; import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo; import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
...@@ -22,22 +18,25 @@ import com.liquidnet.service.goblin.param.shouqianba.request.MallListQueryReques ...@@ -22,22 +18,25 @@ import com.liquidnet.service.goblin.param.shouqianba.request.MallListQueryReques
import com.liquidnet.service.goblin.param.shouqianba.request.MallProductsQueryRequest; import com.liquidnet.service.goblin.param.shouqianba.request.MallProductsQueryRequest;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallListQueryData; import com.liquidnet.service.goblin.param.shouqianba.response.data.MallListQueryData;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData; import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import com.liquidnet.service.goblin.param.shouqianba.request.GoblinSqbGoodsSyncParam;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService; import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.IGoblinSqbGoodsService; import com.liquidnet.service.goblin.service.IGoblinSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils; import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils; import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecVo;
import com.liquidnet.service.goblin.service.manage.IGoblinstoreMgtGoodsService;
import com.liquidnet.service.goblin.dto.manage.*;
import com.liquidnet.service.goblin.util.ObjectUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -54,22 +53,21 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService { ...@@ -54,22 +53,21 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {
private static final String SQB_MERCHANT_ID = "todo_merchant_id"; private static final String SQB_MERCHANT_ID = "todo_merchant_id";
private static final String SQB_MERCHANT_USER_ID = "todo_merchant_user_id"; private static final String SQB_MERCHANT_USER_ID = "todo_merchant_user_id";
private static final String SQB_ROLE = "super_admin"; private static final String SQB_ROLE = "super_admin";
private static final String SQB_STORE_ID = "0"; // 平台级商品 store_id=0
@Autowired @Autowired
private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper; private GoblinGoodsMapper goblinGoodsMapper;
@Autowired @Autowired
private IGoblinShouQianBaService goblinShouQianBaService; private GoblinGoodsSkuMapper goblinGoodsSkuMapper;
@Autowired @Autowired
private GoblinSqbPerformanceGoodsMapper goblinSqbPerformanceGoodsMapper; private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;
@Autowired @Autowired
private GoblinGoodsMapper goblinGoodsMapper; private GoblinSqbPerformanceGoodsMapper goblinSqbPerformanceGoodsMapper;
@Autowired @Autowired
private GoblinGoodsSkuMapper goblinGoodsSkuMapper; private IGoblinShouQianBaService goblinShouQianBaService;
@Autowired @Autowired
private GoblinSqbRedisUtils goblinSqbRedisUtils; private GoblinSqbRedisUtils goblinSqbRedisUtils;
...@@ -78,357 +76,365 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService { ...@@ -78,357 +76,365 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {
private GoblinRedisUtils goblinRedisUtils; private GoblinRedisUtils goblinRedisUtils;
@Autowired @Autowired
private GoblinMongoUtils goblinMongoUtils; private IGoblinstoreMgtGoodsService goblinstoreMgtGoodsService;
@Autowired
private QueueUtils queueUtils;
// ================================ 获取所有商城商品 ================================ private MallProductsQueryData querySqbProduct(String mallSn, String mallSignature, String sqbProductId) {
if (StringUtils.isEmpty(mallSn)) return null;
MallProductsQueryRequest request = new MallProductsQueryRequest();
request.setAppid(SQB_APPID);
request.setSeller(buildSeller());
CommonRequest.Mall mallId = new CommonRequest.Mall();
mallId.setMallSn(mallSn);
mallId.setSignature(mallSignature);
request.setMallID(mallId);
List<MallProductsQueryData> dataList = goblinShouQianBaService.queryMallProducts(request);
if (!CollectionUtils.isEmpty(dataList)) {
for (MallProductsQueryData data : dataList) {
if (sqbProductId.equals(data.getSpuId())) return data;
}
}
return null;
}
/**
* 获取所有商城及商品列表
* 自动拉取所有商城,循环获取每个商城的商品列表,聚合返回
*/
@Override @Override
public ResponseDto<List<GoblinSqbPerfGoodsVo>> getAllMallProducts() { public ResponseDto<List<GoblinSqbPerfGoodsVo>> getAllMallProducts() {
List<GoblinSqbPerfGoodsVo> result = new ArrayList<>();
try { try {
// 1. 调用收钱吧获取商城列表 MallListQueryRequest mallRequest = new MallListQueryRequest();
MallListQueryRequest mallListRequest = new MallListQueryRequest(); mallRequest.setAppid(SQB_APPID);
mallListRequest.setAppid(SQB_APPID);
// 过滤条件:只查已上线的商城
MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter(); MallListQueryRequest.Filter filter = new MallListQueryRequest.Filter();
CommonRequest.Seller seller = buildSeller(); filter.setSeller(buildSeller());
filter.setSeller(seller); mallRequest.setFilter(filter);
filter.setState((byte) 1); // 1=已上线 List<MallListQueryData> mallList = goblinShouQianBaService.queryMallList(mallRequest);
mallListRequest.setFilter(filter);
// 分页:每次取 100 个
MallListQueryRequest.Cursor cursor = new MallListQueryRequest.Cursor();
cursor.setCount(100);
mallListRequest.setCursor(cursor);
List<MallListQueryData> mallList = goblinShouQianBaService.queryMallList(mallListRequest);
if (CollectionUtils.isEmpty(mallList)) { if (CollectionUtils.isEmpty(mallList)) {
log.warn("[收钱吧] 未查询到任何商城信息"); return ResponseDto.success(new ArrayList<>());
return ResponseDto.success(result);
} }
// 2. 循环每个商城获取商品列表 List<GoblinSqbPerfGoodsVo> result = new ArrayList<>();
for (MallListQueryData mall : mallList) { for (MallListQueryData mall : mallList) {
String mallSn = mall.getMallSn(); MallProductsQueryRequest productRequest = new MallProductsQueryRequest();
if (StringUtils.isEmpty(mallSn)) continue; productRequest.setAppid(SQB_APPID);
productRequest.setSeller(buildSeller());
try {
MallProductsQueryRequest productsRequest = new MallProductsQueryRequest();
productsRequest.setAppid(SQB_APPID);
productsRequest.setSeller(seller);
CommonRequest.Mall mallId = new CommonRequest.Mall(); CommonRequest.Mall mallId = new CommonRequest.Mall();
mallId.setMallSn(mallSn); mallId.setMallSn(mall.getMallSn());
mallId.setSignature(mall.getSignature()); mallId.setSignature(mall.getSignature());
productsRequest.setMallID(mallId); productRequest.setMallID(mallId);
List<MallProductsQueryData> productsDataList = goblinShouQianBaService.queryMallProducts(productsRequest); List<MallProductsQueryData> products = goblinShouQianBaService.queryMallProducts(productRequest);
if (CollectionUtils.isEmpty(productsDataList)) { if (!CollectionUtils.isEmpty(products)) {
log.warn("[收钱吧商品同步] 商城 {} 获取商品列表为空", mallSn); for (MallProductsQueryData product : products) {
continue; List<MallProductsQueryData.Sku> skus = product.getSkuModels();
} if (CollectionUtils.isEmpty(skus)) {
result.add(buildPerfGoodsVo(product, null));
// 3. 将商品数据转换为 VO } else {
for (MallProductsQueryData productsData : productsDataList) { for (MallProductsQueryData.Sku sku : skus) {
if (productsData == null || CollectionUtils.isEmpty(productsData.getSkuModels())) continue; result.add(buildPerfGoodsVo(product, sku));
String coverPic = null;
if (!CollectionUtils.isEmpty(productsData.getConverImages())) {
coverPic = productsData.getConverImages().get(0);
} }
for (MallProductsQueryData.Sku sku : productsData.getSkuModels()) {
GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
vo.setSpuId(productsData.getSpuId());
vo.setSpuName(productsData.getTitle());
vo.setSkuId(sku.getSkuId());
String skuName = sku.getSkuName() != null ? sku.getSkuName() : sku.getSkuTitle();
vo.setSkuName(skuName);
vo.setPrice(sku.getPrice());
vo.setCoverPic(coverPic);
result.add(vo);
} }
} }
} catch (Exception e) {
log.error("[收钱吧商品同步] 获取商城 {} 商品列表异常", mallSn, e);
} }
} }
return ResponseDto.success(result);
} catch (Exception e) { } catch (Exception e) {
log.error("[收钱吧商品同步] getAllMallProducts 异常", e); log.error("[收钱吧] getAllMallProducts 异常", e);
return ResponseDto.failure("获取商城商品列表失败:" + e.getMessage()); return ResponseDto.failure("查询收钱吧商品列表失败");
} }
log.info("[收钱吧商品同步] getAllMallProducts 完成,共 {} 个 SKU", result.size());
return ResponseDto.success(result);
} }
// ================================ 批量同步商品到 goblin 系统 ================================ private GoblinSqbPerfGoodsVo buildPerfGoodsVo(MallProductsQueryData product, MallProductsQueryData.Sku sku) {
GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
vo.setSpuId(product.getSpuId());
vo.setSpuName(product.getTitle());
vo.setCoverPic(!CollectionUtils.isEmpty(product.getConverImages()) ? product.getConverImages().get(0) : "");
if (sku != null) {
vo.setSkuId(sku.getSkuId());
vo.setSkuName(sku.getSkuName() != null ? sku.getSkuName() : sku.getSkuTitle());
vo.setPrice(sku.getPrice());
} else {
vo.setSkuName(product.getTitle());
vo.setPrice(0L);
}
return vo;
}
/**
* 批量同步商品到 goblin 系统
* <p>
* 流程:对每个 sqbProductId,调用收钱吧查询商品详情,
* 写入 goblin_goods + goblin_goods_sku + goblin_sqb_goods_ext
* </p>
*
* @param items 待同步商品列表:每项包含 mallSn、sqbProductId、sqbProductSn(来自收钱吧)
* @return 同步结果摘要
*/
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ResponseDto<String> syncGoods(List<Map<String, String>> items) { public ResponseDto<String> addGoods(String storeId, List<GoblinSqbGoodsSyncParam> items) {
if (CollectionUtils.isEmpty(items)) { if (CollectionUtils.isEmpty(items)) return ResponseDto.failure("新增商品列表不能为空");
return ResponseDto.failure("同步商品列表不能为空"); int newCount = 0, existCount = 0, failCount = 0;
} String currentUid = "system";
int newCount = 0; for (GoblinSqbGoodsSyncParam item : items) {
int existCount = 0; String sqbProductId = item.getSqbProductId(), sqbProductSn = item.getSqbProductSn(),
int failCount = 0; mallSn = item.getMallSn(), mallSignature = item.getMallSignature();
String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
for (Map<String, String> item : items) {
String sqbProductId = item.get("sqbProductId");
String sqbProductSn = item.get("sqbProductSn");
String mallSn = item.get("mallSn");
String mallSignature = item.get("mallSignature"); // 商城签名,用于查商品
if (StringUtils.isEmpty(sqbProductId)) { if (StringUtils.isEmpty(sqbProductId)) {
log.warn("[收钱吧商品同步] sqbProductId 为空,跳过: {}", item);
failCount++; failCount++;
continue; continue;
} }
try { try {
// Step 1: 幂等检查 —— 已存在则跳过
LambdaQueryWrapper<GoblinSqbGoodsExt> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<GoblinSqbGoodsExt> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GoblinSqbGoodsExt::getSqbProductId, sqbProductId); queryWrapper.eq(GoblinSqbGoodsExt::getSqbProductId, sqbProductId);
GoblinSqbGoodsExt existing = goblinSqbGoodsExtMapper.selectOne(queryWrapper); if (goblinSqbGoodsExtMapper.selectCount(queryWrapper) > 0) {
if (existing != null) {
log.info("[收钱吧商品同步] 商品已存在,sqbProductId={}, spuId={}, skuId={}",
sqbProductId, existing.getSpuId(), existing.getSkuId());
existCount++; existCount++;
continue; continue;
} }
// Step 2: 查询收钱吧商品详情(通过 queryMallProducts) MallProductsQueryData productsData = querySqbProduct(mallSn, mallSignature, sqbProductId);
MallProductsQueryData productsData = null; if (null == productsData) {
if (!StringUtils.isEmpty(mallSn)) { failCount++;
MallProductsQueryRequest productsRequest = new MallProductsQueryRequest(); continue;
productsRequest.setAppid(SQB_APPID); }
productsRequest.setSeller(buildSeller());
CommonRequest.Mall mallId = new CommonRequest.Mall(); // 1. 组装 AddParam
mallId.setMallSn(mallSn); GoblinStoreMgtGoodsAddParam addParam = buildMgtGoodsAddParam(storeId, productsData);
mallId.setSignature(mallSignature);
productsRequest.setMallID(mallId); // 2. 初始化 VOs
List<MallProductsQueryData> productsDataList = goblinShouQianBaService.queryMallProducts(productsRequest); LocalDateTime now = LocalDateTime.now();
if (!CollectionUtils.isEmpty(productsDataList)) { GoblinGoodsInfoVo goodsInfoVo = addParam.initGoodsInfoVo();
for (MallProductsQueryData data : productsDataList) { goodsInfoVo.setCreatedBy(currentUid);
if (sqbProductId.equals(data.getSpuId())) { goodsInfoVo.setCreatedAt(now);
productsData = data; goodsInfoVo.setSpuType(33);
break; goodsInfoVo.setVirtualFlg("1");
ArrayList<GoblinGoodsSpecVo> goodsSpecVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
addParam.initGoodsSkuInfoVo(goodsInfoVo, goodsSkuInfoVoList, goodsSpecVoList);
for (GoblinGoodsSkuInfoVo skuVo : goodsSkuInfoVoList) {
skuVo.setSkuType(33);
skuVo.setVirtualFlg("1");
skuVo.setCreatedBy(currentUid);
skuVo.setCreatedAt(now);
}
// 3. 调用管理端 Service 加商
goblinstoreMgtGoodsService.goodsAdd(goodsInfoVo, goodsSkuInfoVoList);
// 4. 建立映射
List<MallProductsQueryData.Sku> sqbSkus = productsData.getSkuModels();
if (CollectionUtils.isEmpty(sqbSkus)) {
String skuId = goodsSkuInfoVoList.get(0).getSkuId();
goblinSqbGoodsExtMapper.insert(buildExt(goodsInfoVo.getSpuId(), skuId, mallSn, sqbProductId, sqbProductSn, null, now));
} else {
for (int i = 0; i < sqbSkus.size(); i++) {
String skuId = goodsSkuInfoVoList.get(i).getSkuId();
goblinSqbGoodsExtMapper.insert(buildExt(goodsInfoVo.getSpuId(), skuId, mallSn, sqbProductId, sqbProductSn, sqbSkus.get(i).getSkuId(), now));
}
} }
newCount++;
} catch (Exception e) {
log.error("[收钱吧新增商品同步] 异常, sqbProductId={}", sqbProductId, e);
failCount++;
}
}
return ResponseDto.success(String.format("新增完成:同步 %d, 已存在 %d, 失败 %d", newCount, existCount, failCount));
} }
@Override
@Transactional(rollbackFor = Exception.class)
public ResponseDto<String> updateGoods(String storeId, List<GoblinSqbGoodsSyncParam> items) {
if (CollectionUtils.isEmpty(items)) return ResponseDto.failure("更新商品列表不能为空");
int updateCount = 0, notFoundCount = 0, failCount = 0;
String currentUid = "system";
for (GoblinSqbGoodsSyncParam item : items) {
String sqbProductId = item.getSqbProductId(), mallSn = item.getMallSn(), mallSignature = item.getMallSignature();
try {
LambdaQueryWrapper<GoblinSqbGoodsExt> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GoblinSqbGoodsExt::getSqbProductId, sqbProductId);
List<GoblinSqbGoodsExt> existingExts = goblinSqbGoodsExtMapper.selectList(queryWrapper);
if (CollectionUtils.isEmpty(existingExts)) {
notFoundCount++;
continue;
} }
String spuId = existingExts.get(0).getSpuId();
GoblinGoodsInfoVo mgtGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
if (null == mgtGoodsInfoVo) {
notFoundCount++;
continue;
} }
// Step 3: 生成本地 spuId MallProductsQueryData productsData = querySqbProduct(mallSn, mallSignature, sqbProductId);
String spuId = IDGenerator.nextSnowId(); if (null == productsData) {
failCount++;
continue;
}
// Step 4: 构建 GoblinGoodsInfoVo // 2. 编辑 SPU
GoblinGoodsInfoVo goodsInfoVo = buildGoblinGoodsInfoVo(spuId, productsData, now); GoblinStoreMgtGoodsAddParam addParam = buildMgtGoodsAddParam(storeId, productsData);
log.info("[收钱吧商品同步] 准备写入商品,spuId={}", spuId); addParam.setSpuId(spuId);
goblinstoreMgtGoodsService.goodsEditSpu(currentUid, addParam, mgtGoodsInfoVo);
// Step 5: 遍历 SKU,构建 GoblinGoodsSkuInfoVo 及写 EXT 表 // 3. 编辑 SKU
List<MallProductsQueryData.Sku> sqbSkus = productsData != null && !CollectionUtils.isEmpty(productsData.getSkuModels()) Map<String, String> sqbToSysSkuMap = new HashMap<>();
? productsData.getSkuModels() : Collections.emptyList(); for (GoblinSqbGoodsExt ext : existingExts) {
List<GoblinGoodsSkuInfoVo> skuInfoVos = new ArrayList<>(); sqbToSysSkuMap.put(ext.getSqbSkuId() != null ? ext.getSqbSkuId() : "PLACEHOLDER", ext.getSkuId());
List<String> skuIdList = new ArrayList<>(); }
List<MallProductsQueryData.Sku> sqbSkus = productsData.getSkuModels();
if (CollectionUtils.isEmpty(sqbSkus)) { if (CollectionUtils.isEmpty(sqbSkus)) {
// 没有 SKU 数据时,创建一个占位 SKU String skuId = sqbToSysSkuMap.get("PLACEHOLDER");
String skuId = IDGenerator.nextSnowId(); if (skuId != null) processSkuUpdate(currentUid, storeId, skuId, productsData, null);
GoblinGoodsSkuInfoVo skuVo = buildGoblinGoodsSkuInfoVo(skuId, spuId, null, productsData, now);
skuInfoVos.add(skuVo);
skuIdList.add(skuId);
GoblinSqbGoodsExt ext = buildExt(spuId, skuId, mallSn, sqbProductId, sqbProductSn, null, now);
goblinSqbGoodsExtMapper.insert(ext);
log.info("[收钱吧商品同步] 写入占位 SKU,skuId={}", skuId);
} else { } else {
for (MallProductsQueryData.Sku sqbSku : sqbSkus) { for (MallProductsQueryData.Sku sqbSku : sqbSkus) {
String skuId = IDGenerator.nextSnowId(); String skuId = sqbToSysSkuMap.get(sqbSku.getSkuId());
GoblinGoodsSkuInfoVo skuVo = buildGoblinGoodsSkuInfoVo(skuId, spuId, sqbSku, productsData, now); if (skuId != null) processSkuUpdate(currentUid, storeId, skuId, productsData, sqbSku);
skuInfoVos.add(skuVo); }
skuIdList.add(skuId); }
updateCount++;
GoblinSqbGoodsExt ext = buildExt(spuId, skuId, mallSn, sqbProductId, sqbProductSn, sqbSku.getSkuId(), now);
goblinSqbGoodsExtMapper.insert(ext);
log.info("[收钱吧商品同步] 写入 SKU,skuId={}, sqbSkuId={}", skuId, sqbSku.getSkuId());
}
}
goodsInfoVo.setSkuIdList(skuIdList);
// Step 6: 组装价格区间
if (!CollectionUtils.isEmpty(skuInfoVos)) {
long minPrice = skuInfoVos.stream().mapToLong(s -> s.getPrice() != null ? s.getPrice().multiply(BigDecimal.valueOf(100)).longValue() : 0L).min().orElse(0L);
long maxPrice = skuInfoVos.stream().mapToLong(s -> s.getPrice() != null ? s.getPrice().multiply(BigDecimal.valueOf(100)).longValue() : 0L).max().orElse(0L);
goodsInfoVo.setPriceGe(BigDecimal.valueOf(minPrice).divide(BigDecimal.valueOf(100)));
goodsInfoVo.setPriceLe(BigDecimal.valueOf(maxPrice).divide(BigDecimal.valueOf(100)));
goodsInfoVo.setSellPrice(BigDecimal.valueOf(minPrice).divide(BigDecimal.valueOf(100)));
}
// Step 7: 写 MongoDB
goblinMongoUtils.setGoodsInfoVo(goodsInfoVo);
goblinMongoUtils.setGoodsSkuInfoVos(skuInfoVos);
// Step 8: 发队列通知及 Redis 库存写入
LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
LinkedList<Object[]> initGoodsObjs = CollectionUtil.linkedListObjectArr();
LinkedList<Object[]> initGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
LinkedList<Object[]> initGoodsImageObjs = CollectionUtil.linkedListObjectArr();
toMqSqls.add(SqlMapping.get("goblin_goods.insert"));
initGoodsObjs.add(new Object[]{
spuId, goodsInfoVo.getSpuNo(), goodsInfoVo.getSpuBarCode(), goodsInfoVo.getSpuErpCode(), goodsInfoVo.getErpType(),
goodsInfoVo.getName(), goodsInfoVo.getSubtitle(), goodsInfoVo.getSellPrice(), goodsInfoVo.getPriceGe(), goodsInfoVo.getPriceLe(),
goodsInfoVo.getIntro(), goodsInfoVo.getDetails(), goodsInfoVo.getCoverPic(), goodsInfoVo.getVideo(), goodsInfoVo.getSpecMode(),
goodsInfoVo.getStoreId(), goodsInfoVo.getCateFid(), goodsInfoVo.getCateSid(), goodsInfoVo.getCateTid(), goodsInfoVo.getStoreCateFid(),
goodsInfoVo.getStoreCateSid(), goodsInfoVo.getStoreCateTid(), goodsInfoVo.getBrandId(), goodsInfoVo.getShelvesHandle(), goodsInfoVo.getShelvesTime(),
goodsInfoVo.getSpuValidity(), goodsInfoVo.getVirtualFlg(), goodsInfoVo.getStatus(), goodsInfoVo.getShelvesStatus(), goodsInfoVo.getSpuAppear(),
goodsInfoVo.getShelvesAt(), goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(), goodsInfoVo.getLogisticsTemplate()
});
toMqSqls.add(SqlMapping.get("goblin_goods_sku.insert"));
for (GoblinGoodsSkuInfoVo skuInfoVo : skuInfoVos) {
// 写 Redis 库存
goblinRedisUtils.setSkuStock(null, skuInfoVo.getSkuId(), skuInfoVo.getStock());
initGoodsSkuObjs.add(new Object[]{
skuInfoVo.getSkuId(), skuInfoVo.getSpuId(), skuInfoVo.getSkuNo(), skuInfoVo.getSkuBarCode(), skuInfoVo.getSkuErpCode(),
skuInfoVo.getErpType(), skuInfoVo.getErpHosting(), skuInfoVo.getErpWarehouseNo(), skuInfoVo.getSkuType(), skuInfoVo.getName(),
skuInfoVo.getSubtitle(), skuInfoVo.getSellPrice(), skuInfoVo.getSkuPic(), skuInfoVo.getSkuIsbn(), skuInfoVo.getStock(),
skuInfoVo.getSkuStock(), skuInfoVo.getWarningStock(), skuInfoVo.getPrice(), skuInfoVo.getPriceMember(), skuInfoVo.getWeight(),
skuInfoVo.getBuyFactor(), skuInfoVo.getBuyRoster(), skuInfoVo.getBuyLimit(), skuInfoVo.getStoreId(), skuInfoVo.getSkuValidity(),
skuInfoVo.getVirtualFlg(), skuInfoVo.getStatus(), skuInfoVo.getShelvesStatus(), skuInfoVo.getSkuAppear(), skuInfoVo.getShelvesAt(),
goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(), skuInfoVo.getLogisticsTemplate()
});
}
toMqSqls.add(SqlMapping.get("goblin_goods_image.insert_byreplace"));
if (!CollectionUtils.isEmpty(goodsInfoVo.getImageList())) {
goodsInfoVo.getImageList().forEach(imageUrl -> initGoodsImageObjs.add(new Object[]{spuId, imageUrl}));
}
queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(),
SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsSkuObjs, initGoodsImageObjs));
log.info("[收钱吧商品同步] Redis及MongoDB写入、MQ消息发送成功,sqbProductId={}", sqbProductId);
newCount++;
} catch (Exception e) { } catch (Exception e) {
log.error("[收钱吧商品同步] 处理商品异常,sqbProductId={}", sqbProductId, e); log.error("[收钱吧更新商品同步] 异常, sqbProductId={}", sqbProductId, e);
failCount++; failCount++;
} }
} }
return ResponseDto.success(String.format("更新完成:更新 %d, 未找到 %d, 失败 %d", updateCount, notFoundCount, failCount));
}
private void processSkuUpdate(String currentUid, String storeId, String skuId, MallProductsQueryData productsData, MallProductsQueryData.Sku sqbSku) {
GoblinGoodsSkuInfoVo mgtGoodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
if (null == mgtGoodsSkuInfoVo) return;
GoblinGoodsInfoVo mgtGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(mgtGoodsSkuInfoVo.getSpuId());
if (null == mgtGoodsInfoVo) return;
String summary = String.format("同步完成:新增 %d 条,已存在 %d 条,失败 %d 条", newCount, existCount, failCount); GoblinStoreMgtGoodsEditSkuParam editSkuParam = new GoblinStoreMgtGoodsEditSkuParam();
log.info("[收钱吧商品同步] {}", summary); editSkuParam.setStoreId(storeId);
return ResponseDto.success(summary); editSkuParam.setSpuId(mgtGoodsSkuInfoVo.getSpuId());
editSkuParam.setSkuId(skuId);
editSkuParam.setSkuPic(mgtGoodsSkuInfoVo.getSkuPic());
if (!CollectionUtils.isEmpty(productsData.getConverImages())) {
editSkuParam.setSkuPic(productsData.getConverImages().get(0));
} }
// ================================ 查询演出关联商品 ================================ if (sqbSku != null) {
BigDecimal price = BigDecimal.valueOf(sqbSku.getPrice()).divide(BigDecimal.valueOf(100));
editSkuParam.setPrice(price);
editSkuParam.setSellPrice(price);
editSkuParam.setPriceMember(price);
} else {
editSkuParam.setPrice(mgtGoodsSkuInfoVo.getPrice());
editSkuParam.setSellPrice(mgtGoodsSkuInfoVo.getSellPrice());
editSkuParam.setPriceMember(mgtGoodsSkuInfoVo.getPriceMember());
}
editSkuParam.setSkuSpecList(mgtGoodsSkuInfoVo.getSkuSpecList());
editSkuParam.setSkuAppear("0");
editSkuParam.setBuyFactor("0");
editSkuParam.setSkuValidity(DateUtil.Formatter.yyyyMMddHHmmss.format(mgtGoodsSkuInfoVo.getSkuValidity()));
// 库存增量逻辑
int newSqbTotal = (sqbSku != null && sqbSku.getQuantity() != null) ? sqbSku.getQuantity().intValue() : 0;
int oldTotal = mgtGoodsSkuInfoVo.getStock() != null ? mgtGoodsSkuInfoVo.getStock() : 0;
int operStock = newSqbTotal - oldTotal;
if (operStock != 0) {
int operStockVal = Math.abs(operStock);
int currentRedisSurplus = goblinRedisUtils.getSkuStock(null, skuId);
if (operStock < 0) {
if (currentRedisSurplus >= operStockVal) {
if (goblinRedisUtils.decrSkuStock(null, skuId, operStockVal) >= 0) {
editSkuParam.setStock(oldTotal - operStockVal);
editSkuParam.setSkuStock(mgtGoodsSkuInfoVo.getSkuStock() - operStockVal);
}
} else {
goblinRedisUtils.setSkuStock(null, skuId, newSqbTotal);
editSkuParam.setStock(newSqbTotal);
editSkuParam.setSkuStock(newSqbTotal);
}
} else {
goblinRedisUtils.incrSkuStock(null, skuId, operStockVal);
editSkuParam.setStock(oldTotal + operStockVal);
editSkuParam.setSkuStock(mgtGoodsSkuInfoVo.getSkuStock() + operStockVal);
}
} else {
editSkuParam.setStock(oldTotal);
editSkuParam.setSkuStock(mgtGoodsSkuInfoVo.getSkuStock());
}
goblinstoreMgtGoodsService.goodsEditSku(currentUid, editSkuParam, mgtGoodsSkuInfoVo, mgtGoodsInfoVo, null, null);
}
private GoblinStoreMgtGoodsAddParam buildMgtGoodsAddParam(String storeId, MallProductsQueryData productsData) {
GoblinStoreMgtGoodsAddParam param = new GoblinStoreMgtGoodsAddParam();
param.setStoreId(storeId);
param.setName(productsData.getTitle());
param.setIntro(productsData.getProductIntroduction());
param.setImageList(new ArrayList<>(productsData.getConverImages()));
param.setDetails(productsData.getProductIntroduction());
param.setSpecMode("1");
param.setShelvesHandle("1");
param.setVirtualFlg("1");
List<GoblinStoreMgtGoodsAddSkuParam> skuParams = new ArrayList<>();
List<MallProductsQueryData.Sku> sqbSkus = productsData.getSkuModels();
if (CollectionUtils.isEmpty(sqbSkus)) {
skuParams.add(buildMgtSkuParam(productsData.getTitle(), null, productsData.getConverImages()));
} else {
for (MallProductsQueryData.Sku sqbSku : sqbSkus) {
skuParams.add(buildMgtSkuParam(null, sqbSku, productsData.getConverImages()));
}
}
param.setSkuParamList(skuParams);
return param;
}
private GoblinStoreMgtGoodsAddSkuParam buildMgtSkuParam(String defaultName, MallProductsQueryData.Sku sqbSku, List<String> images) {
GoblinStoreMgtGoodsAddSkuParam sku = new GoblinStoreMgtGoodsAddSkuParam();
sku.setSkuPic(!CollectionUtils.isEmpty(images) ? images.get(0) : "");
sku.setSkuSpecList(new ArrayList<>());
if (sqbSku != null) {
BigDecimal price = BigDecimal.valueOf(sqbSku.getPrice()).divide(BigDecimal.valueOf(100));
sku.setPrice(price);
sku.setSellPrice(price);
sku.setStock(sqbSku.getQuantity() != null ? sqbSku.getQuantity().intValue() : 0);
} else {
sku.setPrice(BigDecimal.ZERO);
sku.setSellPrice(BigDecimal.ZERO);
sku.setStock(0);
}
sku.setSkuValidity(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now().plusYears(1)));
sku.setSkuAppear("0");
sku.setBuyFactor("0");
return sku;
}
/**
* 查询演出关联商品列表
* 先查 Redis 缓存(TTL 5min),未命中则查 MySQL 并写入缓存
*/
@Override @Override
public ResponseDto<List<GoblinSqbPerfGoodsVo>> getPerfGoods(String performancesId) { public ResponseDto<List<GoblinSqbPerfGoodsVo>> getPerfGoods(String performancesId) {
// 1. 先查 Redis 缓存
List<GoblinSqbPerfGoodsVo> cached = goblinSqbRedisUtils.getPerfGoods(performancesId); List<GoblinSqbPerfGoodsVo> cached = goblinSqbRedisUtils.getPerfGoods(performancesId);
if (cached != null) { if (cached != null) return ResponseDto.success(cached);
return ResponseDto.success(cached);
}
// 2. 缓存未命中,查 MySQL
try { try {
LambdaQueryWrapper<GoblinSqbPerformanceGoods> query = new LambdaQueryWrapper<>(); LambdaQueryWrapper<GoblinSqbPerformanceGoods> query = new LambdaQueryWrapper<>();
query.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId) query.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId).eq(GoblinSqbPerformanceGoods::getStatus, 1).orderByAsc(GoblinSqbPerformanceGoods::getSort);
.eq(GoblinSqbPerformanceGoods::getStatus, 1)
.orderByAsc(GoblinSqbPerformanceGoods::getSort);
List<GoblinSqbPerformanceGoods> relations = goblinSqbPerformanceGoodsMapper.selectList(query); List<GoblinSqbPerformanceGoods> relations = goblinSqbPerformanceGoodsMapper.selectList(query);
if (CollectionUtils.isEmpty(relations)) { if (CollectionUtils.isEmpty(relations)) {
List<GoblinSqbPerfGoodsVo> empty = new ArrayList<>(); List<GoblinSqbPerfGoodsVo> empty = new ArrayList<>();
goblinSqbRedisUtils.setPerfGoods(performancesId, empty); goblinSqbRedisUtils.setPerfGoods(performancesId, empty);
return ResponseDto.success(empty); return ResponseDto.success(empty);
} }
List<String> skuIds = relations.stream().map(GoblinSqbPerformanceGoods::getSkuId).collect(Collectors.toList());
// 收集 skuId 和 spuId List<String> spuIds = relations.stream().map(GoblinSqbPerformanceGoods::getSpuId).distinct().collect(Collectors.toList());
List<String> skuIds = relations.stream() List<GoblinGoodsSku> skuList = goblinGoodsSkuMapper.selectList(new LambdaQueryWrapper<GoblinGoodsSku>().in(GoblinGoodsSku::getSkuId, skuIds));
.map(GoblinSqbPerformanceGoods::getSkuId) Map<String, GoblinGoodsSku> skuMap = skuList.stream().collect(Collectors.toMap(GoblinGoodsSku::getSkuId, Function.identity(), (a, b) -> a));
.collect(Collectors.toList()); List<GoblinGoods> spuList = goblinGoodsMapper.selectList(new LambdaQueryWrapper<GoblinGoods>().in(GoblinGoods::getSpuId, spuIds));
List<String> spuIds = relations.stream() Map<String, GoblinGoods> spuMap = spuList.stream().collect(Collectors.toMap(GoblinGoods::getSpuId, Function.identity(), (a, b) -> a));
.map(GoblinSqbPerformanceGoods::getSpuId)
.distinct()
.collect(Collectors.toList());
// 批量查询 SKU 信息
LambdaQueryWrapper<GoblinGoodsSku> skuQuery = new LambdaQueryWrapper<>();
skuQuery.in(GoblinGoodsSku::getSkuId, skuIds);
List<GoblinGoodsSku> skuList = goblinGoodsSkuMapper.selectList(skuQuery);
Map<String, GoblinGoodsSku> skuMap = skuList.stream()
.collect(Collectors.toMap(GoblinGoodsSku::getSkuId, Function.identity(), (a, b) -> a));
// 批量查询 SPU 信息
LambdaQueryWrapper<GoblinGoods> spuQuery = new LambdaQueryWrapper<>();
spuQuery.in(GoblinGoods::getSpuId, spuIds);
List<GoblinGoods> spuList = goblinGoodsMapper.selectList(spuQuery);
Map<String, GoblinGoods> spuMap = spuList.stream()
.collect(Collectors.toMap(GoblinGoods::getSpuId, Function.identity(), (a, b) -> a));
// 组装 VO
List<GoblinSqbPerfGoodsVo> result = new ArrayList<>(); List<GoblinSqbPerfGoodsVo> result = new ArrayList<>();
for (GoblinSqbPerformanceGoods rel : relations) { for (GoblinSqbPerformanceGoods rel : relations) {
GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo(); GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
vo.setSkuId(rel.getSkuId()); vo.setSkuId(rel.getSkuId()); vo.setSpuId(rel.getSpuId()); vo.setSort(rel.getSort());
vo.setSpuId(rel.getSpuId());
vo.setSort(rel.getSort());
GoblinGoodsSku sku = skuMap.get(rel.getSkuId()); GoblinGoodsSku sku = skuMap.get(rel.getSkuId());
if (sku != null) { if (sku != null) { vo.setSkuName(sku.getName()); vo.setPrice(sku.getPrice() != null ? sku.getPrice().longValue() : null); }
vo.setSkuName(sku.getName());
vo.setPrice(sku.getPrice() != null ? sku.getPrice().longValue() : null);
}
GoblinGoods spu = spuMap.get(rel.getSpuId()); GoblinGoods spu = spuMap.get(rel.getSpuId());
if (spu != null) { if (spu != null) { vo.setSpuName(spu.getName()); vo.setCoverPic(spu.getCoverPic()); }
vo.setSpuName(spu.getName());
vo.setCoverPic(spu.getCoverPic());
}
result.add(vo); result.add(vo);
} }
// 3. 写入 Redis 缓存(TTL 5min)
goblinSqbRedisUtils.setPerfGoods(performancesId, result); goblinSqbRedisUtils.setPerfGoods(performancesId, result);
return ResponseDto.success(result); return ResponseDto.success(result);
} catch (Exception e) { } catch (Exception e) {
log.error("[收钱吧] getPerfGoods 异常,performancesId={}", performancesId, e); log.error("[收钱吧] getPerfGoods 异常", e);
return ResponseDto.failure("查询演出关联商品失败:" + e.getMessage()); return ResponseDto.failure("查询失败");
} }
} }
// ================================ 私有辅助方法 ================================
private CommonRequest.Seller buildSeller() { private CommonRequest.Seller buildSeller() {
CommonRequest.Seller seller = new CommonRequest.Seller(); CommonRequest.Seller seller = new CommonRequest.Seller();
seller.setMerchantId(SQB_MERCHANT_ID); seller.setMerchantId(SQB_MERCHANT_ID);
...@@ -437,110 +443,11 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService { ...@@ -437,110 +443,11 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {
return seller; return seller;
} }
/** private GoblinSqbGoodsExt buildExt(String spuId, String skuId, String mallSn, String sqbProductId, String sqbProductSn, String sqbSkuId, LocalDateTime now) {
* 构建 GoblinGoodsInfoVo(收钱吧商品固定字段)
*/
private GoblinGoodsInfoVo buildGoblinGoodsInfoVo(String spuId, MallProductsQueryData productsData, String now) {
GoblinGoodsInfoVo goods = new GoblinGoodsInfoVo();
goods.setSpuId(spuId);
goods.setSpuNo(spuId);
goods.setSpuType(33); // 33 = 收钱吧商品
goods.setVirtualFlg("1"); // 虚拟商品
goods.setStatus("3"); // 3 = 审核通过(收钱吧商品无需审核)
goods.setShelvesHandle("2"); // 2 = 直接上架售卖
goods.setShelvesStatus("3"); // 3 = 上架
goods.setSpuAppear("0"); // 默认展示
goods.setDelFlg("0"); // 未删除
goods.setStoreId(SQB_STORE_ID);
goods.setCreatedBy("system");
goods.setCreatedAt(LocalDateTime.now());
goods.setUpdatedBy("system");
goods.setUpdatedAt(LocalDateTime.now());
goods.setImageList(new ArrayList<>());
if (productsData != null) {
goods.setName(productsData.getTitle());
goods.setIntro(productsData.getProductIntroduction());
if (!CollectionUtils.isEmpty(productsData.getConverImages())) {
goods.setCoverPic(productsData.getConverImages().get(0));
goods.setImageList(new ArrayList<>(productsData.getConverImages()));
}
} else {
goods.setName("收钱吧商品-" + spuId);
}
goods.setSkuIdList(new ArrayList<>());
return goods;
}
/**
* 构建 GoblinGoodsSkuInfoVo 实体
*/
private GoblinGoodsSkuInfoVo buildGoblinGoodsSkuInfoVo(String skuId, String spuId,
MallProductsQueryData.Sku sqbSku,
MallProductsQueryData productsData,
String now) {
GoblinGoodsSkuInfoVo sku = new GoblinGoodsSkuInfoVo();
sku.setSkuId(skuId);
sku.setSpuId(spuId);
sku.setSkuNo(skuId);
sku.setSkuType(33); // 33 = 收钱吧商品
sku.setVirtualFlg("1"); // 虚拟商品
sku.setStatus("3"); // 审核通过
sku.setShelvesHandle("2"); // 直接上架
sku.setShelvesStatus("3"); // 上架
sku.setSkuAppear("0");
sku.setBuyFactor("0"); // 全部用户可买
sku.setBuyLimit(0); // 不限购
sku.setDelFlg("0");
sku.setStoreId(SQB_STORE_ID);
sku.setCreatedBy("system");
sku.setCreatedAt(LocalDateTime.now());
sku.setUpdatedBy("system");
sku.setUpdatedAt(LocalDateTime.now());
if (sqbSku != null) {
// SKU 名称
String skuName = sqbSku.getSkuName() != null ? sqbSku.getSkuName() : sqbSku.getSkuTitle();
sku.setName(skuName != null ? skuName : (productsData != null ? productsData.getTitle() : "规格"));
// 收钱吧价格单位为分,转元
if (sqbSku.getPrice() != null) {
BigDecimal priceYuan = BigDecimal.valueOf(sqbSku.getPrice()).divide(BigDecimal.valueOf(100));
sku.setPrice(priceYuan);
sku.setSellPrice(priceYuan);
}
// 库存:优先取 quantity,若为 null 则默认 9999
int stock = sqbSku.getQuantity() != null ? sqbSku.getQuantity().intValue() : 9999;
sku.setStock(stock);
sku.setSkuStock(stock);
if (productsData != null && !CollectionUtils.isEmpty(productsData.getConverImages())) {
sku.setSkuPic(productsData.getConverImages().get(0));
}
} else {
sku.setName(productsData != null ? productsData.getTitle() : "规格");
sku.setPrice(BigDecimal.ZERO);
sku.setSellPrice(BigDecimal.ZERO);
sku.setStock(0);
sku.setSkuStock(0);
}
return sku;
}
/**
* 构建 GoblinSqbGoodsExt 实体
*/
private GoblinSqbGoodsExt buildExt(String spuId, String skuId, String mallSn,
String sqbProductId, String sqbProductSn,
String sqbSkuId, String now) {
GoblinSqbGoodsExt ext = new GoblinSqbGoodsExt(); GoblinSqbGoodsExt ext = new GoblinSqbGoodsExt();
ext.setSpuId(spuId); ext.setSpuId(spuId); ext.setSkuId(skuId); ext.setMallSn(mallSn);
ext.setSkuId(skuId); ext.setSqbProductId(sqbProductId); ext.setSqbProductSn(sqbProductSn); ext.setSqbSkuId(sqbSkuId);
ext.setMallSn(mallSn); ext.setCreatedAt(now); ext.setUpdatedAt(now);
ext.setSqbProductId(sqbProductId);
ext.setSqbProductSn(sqbProductSn);
ext.setSqbSkuId(sqbSkuId);
ext.setCreatedAt(now);
ext.setUpdatedAt(now);
return ext; return ext;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment