记得上下班打卡 | git大法好,push需谨慎
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liquidnet-bus-v1
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
董敬伟
liquidnet-bus-v1
Commits
fc3794cd
Commit
fc3794cd
authored
Mar 26, 2026
by
姜秀龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
收钱吧 商品同步相关逻辑整理修改
parent
111223e2
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
387 additions
and
413 deletions
+387
-413
sqb_goods_integration.sql
docu/sqb_goods_integration.sql
+8
-8
GoblinSqbGoodsSyncParam.java
...lin/param/shouqianba/request/GoblinSqbGoodsSyncParam.java
+31
-0
IGoblinSqbGoodsService.java
...uidnet/service/goblin/service/IGoblinSqbGoodsService.java
+15
-6
GoblinSqbGoodsExt.java
...om/liquidnet/service/goblin/entity/GoblinSqbGoodsExt.java
+3
-2
GoblinSqbGoodsController.java
...t/service/goblin/controller/GoblinSqbGoodsController.java
+33
-7
GoblinSqbGoodsServiceImpl.java
...ervice/goblin/service/impl/GoblinSqbGoodsServiceImpl.java
+297
-390
No files found.
docu/sqb_goods_integration.sql
View file @
fc3794cd
...
...
@@ -6,8 +6,8 @@ CREATE TABLE `goblin_sqb_mall_info` (
`signature`
VARCHAR
(
256
)
NOT
NULL
COMMENT
'商城密钥'
,
`store_id`
VARCHAR
(
64
)
NOT
NULL
COMMENT
'关联我方店铺ID'
,
`status`
TINYINT
NOT
NULL
DEFAULT
1
COMMENT
'0-禁用 1-启用'
,
`created_at`
DATETIME
NO
T
NULL
,
`updated_at`
DATETIME
NO
T
NULL
,
`created_at`
timestamp
NULL
DEFAUL
T
NULL
,
`updated_at`
timestamp
NULL
DEFAUL
T
NULL
,
PRIMARY
KEY
(
`mid`
),
UNIQUE
KEY
`uk_mall_sn`
(
`mall_sn`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'收钱吧商城信息'
;
...
...
@@ -20,8 +20,8 @@ CREATE TABLE `goblin_sqb_goods_ext` (
`sqb_product_id`
VARCHAR
(
64
)
NOT
NULL
COMMENT
'收钱吧商品ID'
,
`sqb_product_sn`
VARCHAR
(
64
)
NOT
NULL
COMMENT
'收钱吧商品编号'
,
`sqb_sku_id`
VARCHAR
(
64
)
COMMENT
'收钱吧SKU ID'
,
`created_at`
DATETIME
NO
T
NULL
,
`updated_at`
DATETIME
NO
T
NULL
,
`created_at`
timestamp
NULL
DEFAUL
T
NULL
,
`updated_at`
timestamp
NULL
DEFAUL
T
NULL
,
PRIMARY
KEY
(
`mid`
),
UNIQUE
KEY
`uk_spu_sku`
(
`spu_id`
,
`sku_id`
),
KEY
`idx_mall_sn`
(
`mall_sn`
)
...
...
@@ -34,8 +34,8 @@ CREATE TABLE `goblin_sqb_performance_goods` (
`sku_id`
VARCHAR
(
64
)
NOT
NULL
COMMENT
'SKU ID'
,
`sort`
INT
NOT
NULL
DEFAULT
0
COMMENT
'排序权重'
,
`status`
TINYINT
NOT
NULL
DEFAULT
1
COMMENT
'0-禁用 1-启用'
,
`created_at`
DATETIME
NO
T
NULL
,
`updated_at`
DATETIME
NO
T
NULL
,
`created_at`
timestamp
NULL
DEFAUL
T
NULL
,
`updated_at`
timestamp
NULL
DEFAUL
T
NULL
,
PRIMARY
KEY
(
`mid`
),
UNIQUE
KEY
`uk_perf_sku`
(
`performances_id`
,
`sku_id`
),
KEY
`idx_performances_id`
(
`performances_id`
)
...
...
@@ -59,8 +59,8 @@ CREATE TABLE `goblin_sqb_order` (
`coupon_expire_time`
DATETIME
COMMENT
'券码过期时间'
,
`status`
TINYINT
NOT
NULL
DEFAULT
0
COMMENT
'0-待支付 1-已支付 2-已核销 3-已退款 4-退款中 9-失败'
,
`refund_reason`
VARCHAR
(
256
)
COMMENT
'退款原因'
,
`created_at`
DATETIME
NO
T
NULL
,
`updated_at`
DATETIME
NO
T
NULL
,
`created_at`
timestamp
NULL
DEFAUL
T
NULL
,
`updated_at`
timestamp
NULL
DEFAUL
T
NULL
,
PRIMARY
KEY
(
`mid`
),
UNIQUE
KEY
`uk_order_id`
(
`order_id`
),
KEY
`idx_user_id`
(
`user_id`
),
...
...
liquidnet-bus-api/liquidnet-service-goblin-api/src/main/java/com/liquidnet/service/goblin/param/shouqianba/request/GoblinSqbGoodsSyncParam.java
0 → 100644
View file @
fc3794cd
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
;
}
liquidnet-bus-api/liquidnet-service-goblin-api/src/main/java/com/liquidnet/service/goblin/service/IGoblinSqbGoodsService.java
View file @
fc3794cd
...
...
@@ -2,9 +2,9 @@ package com.liquidnet.service.goblin.service;
import
com.liquidnet.service.base.ResponseDto
;
import
com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo
;
import
com.liquidnet.service.goblin.param.shouqianba.request.GoblinSqbGoodsSyncParam
;
import
java.util.List
;
import
java.util.Map
;
/**
* 收钱吧商品同步服务接口
...
...
@@ -20,13 +20,22 @@ public interface IGoblinSqbGoodsService {
ResponseDto
<
List
<
GoblinSqbPerfGoodsVo
>>
getAllMallProducts
();
/**
* 批量同步商品到 goblin 系统
* 已存在则更新,不存在则新增(spuType=33)
* 批量新增商品到 goblin 系统(不存在则新增)
*
* @param items 待同步商品列表,每项包含 mallSn、sqbProductId、sqbProductSn
* @return 同步结果
* @param storeId 门店ID
* @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 并写入缓存)
...
...
liquidnet-bus-do/liquidnet-service-goblin-do/src/main/java/com/liquidnet/service/goblin/entity/GoblinSqbGoodsExt.java
View file @
fc3794cd
...
...
@@ -7,6 +7,7 @@ import lombok.Data;
import
lombok.EqualsAndHashCode
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
/**
* <p>
...
...
@@ -56,8 +57,8 @@ public class GoblinSqbGoodsExt implements Serializable {
*/
private
String
sqbSkuId
;
private
String
createdAt
;
private
LocalDateTime
createdAt
;
private
String
updatedAt
;
private
LocalDateTime
updatedAt
;
}
liquidnet-bus-service/liquidnet-service-goblin/liquidnet-service-goblin-impl/src/main/java/com/liquidnet/service/goblin/controller/GoblinSqbGoodsController.java
View file @
fc3794cd
package
com
.
liquidnet
.
service
.
goblin
.
controller
;
import
com.liquidnet.commons.lang.util.CurrentUtil
;
import
com.liquidnet.service.base.ResponseDto
;
import
com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo
;
import
com.liquidnet.service.goblin.service.IGoblinSqbGoodsService
;
import
com.liquidnet.service.goblin.util.GoblinRedisUtils
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
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
java.util.List
;
import
java.util.Map
;
/**
* 收钱吧商品同步 Controller
...
...
@@ -23,6 +26,9 @@ public class GoblinSqbGoodsController {
@Autowired
IGoblinSqbGoodsService
goblinSqbGoodsService
;
@Autowired
GoblinRedisUtils
goblinRedisUtils
;
/**
* 查询所有商城及商品列表
...
...
@@ -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"
)
@ApiOperation
(
"批量同步收钱吧商品"
)
public
ResponseDto
<
String
>
sync
(
@RequestBody
List
<
Map
<
String
,
String
>>
items
)
{
return
goblinSqbGoodsService
.
syncGoods
(
items
);
@PostMapping
(
"/update"
)
@ApiOperation
(
"批量更新收钱吧商品"
)
public
ResponseDto
<
String
>
updateGoods
(
@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
.
updateGoods
(
storeId
,
items
);
}
/**
...
...
liquidnet-bus-service/liquidnet-service-goblin/liquidnet-service-goblin-impl/src/main/java/com/liquidnet/service/goblin/service/impl/GoblinSqbGoodsServiceImpl.java
View file @
fc3794cd
package
com
.
liquidnet
.
service
.
goblin
.
service
.
impl
;
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.SqlMapping
;
import
com.liquidnet.service.base.constant.MQConst
;
import
com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo
;
import
com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo
;
import
com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo
;
...
...
@@ -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.response.data.MallListQueryData
;
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.IGoblinSqbGoodsService
;
import
com.liquidnet.service.goblin.util.GoblinMongoUtils
;
import
com.liquidnet.service.goblin.util.GoblinRedisUtils
;
import
com.liquidnet.service.goblin.util.GoblinSqbRedisUtils
;
import
com.liquidnet.service.goblin.util.QueueUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.CollectionUtils
;
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.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
...
...
@@ -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_USER_ID
=
"todo_merchant_user_id"
;
private
static
final
String
SQB_ROLE
=
"super_admin"
;
private
static
final
String
SQB_STORE_ID
=
"0"
;
// 平台级商品 store_id=0
@Autowired
private
Goblin
SqbGoodsExtMapper
goblinSqbGoodsExt
Mapper
;
private
Goblin
GoodsMapper
goblinGoods
Mapper
;
@Autowired
private
IGoblinShouQianBaService
goblinShouQianBaService
;
private
GoblinGoodsSkuMapper
goblinGoodsSkuMapper
;
@Autowired
private
GoblinSqb
PerformanceGoodsMapper
goblinSqbPerformanceGoods
Mapper
;
private
GoblinSqb
GoodsExtMapper
goblinSqbGoodsExt
Mapper
;
@Autowired
private
Goblin
GoodsMapper
goblin
GoodsMapper
;
private
Goblin
SqbPerformanceGoodsMapper
goblinSqbPerformance
GoodsMapper
;
@Autowired
private
GoblinGoodsSkuMapper
goblinGoodsSkuMapper
;
private
IGoblinShouQianBaService
goblinShouQianBaService
;
@Autowired
private
GoblinSqbRedisUtils
goblinSqbRedisUtils
;
...
...
@@ -78,357 +76,365 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {
private
GoblinRedisUtils
goblinRedisUtils
;
@Autowired
private
GoblinMongoUtils
goblinMongoUtils
;
@Autowired
private
QueueUtils
queueUtils
;
// ================================ 获取所有商城商品 ================================
private
IGoblinstoreMgtGoodsService
goblinstoreMgtGoodsService
;
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
public
ResponseDto
<
List
<
GoblinSqbPerfGoodsVo
>>
getAllMallProducts
()
{
List
<
GoblinSqbPerfGoodsVo
>
result
=
new
ArrayList
<>();
try
{
// 1. 调用收钱吧获取商城列表
MallListQueryRequest
mallListRequest
=
new
MallListQueryRequest
();
mallListRequest
.
setAppid
(
SQB_APPID
);
// 过滤条件:只查已上线的商城
MallListQueryRequest
mallRequest
=
new
MallListQueryRequest
();
mallRequest
.
setAppid
(
SQB_APPID
);
MallListQueryRequest
.
Filter
filter
=
new
MallListQueryRequest
.
Filter
();
CommonRequest
.
Seller
seller
=
buildSeller
();
filter
.
setSeller
(
seller
);
filter
.
setState
((
byte
)
1
);
// 1=已上线
mallListRequest
.
setFilter
(
filter
);
// 分页:每次取 100 个
MallListQueryRequest
.
Cursor
cursor
=
new
MallListQueryRequest
.
Cursor
();
cursor
.
setCount
(
100
);
mallListRequest
.
setCursor
(
cursor
);
List
<
MallListQueryData
>
mallList
=
goblinShouQianBaService
.
queryMallList
(
mallListRequest
);
filter
.
setSeller
(
buildSeller
());
mallRequest
.
setFilter
(
filter
);
List
<
MallListQueryData
>
mallList
=
goblinShouQianBaService
.
queryMallList
(
mallRequest
);
if
(
CollectionUtils
.
isEmpty
(
mallList
))
{
log
.
warn
(
"[收钱吧] 未查询到任何商城信息"
);
return
ResponseDto
.
success
(
result
);
return
ResponseDto
.
success
(
new
ArrayList
<>());
}
// 2. 循环每个商城获取商品列表
List
<
GoblinSqbPerfGoodsVo
>
result
=
new
ArrayList
<>();
for
(
MallListQueryData
mall
:
mallList
)
{
String
mallSn
=
mall
.
getMallSn
();
if
(
StringUtils
.
isEmpty
(
mallSn
))
continue
;
try
{
MallProductsQueryRequest
productsRequest
=
new
MallProductsQueryRequest
();
productsRequest
.
setAppid
(
SQB_APPID
);
productsRequest
.
setSeller
(
seller
);
CommonRequest
.
Mall
mallId
=
new
CommonRequest
.
Mall
();
mallId
.
setMallSn
(
mallSn
);
mallId
.
setSignature
(
mall
.
getSignature
());
productsRequest
.
setMallID
(
mallId
);
List
<
MallProductsQueryData
>
productsDataList
=
goblinShouQianBaService
.
queryMallProducts
(
productsRequest
);
if
(
CollectionUtils
.
isEmpty
(
productsDataList
))
{
log
.
warn
(
"[收钱吧商品同步] 商城 {} 获取商品列表为空"
,
mallSn
);
continue
;
}
// 3. 将商品数据转换为 VO
for
(
MallProductsQueryData
productsData
:
productsDataList
)
{
if
(
productsData
==
null
||
CollectionUtils
.
isEmpty
(
productsData
.
getSkuModels
()))
continue
;
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
);
MallProductsQueryRequest
productRequest
=
new
MallProductsQueryRequest
();
productRequest
.
setAppid
(
SQB_APPID
);
productRequest
.
setSeller
(
buildSeller
());
CommonRequest
.
Mall
mallId
=
new
CommonRequest
.
Mall
();
mallId
.
setMallSn
(
mall
.
getMallSn
());
mallId
.
setSignature
(
mall
.
getSignature
());
productRequest
.
setMallID
(
mallId
);
List
<
MallProductsQueryData
>
products
=
goblinShouQianBaService
.
queryMallProducts
(
productRequest
);
if
(!
CollectionUtils
.
isEmpty
(
products
))
{
for
(
MallProductsQueryData
product
:
products
)
{
List
<
MallProductsQueryData
.
Sku
>
skus
=
product
.
getSkuModels
();
if
(
CollectionUtils
.
isEmpty
(
skus
))
{
result
.
add
(
buildPerfGoodsVo
(
product
,
null
));
}
else
{
for
(
MallProductsQueryData
.
Sku
sku
:
skus
)
{
result
.
add
(
buildPerfGoodsVo
(
product
,
sku
));
}
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[收钱吧商品同步] 获取商城 {} 商品列表异常"
,
mallSn
,
e
);
}
}
return
ResponseDto
.
success
(
result
);
}
catch
(
Exception
e
)
{
log
.
error
(
"[收钱吧
商品同步
] getAllMallProducts 异常"
,
e
);
return
ResponseDto
.
failure
(
"
获取商城商品列表失败:"
+
e
.
getMessage
()
);
log
.
error
(
"[收钱吧] getAllMallProducts 异常"
,
e
);
return
ResponseDto
.
failure
(
"
查询收钱吧商品列表失败"
);
}
}
log
.
info
(
"[收钱吧商品同步] getAllMallProducts 完成,共 {} 个 SKU"
,
result
.
size
());
return
ResponseDto
.
success
(
result
);
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 系统 ================================
/**
* 批量同步商品到 goblin 系统
* <p>
* 流程:对每个 sqbProductId,调用收钱吧查询商品详情,
* 写入 goblin_goods + goblin_goods_sku + goblin_sqb_goods_ext
* </p>
*
* @param items 待同步商品列表:每项包含 mallSn、sqbProductId、sqbProductSn(来自收钱吧)
* @return 同步结果摘要
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ResponseDto
<
String
>
syncGoods
(
List
<
Map
<
String
,
String
>>
items
)
{
if
(
CollectionUtils
.
isEmpty
(
items
))
{
return
ResponseDto
.
failure
(
"同步商品列表不能为空"
);
}
int
newCount
=
0
;
int
existCount
=
0
;
int
failCount
=
0
;
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"
);
// 商城签名,用于查商品
public
ResponseDto
<
String
>
addGoods
(
String
storeId
,
List
<
GoblinSqbGoodsSyncParam
>
items
)
{
if
(
CollectionUtils
.
isEmpty
(
items
))
return
ResponseDto
.
failure
(
"新增商品列表不能为空"
);
int
newCount
=
0
,
existCount
=
0
,
failCount
=
0
;
String
currentUid
=
"system"
;
for
(
GoblinSqbGoodsSyncParam
item
:
items
)
{
String
sqbProductId
=
item
.
getSqbProductId
(),
sqbProductSn
=
item
.
getSqbProductSn
(),
mallSn
=
item
.
getMallSn
(),
mallSignature
=
item
.
getMallSignature
();
if
(
StringUtils
.
isEmpty
(
sqbProductId
))
{
log
.
warn
(
"[收钱吧商品同步] sqbProductId 为空,跳过: {}"
,
item
);
failCount
++;
continue
;
}
try
{
// Step 1: 幂等检查 —— 已存在则跳过
LambdaQueryWrapper
<
GoblinSqbGoodsExt
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
queryWrapper
.
eq
(
GoblinSqbGoodsExt:
:
getSqbProductId
,
sqbProductId
);
GoblinSqbGoodsExt
existing
=
goblinSqbGoodsExtMapper
.
selectOne
(
queryWrapper
);
if
(
existing
!=
null
)
{
log
.
info
(
"[收钱吧商品同步] 商品已存在,sqbProductId={}, spuId={}, skuId={}"
,
sqbProductId
,
existing
.
getSpuId
(),
existing
.
getSkuId
());
if
(
goblinSqbGoodsExtMapper
.
selectCount
(
queryWrapper
)
>
0
)
{
existCount
++;
continue
;
}
// Step 2: 查询收钱吧商品详情(通过 queryMallProducts)
MallProductsQueryData
productsData
=
null
;
if
(!
StringUtils
.
isEmpty
(
mallSn
))
{
MallProductsQueryRequest
productsRequest
=
new
MallProductsQueryRequest
();
productsRequest
.
setAppid
(
SQB_APPID
);
productsRequest
.
setSeller
(
buildSeller
());
CommonRequest
.
Mall
mallId
=
new
CommonRequest
.
Mall
();
mallId
.
setMallSn
(
mallSn
);
mallId
.
setSignature
(
mallSignature
);
productsRequest
.
setMallID
(
mallId
);
List
<
MallProductsQueryData
>
productsDataList
=
goblinShouQianBaService
.
queryMallProducts
(
productsRequest
);
if
(!
CollectionUtils
.
isEmpty
(
productsDataList
))
{
for
(
MallProductsQueryData
data
:
productsDataList
)
{
if
(
sqbProductId
.
equals
(
data
.
getSpuId
()))
{
productsData
=
data
;
break
;
}
}
}
MallProductsQueryData
productsData
=
querySqbProduct
(
mallSn
,
mallSignature
,
sqbProductId
);
if
(
null
==
productsData
)
{
failCount
++;
continue
;
}
// Step 3: 生成本地 spuId
String
spuId
=
IDGenerator
.
nextSnowId
();
// Step 4: 构建 GoblinGoodsInfoVo
GoblinGoodsInfoVo
goodsInfoVo
=
buildGoblinGoodsInfoVo
(
spuId
,
productsData
,
now
);
log
.
info
(
"[收钱吧商品同步] 准备写入商品,spuId={}"
,
spuId
);
// 1. 组装 AddParam
GoblinStoreMgtGoodsAddParam
addParam
=
buildMgtGoodsAddParam
(
storeId
,
productsData
);
// 2. 初始化 VOs
LocalDateTime
now
=
LocalDateTime
.
now
();
GoblinGoodsInfoVo
goodsInfoVo
=
addParam
.
initGoodsInfoVo
();
goodsInfoVo
.
setCreatedBy
(
currentUid
);
goodsInfoVo
.
setCreatedAt
(
now
);
goodsInfoVo
.
setSpuType
(
33
);
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
);
}
// Step 5: 遍历 SKU,构建 GoblinGoodsSkuInfoVo 及写 EXT 表
List
<
MallProductsQueryData
.
Sku
>
sqbSkus
=
productsData
!=
null
&&
!
CollectionUtils
.
isEmpty
(
productsData
.
getSkuModels
())
?
productsData
.
getSkuModels
()
:
Collections
.
emptyList
();
List
<
GoblinGoodsSkuInfoVo
>
skuInfoVos
=
new
ArrayList
<>();
List
<
String
>
skuIdList
=
new
ArrayList
<>();
// 3. 调用管理端 Service 加商
goblinstoreMgtGoodsService
.
goodsAdd
(
goodsInfoVo
,
goodsSkuInfoVoList
);
// 4. 建立映射
List
<
MallProductsQueryData
.
Sku
>
sqbSkus
=
productsData
.
getSkuModels
();
if
(
CollectionUtils
.
isEmpty
(
sqbSkus
))
{
// 没有 SKU 数据时,创建一个占位 SKU
String
skuId
=
IDGenerator
.
nextSnowId
();
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
);
String
skuId
=
goodsSkuInfoVoList
.
get
(
0
).
getSkuId
();
goblinSqbGoodsExtMapper
.
insert
(
buildExt
(
goodsInfoVo
.
getSpuId
(),
skuId
,
mallSn
,
sqbProductId
,
sqbProductSn
,
null
,
now
));
}
else
{
for
(
MallProductsQueryData
.
Sku
sqbSku
:
sqbSkus
)
{
String
skuId
=
IDGenerator
.
nextSnowId
();
GoblinGoodsSkuInfoVo
skuVo
=
buildGoblinGoodsSkuInfoVo
(
skuId
,
spuId
,
sqbSku
,
productsData
,
now
);
skuInfoVos
.
add
(
skuVo
);
skuIdList
.
add
(
skuId
);
GoblinSqbGoodsExt
ext
=
buildExt
(
spuId
,
skuId
,
mallSn
,
sqbProductId
,
sqbProductSn
,
sqbSku
.
getSkuId
(),
now
);
goblinSqbGoodsExtMapper
.
insert
(
ext
);
log
.
info
(
"[收钱吧商品同步] 写入 SKU,skuId={}, sqbSkuId={}"
,
skuId
,
sqbSku
.
getSkuId
());
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
));
}
}
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
)));
}
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"
;
// Step 7: 写 MongoDB
goblinMongoUtils
.
setGoodsInfoVo
(
goodsInfoVo
);
goblinMongoUtils
.
setGoodsSkuInfoVos
(
skuInfoVos
);
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
;
}
// 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
()
});
String
spuId
=
existingExts
.
get
(
0
).
getSpuId
();
GoblinGoodsInfoVo
mgtGoodsInfoVo
=
goblinRedisUtils
.
getGoodsInfoVo
(
spuId
);
if
(
null
==
mgtGoodsInfoVo
)
{
notFoundCount
++;
continue
;
}
toMqSqls
.
add
(
SqlMapping
.
get
(
"goblin_goods_image.insert_byreplace"
));
if
(!
CollectionUtils
.
isEmpty
(
goodsInfoVo
.
getImageList
()))
{
goodsInfoVo
.
getImageList
().
forEach
(
imageUrl
->
initGoodsImageObjs
.
add
(
new
Object
[]{
spuId
,
imageUrl
}));
MallProductsQueryData
productsData
=
querySqbProduct
(
mallSn
,
mallSignature
,
sqbProductId
);
if
(
null
==
productsData
)
{
failCount
++;
continue
;
}
queueUtils
.
sendMsgByRedis
(
MQConst
.
GoblinQueue
.
SQL_GOODS
.
getKey
(),
SqlMapping
.
gets
(
toMqSqls
,
initGoodsObjs
,
initGoodsSkuObjs
,
initGoodsImageObjs
)
);
log
.
info
(
"[收钱吧商品同步] Redis及MongoDB写入、MQ消息发送成功,sqbProductId={}"
,
sqbProductId
);
// 2. 编辑 SPU
GoblinStoreMgtGoodsAddParam
addParam
=
buildMgtGoodsAddParam
(
storeId
,
productsData
);
addParam
.
setSpuId
(
spuId
);
goblinstoreMgtGoodsService
.
goodsEditSpu
(
currentUid
,
addParam
,
mgtGoodsInfoVo
);
newCount
++;
// 3. 编辑 SKU
Map
<
String
,
String
>
sqbToSysSkuMap
=
new
HashMap
<>();
for
(
GoblinSqbGoodsExt
ext
:
existingExts
)
{
sqbToSysSkuMap
.
put
(
ext
.
getSqbSkuId
()
!=
null
?
ext
.
getSqbSkuId
()
:
"PLACEHOLDER"
,
ext
.
getSkuId
());
}
List
<
MallProductsQueryData
.
Sku
>
sqbSkus
=
productsData
.
getSkuModels
();
if
(
CollectionUtils
.
isEmpty
(
sqbSkus
))
{
String
skuId
=
sqbToSysSkuMap
.
get
(
"PLACEHOLDER"
);
if
(
skuId
!=
null
)
processSkuUpdate
(
currentUid
,
storeId
,
skuId
,
productsData
,
null
);
}
else
{
for
(
MallProductsQueryData
.
Sku
sqbSku
:
sqbSkus
)
{
String
skuId
=
sqbToSysSkuMap
.
get
(
sqbSku
.
getSkuId
());
if
(
skuId
!=
null
)
processSkuUpdate
(
currentUid
,
storeId
,
skuId
,
productsData
,
sqbSku
);
}
}
updateCount
++;
}
catch
(
Exception
e
)
{
log
.
error
(
"[收钱吧
商品同步] 处理商品异常,
sqbProductId={}"
,
sqbProductId
,
e
);
log
.
error
(
"[收钱吧
更新商品同步] 异常,
sqbProductId={}"
,
sqbProductId
,
e
);
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
;
GoblinStoreMgtGoodsEditSkuParam
editSkuParam
=
new
GoblinStoreMgtGoodsEditSkuParam
();
editSkuParam
.
setStoreId
(
storeId
);
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
);
}
String
summary
=
String
.
format
(
"同步完成:新增 %d 条,已存在 %d 条,失败 %d 条"
,
newCount
,
existCount
,
failCount
);
log
.
info
(
"[收钱吧商品同步] {}"
,
summary
);
return
ResponseDto
.
success
(
summary
);
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
public
ResponseDto
<
List
<
GoblinSqbPerfGoodsVo
>>
getPerfGoods
(
String
performancesId
)
{
// 1. 先查 Redis 缓存
List
<
GoblinSqbPerfGoodsVo
>
cached
=
goblinSqbRedisUtils
.
getPerfGoods
(
performancesId
);
if
(
cached
!=
null
)
{
return
ResponseDto
.
success
(
cached
);
}
// 2. 缓存未命中,查 MySQL
if
(
cached
!=
null
)
return
ResponseDto
.
success
(
cached
);
try
{
LambdaQueryWrapper
<
GoblinSqbPerformanceGoods
>
query
=
new
LambdaQueryWrapper
<>();
query
.
eq
(
GoblinSqbPerformanceGoods:
:
getPerformancesId
,
performancesId
)
.
eq
(
GoblinSqbPerformanceGoods:
:
getStatus
,
1
)
.
orderByAsc
(
GoblinSqbPerformanceGoods:
:
getSort
);
query
.
eq
(
GoblinSqbPerformanceGoods:
:
getPerformancesId
,
performancesId
).
eq
(
GoblinSqbPerformanceGoods:
:
getStatus
,
1
).
orderByAsc
(
GoblinSqbPerformanceGoods:
:
getSort
);
List
<
GoblinSqbPerformanceGoods
>
relations
=
goblinSqbPerformanceGoodsMapper
.
selectList
(
query
);
if
(
CollectionUtils
.
isEmpty
(
relations
))
{
List
<
GoblinSqbPerfGoodsVo
>
empty
=
new
ArrayList
<>();
goblinSqbRedisUtils
.
setPerfGoods
(
performancesId
,
empty
);
return
ResponseDto
.
success
(
empty
);
}
// 收集 skuId 和 spuId
List
<
String
>
skuIds
=
relations
.
stream
()
.
map
(
GoblinSqbPerformanceGoods:
:
getSkuId
)
.
collect
(
Collectors
.
toList
());
List
<
String
>
spuIds
=
relations
.
stream
()
.
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
<
String
>
skuIds
=
relations
.
stream
().
map
(
GoblinSqbPerformanceGoods:
:
getSkuId
).
collect
(
Collectors
.
toList
());
List
<
String
>
spuIds
=
relations
.
stream
().
map
(
GoblinSqbPerformanceGoods:
:
getSpuId
).
distinct
().
collect
(
Collectors
.
toList
());
List
<
GoblinGoodsSku
>
skuList
=
goblinGoodsSkuMapper
.
selectList
(
new
LambdaQueryWrapper
<
GoblinGoodsSku
>().
in
(
GoblinGoodsSku:
:
getSkuId
,
skuIds
));
Map
<
String
,
GoblinGoodsSku
>
skuMap
=
skuList
.
stream
().
collect
(
Collectors
.
toMap
(
GoblinGoodsSku:
:
getSkuId
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
List
<
GoblinGoods
>
spuList
=
goblinGoodsMapper
.
selectList
(
new
LambdaQueryWrapper
<
GoblinGoods
>().
in
(
GoblinGoods:
:
getSpuId
,
spuIds
));
Map
<
String
,
GoblinGoods
>
spuMap
=
spuList
.
stream
().
collect
(
Collectors
.
toMap
(
GoblinGoods:
:
getSpuId
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
List
<
GoblinSqbPerfGoodsVo
>
result
=
new
ArrayList
<>();
for
(
GoblinSqbPerformanceGoods
rel
:
relations
)
{
GoblinSqbPerfGoodsVo
vo
=
new
GoblinSqbPerfGoodsVo
();
vo
.
setSkuId
(
rel
.
getSkuId
());
vo
.
setSpuId
(
rel
.
getSpuId
());
vo
.
setSort
(
rel
.
getSort
());
vo
.
setSkuId
(
rel
.
getSkuId
());
vo
.
setSpuId
(
rel
.
getSpuId
());
vo
.
setSort
(
rel
.
getSort
());
GoblinGoodsSku
sku
=
skuMap
.
get
(
rel
.
getSkuId
());
if
(
sku
!=
null
)
{
vo
.
setSkuName
(
sku
.
getName
());
vo
.
setPrice
(
sku
.
getPrice
()
!=
null
?
sku
.
getPrice
().
longValue
()
:
null
);
}
if
(
sku
!=
null
)
{
vo
.
setSkuName
(
sku
.
getName
());
vo
.
setPrice
(
sku
.
getPrice
()
!=
null
?
sku
.
getPrice
().
longValue
()
:
null
);
}
GoblinGoods
spu
=
spuMap
.
get
(
rel
.
getSpuId
());
if
(
spu
!=
null
)
{
vo
.
setSpuName
(
spu
.
getName
());
vo
.
setCoverPic
(
spu
.
getCoverPic
());
}
if
(
spu
!=
null
)
{
vo
.
setSpuName
(
spu
.
getName
());
vo
.
setCoverPic
(
spu
.
getCoverPic
());
}
result
.
add
(
vo
);
}
// 3. 写入 Redis 缓存(TTL 5min)
goblinSqbRedisUtils
.
setPerfGoods
(
performancesId
,
result
);
return
ResponseDto
.
success
(
result
);
}
catch
(
Exception
e
)
{
log
.
error
(
"[收钱吧] getPerfGoods 异常
,performancesId={}"
,
performancesId
,
e
);
return
ResponseDto
.
failure
(
"查询
演出关联商品失败:"
+
e
.
getMessage
()
);
log
.
error
(
"[收钱吧] getPerfGoods 异常
"
,
e
);
return
ResponseDto
.
failure
(
"查询
失败"
);
}
}
// ================================ 私有辅助方法 ================================
private
CommonRequest
.
Seller
buildSeller
()
{
CommonRequest
.
Seller
seller
=
new
CommonRequest
.
Seller
();
seller
.
setMerchantId
(
SQB_MERCHANT_ID
);
...
...
@@ -437,110 +443,11 @@ public class GoblinSqbGoodsServiceImpl implements IGoblinSqbGoodsService {
return
seller
;
}
/**
* 构建 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
)
{
private
GoblinSqbGoodsExt
buildExt
(
String
spuId
,
String
skuId
,
String
mallSn
,
String
sqbProductId
,
String
sqbProductSn
,
String
sqbSkuId
,
LocalDateTime
now
)
{
GoblinSqbGoodsExt
ext
=
new
GoblinSqbGoodsExt
();
ext
.
setSpuId
(
spuId
);
ext
.
setSkuId
(
skuId
);
ext
.
setMallSn
(
mallSn
);
ext
.
setSqbProductId
(
sqbProductId
);
ext
.
setSqbProductSn
(
sqbProductSn
);
ext
.
setSqbSkuId
(
sqbSkuId
);
ext
.
setCreatedAt
(
now
);
ext
.
setUpdatedAt
(
now
);
ext
.
setSpuId
(
spuId
);
ext
.
setSkuId
(
skuId
);
ext
.
setMallSn
(
mallSn
);
ext
.
setSqbProductId
(
sqbProductId
);
ext
.
setSqbProductSn
(
sqbProductSn
);
ext
.
setSqbSkuId
(
sqbSkuId
);
ext
.
setCreatedAt
(
now
);
ext
.
setUpdatedAt
(
now
);
return
ext
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment