Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jiedao-api-boot-master
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
lanbaoming
jiedao-api-boot-master
Commits
ab8f42f6
Commit
ab8f42f6
authored
Jul 26, 2024
by
zhangfeng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feature-reward:批量兑换
parent
f6a68ca2
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
103 additions
and
72 deletions
+103
-72
I18nMessage.java
...ava/cn/iocoder/yudao/framework/i18n/core/I18nMessage.java
+0
-2
OrderTimeServiceImpl.java
...module/order/service/order/impl/OrderTimeServiceImpl.java
+0
-1
ErrorCodeConstants.java
...iocoder/yudao/module/reward/enums/ErrorCodeConstants.java
+2
-0
RedeemRewardApiImpl.java
...r/yudao/module/reward/api/reward/RedeemRewardApiImpl.java
+86
-64
RewardDO.java
...r/yudao/module/reward/dal/dataobject/reward/RewardDO.java
+2
-0
RewardServiceImpl.java
...yudao/module/reward/service/reward/RewardServiceImpl.java
+12
-5
RewardUpdateReqVO.java
...oder/yudao/module/reward/vo/reward/RewardUpdateReqVO.java
+1
-0
No files found.
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/i18n/core/I18nMessage.java
View file @
ab8f42f6
...
...
@@ -6,8 +6,6 @@ import lombok.extern.slf4j.Slf4j;
import
org.springframework.context.i18n.LocaleContextHolder
;
import
org.springframework.context.support.MessageSourceAccessor
;
import
org.springframework.context.support.ReloadableResourceBundleMessageSource
;
import
sun.util.locale.BaseLocale
;
import
sun.util.locale.LocaleUtils
;
import
java.io.IOException
;
import
java.util.Locale
;
...
...
yudao-module-order/yudao-module-order-core/src/main/java/cn/iocoder/yudao/module/order/service/order/impl/OrderTimeServiceImpl.java
View file @
ab8f42f6
...
...
@@ -20,7 +20,6 @@ import com.alibaba.fastjson.JSONObject;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
com.sun.org.apache.xpath.internal.operations.Or
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
...
...
yudao-module-reward/yudao-module-reward-api/src/main/java/cn/iocoder/yudao/module/reward/enums/ErrorCodeConstants.java
View file @
ab8f42f6
...
...
@@ -21,5 +21,7 @@ public interface ErrorCodeConstants {
ErrorCode
REWARD_SCORE_NOT_ENOUGH
=
new
ErrorCode
(
1001011013
,
"会员积分不够"
);
ErrorCode
REWARD_COUNT_NOT_ENOUGH
=
new
ErrorCode
(
1001011014
,
"礼品数量不够"
);
ErrorCode
REWARD_REDEEM_FAIL
=
new
ErrorCode
(
1001011015
,
"批量兑换失败"
);
ErrorCode
REWARD_REDEEM_COUNT_NOT_ALLOW
=
new
ErrorCode
(
1001011016
,
"批量兑换每次最多十条"
);
ErrorCode
REWARD_REDEEM_ALLOW_COUNT_ERROR
=
new
ErrorCode
(
1001011017
,
"超出允许兑换次数"
);
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/api/reward/RedeemRewardApiImpl.java
View file @
ab8f42f6
...
...
@@ -15,7 +15,9 @@ import cn.iocoder.yudao.module.reward.dal.dataobject.reward.RewardDO;
import
cn.iocoder.yudao.module.reward.dal.mysql.redeem.RewardRedeemMapper
;
import
cn.iocoder.yudao.module.reward.dal.mysql.reward.RewardMapper
;
import
cn.iocoder.yudao.module.reward.enums.RewardRedeemStatusEnum
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.validation.annotation.Validated
;
import
javax.annotation.Resource
;
...
...
@@ -42,22 +44,10 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
private
MemberUserScoreApi
memberUserScoreApi
;
@Resource
private
SnowflakeGenerator
snowflakeGenerator
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
RedeemRewardRespDTO
redeemReward
(
RedeemRewardReqVO
redeemRewardReqVO
)
{
boolean
lock
=
false
;
try
{
lock
=
redisDistributedLock
.
lock
(
"reward:redeem:lock:"
+
redeemRewardReqVO
.
getRewardId
());
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
// 查询会员积分
UserRespDTO
memberUser
=
memberUserApi
.
getUser
(
redeemRewardReqVO
.
getRewardId
());
if
(
memberUser
==
null
)
{
throw
exception
(
USER_NOT_EXISTS
);
}
Integer
holdScore
=
memberUser
.
getHoldScore
();
// 查询礼品
RewardDO
rewardDO
=
rewardMapper
.
selectById
(
redeemRewardReqVO
.
getRewardId
());
if
(
rewardDO
==
null
)
{
...
...
@@ -67,10 +57,6 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
if
(
rewardDO
.
getStatus
()
!=
1
)
{
throw
exception
(
REWARD_NOT_ENABLE
);
}
// 会员积分不够
if
(
holdScore
<
rewardDO
.
getPointsRequire
()
*
redeemRewardReqVO
.
getRewardCount
())
{
throw
exception
(
REWARD_SCORE_NOT_ENOUGH
);
}
// 礼品数量不够
if
(
rewardDO
.
getQuantityRemain
()
<
redeemRewardReqVO
.
getRewardCount
())
{
throw
exception
(
REWARD_COUNT_NOT_ENOUGH
);
...
...
@@ -79,16 +65,19 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
if
(!
Objects
.
equals
(
rewardDO
.
getPickMethod
(),
redeemRewardReqVO
.
getRedeemType
()))
{
throw
exception
(
REWARD_PICK_METHOD_NOT_ALLOW_CREATE
);
}
//TODO:校验兑换次数(查兑换记录)
verifyMemberUser
(
redeemRewardReqVO
,
rewardDO
);
boolean
lock
=
false
;
try
{
lock
=
redisDistributedLock
.
lock
(
"reward:redeem:lock:"
+
redeemRewardReqVO
.
getRewardId
());
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
// 更新礼品
rewardMapper
.
updateById
(
rewardDO
);
redeemReward
(
rewardDO
,
redeemRewardReqVO
.
getRewardCount
());
// 添加兑换记录
Long
redeemId
=
addRedeemRecord
(
redeemRewardReqVO
);
// 更新会员积分
updateMemberScore
(
redeemRewardReqVO
,
rewardDO
,
redeemId
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
...
...
@@ -97,13 +86,24 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
return
null
;
}
private
void
redeemReward
(
RewardDO
rewardDO
,
Integer
rewardCount
)
{
// 更新时校验礼品数量是否足够
RewardDO
rewardDO1
=
rewardMapper
.
selectById
(
rewardDO
.
getId
());
if
(
rewardDO1
.
getQuantityRemain
()
<
rewardCount
)
{
throw
exception
(
REWARD_COUNT_NOT_ENOUGH
);
}
rewardDO
.
setExchangeCount
(
rewardDO
.
getExchangeCount
()
+
1
);
rewardDO
.
setQuantityRemain
(
rewardDO
.
getQuantityRemain
()
-
rewardCount
);
rewardMapper
.
updateById
(
rewardDO
);
}
private
void
updateMemberScore
(
RedeemRewardReqVO
redeemRewardReqVO
,
RewardDO
rewardDO
,
Long
redeemId
)
{
Map
<
String
,
Object
>
extParam
=
new
HashMap
<>();
extParam
.
put
(
"redeemId"
,
redeemId
);
memberUserScoreApi
.
operateScore
(
MemberUserScoreOperateReqDTO
.
builder
()
.
memberId
(
redeemRewardReqVO
.
getMemberId
())
.
sourceType
(
ScoreSourceTypeEnum
.
EXCHANGE_REWARD
)
.
scoreCount
(
redeemRewardReqVO
.
getRewardCount
()
*
rewardDO
.
getPointsRequire
())
.
scoreCount
(
redeemRewardReqVO
.
getRewardCount
()
*
rewardDO
.
getPointsRequire
())
.
extParam
(
extParam
)
.
build
());
}
...
...
@@ -117,7 +117,12 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
List
<
RedeemRewardRespDTO
>
redeemRewards
(
List
<
RedeemRewardReqVO
>
redeemRewardReqVOList
)
{
// 批量兑换每次最多十条
if
(
redeemRewardReqVOList
.
size
()
>
10
)
{
throw
exception
(
REWARD_REDEEM_COUNT_NOT_ALLOW
);
}
Long
rewardId
=
redeemRewardReqVOList
.
get
(
0
).
getRewardId
();
// 查询礼品
RewardDO
rewardDO
=
rewardMapper
.
selectById
(
rewardId
);
...
...
@@ -125,44 +130,61 @@ public class RedeemRewardApiImpl implements RedeemRewardApi {
if
(
rewardDO
.
getStatus
()
!=
1
)
{
throw
exception
(
REWARD_NOT_ENABLE
);
}
boolean
lock
=
false
;
try
{
lock
=
redisDistributedLock
.
lock
(
"reward:redeem:lock:"
+
rewardId
);
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
// 校验礼品数量
//
ArrayList
<
Long
>
memberIds
=
new
ArrayList
<>();
int
totalCount
=
0
;
ArrayList
<
UserRespDTO
>
members
=
new
ArrayList
<>();
for
(
RedeemRewardReqVO
redeemRewardReqVO
:
redeemRewardReqVOList
)
{
// 每个兑换VO校验一遍
// 兑换方式不匹配
if
(!
Objects
.
equals
(
rewardDO
.
getPickMethod
(),
redeemRewardReqVO
.
getRedeemType
()))
{
throw
exception
(
REWARD_PICK_METHOD_NOT_ALLOW_CREATE
);
}
// 查询会员id列表,暂时挨个查
memberIds
.
add
(
redeemRewardReqVO
.
getMemberId
());
members
.
add
(
memberUserApi
.
getUser
(
redeemRewardReqVO
.
getMemberId
()));
verifyMemberUser
(
redeemRewardReqVO
,
rewardDO
);
// 记录兑换总数
totalCount
+=
redeemRewardReqVO
.
getRewardCount
();
}
// 查询会员列表,获取积分列表
totalCount
+=
redeemRewardReqVO
.
getRewardCount
();
// 判断兑换总数是否大于礼物数量
if
(
totalCount
>
rewardDO
.
getQuantityRemain
()){
if
(
totalCount
>
rewardDO
.
getQuantityRemain
())
{
throw
exception
(
REWARD_COUNT_NOT_ENOUGH
);
}
// 判断会员积分是否够(初步校验,实际兑换时会再加锁校验)
}
boolean
lock
=
false
;
try
{
lock
=
redisDistributedLock
.
lock
(
"reward:redeem:lock:"
+
rewardId
);
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
for
(
RedeemRewardReqVO
redeemRewardReqVO
:
redeemRewardReqVOList
)
{
// 更新礼品
redeemReward
(
rewardDO
,
redeemRewardReqVO
.
getRewardCount
());
// 添加兑换记录
Long
redeemId
=
addRedeemRecord
(
redeemRewardReqVO
);
// 更新会员积分
updateMemberScore
(
redeemRewardReqVO
,
rewardDO
,
redeemId
);
}
}
catch
(
Exception
e
)
{
throw
exception
(
REWARD_REDEEM_FAIL
);
}
finally
{
}
finally
{
redisDistributedLock
.
releaseLock
(
"reward:redeem:lock:"
+
rewardId
);
}
return
null
;
}
private
void
verifyMemberUser
(
RedeemRewardReqVO
redeemRewardReqVO
,
RewardDO
rewardDO
)
{
// 查询会员积分
UserRespDTO
memberUser
=
memberUserApi
.
getUser
(
redeemRewardReqVO
.
getMemberId
());
if
(
memberUser
==
null
)
{
throw
exception
(
USER_NOT_EXISTS
);
}
Integer
holdScore
=
memberUser
.
getHoldScore
();
// 会员积分不够
if
(
holdScore
<
rewardDO
.
getPointsRequire
()
*
redeemRewardReqVO
.
getRewardCount
())
{
throw
exception
(
REWARD_SCORE_NOT_ENOUGH
);
}
// 校验兑换次数
LambdaQueryWrapper
<
RewardRedeemDO
>
rewardRedeemDOWrapper
=
new
LambdaQueryWrapper
<>();
rewardRedeemDOWrapper
.
eq
(
RewardRedeemDO:
:
getRewardId
,
redeemRewardReqVO
.
getRewardId
())
.
eq
(
RewardRedeemDO:
:
getMemberId
,
redeemRewardReqVO
.
getMemberId
());
Long
count
=
rewardRedeemMapper
.
selectCount
(
rewardRedeemDOWrapper
);
if
(
count
>
rewardDO
.
getAllowCount
())
{
throw
exception
(
REWARD_REDEEM_ALLOW_COUNT_ERROR
);
}
}
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/dal/dataobject/reward/RewardDO.java
View file @
ab8f42f6
...
...
@@ -80,6 +80,7 @@ public class RewardDO extends BaseDO {
private
Date
endTime
;
/**
* 领取方式(1上门领取,2包邮到家,3邮寄到付)
* TODO :改为枚举
*/
private
Integer
pickMethod
;
/**
...
...
@@ -100,6 +101,7 @@ public class RewardDO extends BaseDO {
private
String
remarkFr
;
/**
* 礼品状态(1已启用,2未启用,3已关闭,4已过期)
* TODO :改为枚举
*/
private
Integer
status
;
...
...
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/service/reward/RewardServiceImpl.java
View file @
ab8f42f6
...
...
@@ -56,6 +56,10 @@ public class RewardServiceImpl extends AbstractService<RewardMapper, RewardDO> i
// 插入
RewardDO
rewardDO
=
RewardConvert
.
INSTANCE
.
convert
(
createReqVO
);
rewardDO
.
setCode
(
generateRewardCode
());
// 剩余数量若没传给默认值0
if
(
rewardDO
.
getQuantityRemain
()
==
null
)
{
rewardDO
.
setQuantityRemain
(
0
);
}
//如果插入失败,重新生成code再次插入
try
{
rewardMapper
.
insert
(
rewardDO
);
...
...
@@ -68,6 +72,7 @@ public class RewardServiceImpl extends AbstractService<RewardMapper, RewardDO> i
}
@Override
// TODO :完善校验
public
void
update
(
RewardUpdateReqVO
updateReqVO
)
{
// 校验存在
RewardDO
rewardDO
=
rewardMapper
.
selectById
(
updateReqVO
.
getId
());
...
...
@@ -273,6 +278,7 @@ public class RewardServiceImpl extends AbstractService<RewardMapper, RewardDO> i
//校验礼品是否过期并修改礼品状态
//TODO:异步更新礼品状态
private
void
validateExpire
(
RewardDO
rewardDO
)
{
if
(
rewardDO
.
getEndTime
()
!=
null
){
if
(
rewardDO
.
getStatus
()
==
1
&&
rewardDO
.
getEndTime
().
toInstant
().
isBefore
(
Instant
.
now
()))
{
RewardDO
expireReward
=
new
RewardDO
();
expireReward
.
setId
(
rewardDO
.
getId
());
...
...
@@ -280,4 +286,5 @@ public class RewardServiceImpl extends AbstractService<RewardMapper, RewardDO> i
rewardMapper
.
updateById
(
expireReward
);
}
}
}
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/vo/reward/RewardUpdateReqVO.java
View file @
ab8f42f6
...
...
@@ -51,6 +51,7 @@ public class RewardUpdateReqVO {
private
Integer
nodeId
;
@ApiModelProperty
(
value
=
"剩余数量"
)
@NotNull
(
message
=
"剩余数量不能为空"
)
@Min
(
value
=
0
)
private
Integer
quantityRemain
;
...
...
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