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
1e09e12b
Commit
1e09e12b
authored
Jul 26, 2024
by
zhaobiyan
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
c32fef46
621eb138
Changes
33
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
620 additions
and
58 deletions
+620
-58
DateUtils.java
...n/iocoder/yudao/framework/common/util/date/DateUtils.java
+9
-7
I18nMessage.java
...ava/cn/iocoder/yudao/framework/i18n/core/I18nMessage.java
+0
-2
ErrorCodeConstants.java
.../iocoder/yudao/module/infra/enums/ErrorCodeConstants.java
+1
-0
MemberUserScoreApi.java
...der/yudao/module/member/api/score/MemberUserScoreApi.java
+6
-0
MemberUserScoreBatchOperateReqDTO.java
...mber/api/score/dto/MemberUserScoreBatchOperateReqDTO.java
+44
-0
UserRespDTO.java
...iocoder/yudao/module/member/api/user/dto/UserRespDTO.java
+2
-0
MemberUserScoreApiImpl.java
...yudao/module/member/api/score/MemberUserScoreApiImpl.java
+41
-8
MemberCodeFlushTask.java
...dule/member/controller/admin/job/MemberCodeFlushTask.java
+1
-1
MemberUserScoreExpireTask.java
...ember/controller/admin/job/MemberUserScoreExpireTask.java
+75
-0
MemberUserScoreController.java
...ller/admin/memberUserScore/MemberUserScoreController.java
+11
-13
MemberUserScoreDetailDO.java
...object/memberUserScoreDetail/MemberUserScoreDetailDO.java
+11
-2
MemberUserDO.java
...yudao/module/member/dal/dataobject/user/MemberUserDO.java
+1
-0
MemberUserMapper.java
.../yudao/module/member/dal/mysql/user/MemberUserMapper.java
+3
-1
MemberUserScoreDetailServiceImpl.java
...mberUserScoreDetail/MemberUserScoreDetailServiceImpl.java
+2
-2
MemberUserServiceImpl.java
...dao/module/member/service/user/MemberUserServiceImpl.java
+12
-1
MemberUserScoreBackVO.java
...dule/member/vo/memberUserScore/MemberUserScoreBackVO.java
+2
-0
MemberUserScoreMapper.xml
.../src/main/resources/mapper/user/MemberUserScoreMapper.xml
+3
-2
OrderTimeServiceImpl.java
...module/order/service/order/impl/OrderTimeServiceImpl.java
+0
-1
RedeemRewardReqVO.java
...yudao/module/reward/api/reward/dto/RedeemRewardReqVO.java
+7
-9
ErrorCodeConstants.java
...iocoder/yudao/module/reward/enums/ErrorCodeConstants.java
+6
-0
RewardRedeemStatusEnum.java
...der/yudao/module/reward/enums/RewardRedeemStatusEnum.java
+24
-0
pom.xml
yudao-module-reward/yudao-module-reward-impl/pom.xml
+10
-1
RedeemRewardApiImpl.java
...r/yudao/module/reward/api/reward/RedeemRewardApiImpl.java
+168
-1
RewardRedeemDO.java
...o/module/reward/dal/dataobject/redeem/RewardRedeemDO.java
+100
-0
RewardDO.java
...r/yudao/module/reward/dal/dataobject/reward/RewardDO.java
+2
-0
RewardRedeemMapper.java
...ao/module/reward/dal/mysql/redeem/RewardRedeemMapper.java
+14
-0
RewardRedeemService.java
...dao/module/reward/service/redeem/RewardRedeemService.java
+13
-0
RewardRedeemServiceImpl.java
...module/reward/service/redeem/RewardRedeemServiceImpl.java
+22
-0
RewardServiceImpl.java
...yudao/module/reward/service/reward/RewardServiceImpl.java
+13
-5
RewardUpdateReqVO.java
...oder/yudao/module/reward/vo/reward/RewardUpdateReqVO.java
+1
-0
RewardRedeemMapper.xml
...ard-impl/src/main/resources/mapper/RewardRedeemMapper.xml
+12
-0
messages_en.properties
yudao-server/src/main/resources/i18n/messages_en.properties
+2
-1
messages_zh.properties
yudao-server/src/main/resources/i18n/messages_zh.properties
+2
-1
No files found.
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java
View file @
1e09e12b
...
...
@@ -3,8 +3,6 @@ package cn.iocoder.yudao.framework.common.util.date;
import
cn.hutool.core.date.DateUtil
;
import
java.time.Duration
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
java.util.Calendar
;
import
java.util.Date
;
...
...
@@ -152,11 +150,15 @@ public class DateUtils {
return
null
==
date
?
""
:
DateUtil
.
format
(
date
,
FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND
);
}
public
static
Date
getNextDayStart
(
Date
date
)
{
LocalDateTime
localDateTime
=
LocalDateTime
.
ofInstant
(
date
.
toInstant
(),
ZoneId
.
systemDefault
());
localDateTime
=
localDateTime
.
plusDays
(
1
).
withHour
(
0
).
withMinute
(
0
).
withSecond
(
0
);
java
.
time
.
LocalDate
localDate
=
localDateTime
.
toLocalDate
();
return
Date
.
from
(
localDate
.
atStartOfDay
(
ZoneId
.
systemDefault
()).
toInstant
());
public
static
Date
getNextNDayStart
(
Date
date
,
int
days
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTime
(
date
);
calendar
.
add
(
Calendar
.
DAY_OF_MONTH
,
days
);
calendar
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
calendar
.
set
(
Calendar
.
MILLISECOND
,
0
);
return
calendar
.
getTime
();
}
public
static
Date
addDays
(
Date
date
,
int
days
)
{
...
...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/i18n/core/I18nMessage.java
View file @
1e09e12b
...
...
@@ -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-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java
View file @
1e09e12b
...
...
@@ -14,6 +14,7 @@ public interface ErrorCodeConstants {
ErrorCode
CONFIG_KEY_DUPLICATE
=
new
ErrorCode
(
1001000002
,
"参数配置 key 重复"
);
ErrorCode
CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE
=
new
ErrorCode
(
1001000003
,
"不能删除类型为系统内置的参数配置"
);
ErrorCode
CONFIG_GET_VALUE_ERROR_IF_SENSITIVE
=
new
ErrorCode
(
1001000004
,
"不允许获取敏感配置到前端"
);
ErrorCode
GET_LOCK_FAILED
=
new
ErrorCode
(
1001000005
,
"get.lock.failed"
);
// ========== 定时任务 1001001000 ==========
ErrorCode
JOB_NOT_EXISTS
=
new
ErrorCode
(
1001001000
,
"定时任务不存在"
);
...
...
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/score/MemberUserScoreApi.java
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
member
.
api
.
score
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreBatchOperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateRespDTO
;
import
java.util.List
;
public
interface
MemberUserScoreApi
{
MemberUserScoreOperateRespDTO
operateScore
(
MemberUserScoreOperateReqDTO
req
);
List
<
MemberUserScoreOperateRespDTO
>
batchOperateScore
(
MemberUserScoreBatchOperateReqDTO
req
);
}
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/score/dto/MemberUserScoreBatchOperateReqDTO.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
member
.
api
.
score
.
dto
;
import
cn.iocoder.yudao.module.member.enums.ScoreOperateTypeEnum
;
import
cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.ToString
;
import
java.util.List
;
import
java.util.Map
;
@Data
@Builder
@ToString
public
class
MemberUserScoreBatchOperateReqDTO
{
/**
* 会员id
*/
private
List
<
Long
>
memberIds
;
/**
* 积分数量
*/
private
Integer
scoreCount
;
/**
* 积分来源
*/
private
ScoreSourceTypeEnum
sourceType
;
/**
* 人工操作时必传,其他来源不需要传
*/
private
ScoreOperateTypeEnum
operateType
;
/**
* 积分规则id
*/
private
Long
ruleId
;
/**
* 积分过期时间
*/
private
Integer
expireDays
;
/**
* 扩展参数
*/
private
Map
<
String
,
Object
>
extParam
;
}
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java
View file @
1e09e12b
...
...
@@ -46,4 +46,6 @@ public class UserRespDTO {
*/
private
String
controlPassword
;
private
Integer
holdScore
;
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/score/MemberUserScoreApiImpl.java
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
member
.
api
.
score
;
import
cn.iocoder.yudao.framework.redis.helper.RedisDistributedLock
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreDetailUpdateReqDto
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateRespDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreUpdateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.*
;
import
cn.iocoder.yudao.module.member.dal.dataobject.memberUserScore.MemberUserScoreDO
;
import
cn.iocoder.yudao.module.member.enums.ScoreOperateTypeEnum
;
import
cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum
;
import
cn.iocoder.yudao.module.member.service.memberUserScore.MemberUserScoreService
;
import
cn.iocoder.yudao.module.member.service.memberUserScoreDetail.MemberUserScoreDetailService
;
import
cn.iocoder.yudao.module.member.service.memberUserScoreLog.MemberUserScoreLogService
;
import
cn.iocoder.yudao.module.member.vo.memberUserScoreLog.MemberUserScoreLogCreateReq
;
import
com.alibaba.excel.util.CollectionUtils
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
exception
.
util
.
ServiceExceptionUtil
.
exception
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
MEMBER_ID_IS_NULL
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
SCORE_COUNT_ERROR
;
import
static
cn
.
iocoder
.
yudao
.
module
.
infra
.
enums
.
ErrorCodeConstants
.
GET_LOCK_FAILED
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
*
;
@Slf4j
@Service
...
...
@@ -42,11 +46,10 @@ public class MemberUserScoreApiImpl implements MemberUserScoreApi{
if
(
req
.
getScoreCount
()
<=
0
)
{
throw
exception
(
SCORE_COUNT_ERROR
);
}
//todo 校验
String
lockKey
=
"member:operate:socre:"
+
req
.
getMemberId
();
boolean
lock
=
redisDistributedLock
.
lock
(
lockKey
,
5000
,
3
,
100
);
if
(!
lock
)
{
return
MemberUserScoreOperateRespDTO
.
builder
().
success
(
false
).
code
(
500
).
reqDTO
(
req
).
build
(
);
throw
exception
(
GET_LOCK_FAILED
);
}
try
{
Long
logId
=
saveScoreLog
(
req
);
...
...
@@ -58,6 +61,36 @@ public class MemberUserScoreApiImpl implements MemberUserScoreApi{
return
MemberUserScoreOperateRespDTO
.
success
(
req
);
}
@Override
@Transactional
public
List
<
MemberUserScoreOperateRespDTO
>
batchOperateScore
(
MemberUserScoreBatchOperateReqDTO
req
)
{
if
(
CollectionUtils
.
isEmpty
(
req
.
getMemberIds
()))
{
throw
exception
(
MEMBER_ID_IS_NULL
);
}
if
(
req
.
getScoreCount
()
<=
0
)
{
throw
exception
(
SCORE_COUNT_ERROR
);
}
// 校验用户当前积分是否满足扣减要求
if
(
req
.
getOperateType
()
==
ScoreOperateTypeEnum
.
REDUCE
)
{
LambdaQueryWrapper
<
MemberUserScoreDO
>
wrapper
=
Wrappers
.
lambdaQuery
();
wrapper
.
in
(
MemberUserScoreDO:
:
getMemberId
,
req
.
getMemberIds
());
List
<
MemberUserScoreDO
>
userScoreDOList
=
memberUserScoreService
.
list
(
wrapper
);
List
<
MemberUserScoreDO
>
notEnoughScoreList
=
userScoreDOList
.
stream
()
.
filter
(
item
->
item
.
getHoldScore
()
<
req
.
getScoreCount
()).
collect
(
Collectors
.
toList
());
if
(!
notEnoughScoreList
.
isEmpty
())
{
throw
exception
(
MEMBER_SCORE_NOT_ENOUGH
);
}
}
return
req
.
getMemberIds
().
stream
().
map
(
memberId
->
operateScore
(
MemberUserScoreOperateReqDTO
.
builder
()
.
memberId
(
memberId
)
.
scoreCount
(
req
.
getScoreCount
())
.
operateType
(
req
.
getOperateType
())
.
sourceType
(
req
.
getSourceType
())
.
extParam
(
req
.
getExtParam
())
.
build
()))
.
collect
(
Collectors
.
toList
());
}
private
void
updateUserScore
(
MemberUserScoreOperateReqDTO
req
)
{
memberUserScoreService
.
updateUserScore
(
MemberUserScoreUpdateReqDTO
.
builder
()
.
memberId
(
req
.
getMemberId
())
...
...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/job/MemberCodeFlushTask.java
View file @
1e09e12b
...
...
@@ -21,6 +21,6 @@ public class MemberCodeFlushTask implements JobHandler {
@Override
public
String
execute
(
String
param
)
throws
Exception
{
userService
.
historyCodeFlush
();
return
""
;
return
"
success
"
;
}
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/job/MemberUserScoreExpireTask.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
member
.
controller
.
admin
.
job
;
import
cn.iocoder.yudao.framework.common.util.date.DateUtils
;
import
cn.iocoder.yudao.framework.quartz.core.handler.JobHandler
;
import
cn.iocoder.yudao.module.member.api.score.MemberUserScoreApi
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO
;
import
cn.iocoder.yudao.module.member.dal.dataobject.memberUserScoreDetail.MemberUserScoreDetailDO
;
import
cn.iocoder.yudao.module.member.enums.MemberScoreStatueEnum
;
import
cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum
;
import
cn.iocoder.yudao.module.member.service.memberUserScoreDetail.MemberUserScoreDetailService
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.CollectionUtils
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.google.common.collect.Lists
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 会员积分过期定时任务
*/
@Component
@Slf4j
public
class
MemberUserScoreExpireTask
implements
JobHandler
{
/**
* 会员积分的过期时间为每日的0点整
* 任务每天0点整运行,扫描当天0点过期的积分进行状态修改
* @param param 参数
* @return
* @throws Exception
*/
@Resource
private
MemberUserScoreDetailService
scoreDetailService
;
@Resource
private
MemberUserScoreApi
memberUserScoreApi
;
@Override
public
String
execute
(
String
param
)
throws
Exception
{
log
.
info
(
"member user score expire task running"
);
LambdaQueryWrapper
<
MemberUserScoreDetailDO
>
wrapper
=
Wrappers
.
lambdaQuery
();
wrapper
.
in
(
MemberUserScoreDetailDO:
:
getStatus
,
Lists
.
newArrayList
(
MemberScoreStatueEnum
.
AVAILABLE
.
getValue
(),
MemberScoreStatueEnum
.
PART_AVAILABLE
.
getValue
()));
wrapper
.
eq
(
MemberUserScoreDetailDO:
:
getExpireTime
,
DateUtils
.
getNextNDayStart
(
new
Date
(),
0
));
wrapper
.
orderByAsc
(
MemberUserScoreDetailDO:
:
getCreateTime
);
List
<
MemberUserScoreDetailDO
>
todoList
=
scoreDetailService
.
list
(
wrapper
);
log
.
info
(
"member user score expire task, to expire record count :{}"
,
todoList
.
size
());
if
(
CollectionUtils
.
isEmpty
(
todoList
))
{
return
"success"
;
}
for
(
MemberUserScoreDetailDO
memberUserScoreDetailDO
:
todoList
)
{
try
{
log
.
info
(
"score expire, score detail id :{}"
,
memberUserScoreDetailDO
.
getId
());
List
logIds
=
(
List
)
memberUserScoreDetailDO
.
getExtParamByKey
(
MemberUserScoreDetailDO
.
MemberUserScoreDetailExtKey
.
LOG_IDS
);
Map
<
String
,
Object
>
extParam
=
new
HashMap
<>();
extParam
.
put
(
"scoreLogIds"
,
logIds
);
memberUserScoreApi
.
operateScore
(
MemberUserScoreOperateReqDTO
.
builder
()
.
memberId
(
memberUserScoreDetailDO
.
getMemberId
())
.
scoreCount
(
memberUserScoreDetailDO
.
getRemainCount
())
.
sourceType
(
ScoreSourceTypeEnum
.
SYSTEM_EXPIRED
)
.
extParam
(
extParam
)
.
build
());
}
catch
(
Exception
e
)
{
log
.
error
(
"member user score expire exception, data:{}"
,
memberUserScoreDetailDO
,
e
);
}
}
log
.
info
(
"member user score expire task finished"
);
return
"success"
;
}
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/memberUserScore/MemberUserScoreController.java
View file @
1e09e12b
...
...
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.controller.admin.memberUserScore;
import
cn.iocoder.yudao.framework.common.pojo.CommonResult
;
import
cn.iocoder.yudao.framework.common.pojo.PageResult
;
import
cn.iocoder.yudao.module.member.api.score.MemberUserScoreApiImpl
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScore
Batch
OperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateRespDTO
;
import
cn.iocoder.yudao.module.member.enums.ScoreOperateTypeEnum
;
import
cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum
;
...
...
@@ -22,8 +22,8 @@ import org.springframework.web.bind.annotation.RestController;
import
javax.annotation.Resource
;
import
javax.validation.Valid
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
pojo
.
CommonResult
.
success
;
...
...
@@ -52,17 +52,15 @@ public class MemberUserScoreController {
@ApiOperation
(
"操作积分"
)
@PreAuthorize
(
"@ss.hasPermission('member:user-score:operate')"
)
public
CommonResult
<
Boolean
>
operate
(
@Valid
@RequestBody
MemberUserScoreOperateQueryVO
query
)
{
query
.
getMemberIds
().
forEach
(
memberId
->
{
Map
<
String
,
Object
>
extParam
=
new
HashMap
<>();
extParam
.
put
(
"comment"
,
query
.
getComment
());
MemberUserScoreOperateRespDTO
memberUserScoreOperateRespDTO
=
scoreApi
.
operateScore
(
MemberUserScoreOperateReqDTO
.
builder
()
.
memberId
(
memberId
)
.
scoreCount
(
query
.
getScoreCount
())
.
operateType
(
ScoreOperateTypeEnum
.
parseByValue
(
query
.
getOperateType
()))
.
sourceType
(
ScoreSourceTypeEnum
.
MANUAL_OPERATE
)
.
extParam
(
extParam
)
.
build
());
});
Map
<
String
,
Object
>
extParam
=
new
HashMap
<>();
extParam
.
put
(
"comment"
,
query
.
getComment
());
List
<
MemberUserScoreOperateRespDTO
>
memberUserScoreOperateRespDTOS
=
scoreApi
.
batchOperateScore
(
MemberUserScoreBatchOperateReqDTO
.
builder
()
.
memberIds
(
query
.
getMemberIds
())
.
scoreCount
(
query
.
getScoreCount
())
.
operateType
(
ScoreOperateTypeEnum
.
parseByValue
(
query
.
getOperateType
()))
.
sourceType
(
ScoreSourceTypeEnum
.
MANUAL_OPERATE
)
.
extParam
(
extParam
)
.
build
());
return
success
(
null
);
}
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/memberUserScoreDetail/MemberUserScoreDetailDO.java
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
member
.
dal
.
dataobject
.
memberUserScoreDetail
;
import
cn.hutool.json.JSONObject
;
import
cn.hutool.json.JSONUtil
;
import
cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
io.vavr.collection.List
;
import
lombok.*
;
import
org.apache.commons.lang.StringUtils
;
import
java.util.Date
;
import
java.util.Map
;
/**
* 会员积分 DO
...
...
@@ -40,8 +45,7 @@ public class MemberUserScoreDetailDO extends BaseDO {
@Getter
public
enum
MemberUserScoreDetailExtKey
{
LOG_IDS
(
"logIds"
);
LOG_IDS
(
"scoreLogIds"
);
private
final
String
key
;
...
...
@@ -50,4 +54,9 @@ public class MemberUserScoreDetailDO extends BaseDO {
}
}
public
Object
getExtParamByKey
(
MemberUserScoreDetailExtKey
key
)
{
JSONObject
extParamJsonObject
=
JSONUtil
.
parseObj
(
extParam
);
return
extParamJsonObject
.
get
(
key
.
getKey
(),
List
.
class
);
}
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java
View file @
1e09e12b
...
...
@@ -236,4 +236,5 @@ public class MemberUserDO extends TenantBaseDO {
private
String
code
;
private
Integer
holdScore
;
}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java
View file @
1e09e12b
...
...
@@ -160,11 +160,13 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
" uea.`name` as enterprise_name,"
,
" uea.`create_time` as enterprise_audit_create_time,"
,
" uea.`audit_time` as enterprise_audit_time,"
,
" uea.`audit_remark` as enterprise_audit_remark"
,
" uea.`audit_remark` as enterprise_audit_remark,"
,
" ifnull( mus.`hold_score`, 0) as hold_score"
,
"from member_user u "
,
"left join member_user_enterprise e on e.user_id = u.id and e.deleted = 0 "
,
"left join member_user_card_auth uca on u.id = uca.user_id and uca.deleted = 0 "
,
"left join member_user_enterprise_auth uea on u.id = uea.user_id and uea.deleted = 0 "
,
"left join member_user_score mus on u.id = mus.member_id and mus.deleted = 0 "
,
"where "
,
"u.deleted = 0 "
,
"AND u.id = #{id} "
,
...
...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/memberUserScoreDetail/MemberUserScoreDetailServiceImpl.java
View file @
1e09e12b
...
...
@@ -19,7 +19,7 @@ import java.util.*;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
exception
.
util
.
ServiceExceptionUtil
.
exception
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
date
.
DateUtils
.
addDays
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
date
.
DateUtils
.
getNextDayStart
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
date
.
DateUtils
.
getNext
N
DayStart
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
MEMBER_ID_IS_NULL
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
MEMBER_SCORE_NOT_ENOUGH
;
...
...
@@ -90,7 +90,7 @@ public class MemberUserScoreDetailServiceImpl extends AbstractService<MemberUser
memberUserScoreDetailDO
.
setRemainCount
(
reqDto
.
getScoreCount
());
memberUserScoreDetailDO
.
setCreateTime
(
new
Date
());
if
(
reqDto
.
getExpireDays
()
!=
null
)
{
memberUserScoreDetailDO
.
setExpireTime
(
addDays
(
getNext
DayStart
(
memberUserScoreDetailDO
.
getCreateTime
()
),
reqDto
.
getExpireDays
()));
memberUserScoreDetailDO
.
setExpireTime
(
addDays
(
getNext
NDayStart
(
memberUserScoreDetailDO
.
getCreateTime
(),
1
),
reqDto
.
getExpireDays
()));
}
Map
<
String
,
Object
>
extParma
=
new
HashMap
<>();
extParma
.
put
(
MemberUserScoreDetailDO
.
MemberUserScoreDetailExtKey
.
LOG_IDS
.
getKey
(),
Lists
.
newArrayList
(
reqDto
.
getScoreLogId
()));
...
...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
View file @
1e09e12b
...
...
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import
cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX
;
import
cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils
;
import
cn.iocoder.yudao.framework.mybatis.core.vo.PageVO
;
import
cn.iocoder.yudao.framework.redis.helper.RedisDistributedLock
;
import
cn.iocoder.yudao.framework.redis.helper.RedisHelper
;
import
cn.iocoder.yudao.module.ecw.api.customer.CustomerApi
;
import
cn.iocoder.yudao.module.ecw.api.internalMessage.ClientInternalMessageApi
;
...
...
@@ -63,6 +64,7 @@ import java.util.stream.Collectors;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
exception
.
util
.
ServiceExceptionUtil
.
exception
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
servlet
.
ServletUtils
.
getClientIP
;
import
static
cn
.
iocoder
.
yudao
.
module
.
infra
.
enums
.
ErrorCodeConstants
.
GET_LOCK_FAILED
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.*;
/**
...
...
@@ -111,6 +113,9 @@ public class MemberUserServiceImpl implements MemberUserService {
@Resource
private
RedisHelper
redisHelper
;
@Resource
private
RedisDistributedLock
redisDistributedLock
;
@Override
public
MemberUserDO
getUserByMobile
(
String
mobile
)
{
...
...
@@ -580,7 +585,11 @@ public class MemberUserServiceImpl implements MemberUserService {
if
(
nextMemberCodeNumber
!=
null
)
{
return
MemberUserCodeUtils
.
generateMemberCode
(
nextMemberCodeNumber
);
}
synchronized
(
this
)
{
boolean
lock
=
redisDistributedLock
.
lock
(
"next:member:code:lock"
,
2000
,
3
,
500
);
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
try
{
nextMemberCodeNumber
=
redisHelper
.
execute4Long
(
redisScript
,
Collections
.
singletonList
(
key
));
if
(
nextMemberCodeNumber
!=
null
)
{
return
MemberUserCodeUtils
.
generateMemberCode
(
nextMemberCodeNumber
);
...
...
@@ -589,6 +598,8 @@ public class MemberUserServiceImpl implements MemberUserService {
Long
memberCodeMaxNumber
=
MemberUserCodeUtils
.
getMemberCodeNumber
(
currentMaxMemberCode
);
redisHelper
.
set
(
key
,
String
.
valueOf
(
memberCodeMaxNumber
),
5
,
TimeUnit
.
MINUTES
);
return
MemberUserCodeUtils
.
generateMemberCode
(
redisHelper
.
incrBy
(
key
,
1
));
}
finally
{
redisDistributedLock
.
releaseLock
(
"next:member:code:lock"
);
}
}
...
...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/vo/memberUserScore/MemberUserScoreBackVO.java
View file @
1e09e12b
...
...
@@ -28,6 +28,8 @@ public class MemberUserScoreBackVO {
private
Integer
holdScore
;
@ApiModelProperty
(
value
=
"已兑换积分"
)
private
Integer
usedScore
;
@ApiModelProperty
(
value
=
"已失效积分"
)
private
Integer
expiredScore
;
@ApiModelProperty
(
value
=
"会员注册时间"
)
private
Date
createTime
;
}
yudao-module-member/yudao-module-member-impl/src/main/resources/mapper/user/MemberUserScoreMapper.xml
View file @
1e09e12b
...
...
@@ -10,8 +10,9 @@
mu.mobile,
re.title_zh as countryNameZh,
re.title_en as countryNameEn,
mus.hold_score as holdScore,
mus.used_score as usedScore,
ifnull(mus.hold_score, 0) as holdScore,
ifnull(mus.used_score, 0) as usedScore,
ifnull(mus.expired_score, 0) as expiredScore,
mu.create_time as createTime
from member_user mu
left join member_user_score mus on mus.member_id = mu.id
...
...
yudao-module-order/yudao-module-order-core/src/main/java/cn/iocoder/yudao/module/order/service/order/impl/OrderTimeServiceImpl.java
View file @
1e09e12b
...
...
@@ -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/api/reward/dto/RedeemRewardReqVO.java
View file @
1e09e12b
...
...
@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import
lombok.Data
;
import
org.springframework.format.annotation.DateTimeFormat
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
date
.
DateUtils
.
FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND
;
...
...
@@ -12,26 +13,23 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data
@ApiModel
(
"管理后台 - 礼品兑换 Request VO"
)
public
class
RedeemRewardReqVO
{
@ApiModelProperty
(
value
=
"会员名称"
)
private
String
memberName
;
@ApiModelProperty
(
value
=
"当前积分"
)
private
Integer
score
;
@ApiModelProperty
(
value
=
"会员id"
)
private
Long
memberId
;
@ApiModelProperty
(
value
=
"礼品id"
)
private
Long
rewardId
;
@ApiModelProperty
(
value
=
"兑换数量"
)
private
Integer
c
ount
;
private
Integer
rewardC
ount
;
@ApiModelProperty
(
value
=
"兑换方式,同领取方式(1上门领取,2包邮到家,3邮寄到付)"
)
private
Integer
pickMethod
;
private
Integer
redeemType
;
@ApiModelProperty
(
value
=
"兑换入口(后台,app,web)"
)
private
String
entrance
;
private
Integer
entrance
;
@ApiModelProperty
(
value
=
"费用数字(两位小数)"
)
private
Integer
expenses
;
private
BigDecimal
expenses
;
@ApiModelProperty
(
value
=
"费用币种(字典配置)"
)
private
Integer
currency
;
...
...
yudao-module-reward/yudao-module-reward-api/src/main/java/cn/iocoder/yudao/module/reward/enums/ErrorCodeConstants.java
View file @
1e09e12b
...
...
@@ -17,5 +17,11 @@ public interface ErrorCodeConstants {
ErrorCode
REWARD_PICK_METHOD_NOT_ALLOW_CREATE
=
new
ErrorCode
(
1001011009
,
"领取方式不合法"
);
ErrorCode
REWARD_STATUS_NOT_ALLOW_UPDATE
=
new
ErrorCode
(
1001011010
,
"礼物状态不允许编辑"
);
ErrorCode
REWARD_STATUS_NOT_ALLOW_ENABLE
=
new
ErrorCode
(
1001011011
,
"礼物不能启用"
);
ErrorCode
REWARD_NOT_ENABLE
=
new
ErrorCode
(
1001011012
,
"礼物未启用"
);
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-api/src/main/java/cn/iocoder/yudao/module/reward/enums/RewardRedeemStatusEnum.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
enums
;
public
enum
RewardRedeemStatusEnum
{
REDEEMING
(
1
,
"兑换中"
),
REDEEMED
(
2
,
"已兑换"
),
CANCELED
(
3
,
"已取消"
)
;
private
final
int
value
;
private
final
String
name
;
RewardRedeemStatusEnum
(
int
value
,
String
name
)
{
this
.
value
=
value
;
this
.
name
=
name
;
}
public
int
getValue
()
{
return
value
;
}
public
String
getName
()
{
return
name
;
}
}
yudao-module-reward/yudao-module-reward-impl/pom.xml
View file @
1e09e12b
...
...
@@ -26,7 +26,16 @@
<artifactId>
yudao-module-reward-api
</artifactId>
<version>
${revision}
</version>
</dependency>
<dependency>
<groupId>
cn.iocoder.boot
</groupId>
<artifactId>
yudao-module-infra-api
</artifactId>
<version>
${revision}
</version>
</dependency>
<dependency>
<groupId>
cn.iocoder.boot
</groupId>
<artifactId>
yudao-module-member-api
</artifactId>
<version>
${revision}
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/api/reward/RedeemRewardApiImpl.java
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
api
.
reward
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.lang.generator.SnowflakeGenerator
;
import
cn.iocoder.yudao.framework.redis.helper.RedisDistributedLock
;
import
cn.iocoder.yudao.module.member.api.score.MemberUserScoreApi
;
import
cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO
;
import
cn.iocoder.yudao.module.member.api.user.MemberUserApi
;
import
cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO
;
import
cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum
;
import
cn.iocoder.yudao.module.reward.api.reward.dto.RedeemRewardReqVO
;
import
cn.iocoder.yudao.module.reward.api.reward.dto.RedeemRewardRespDTO
;
import
cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO
;
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
java.util.List
;
import
javax.annotation.Resource
;
import
java.util.*
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
exception
.
util
.
ServiceExceptionUtil
.
exception
;
import
static
cn
.
iocoder
.
yudao
.
module
.
infra
.
enums
.
ErrorCodeConstants
.
GET_LOCK_FAILED
;
import
static
cn
.
iocoder
.
yudao
.
module
.
member
.
enums
.
ErrorCodeConstants
.
USER_NOT_EXISTS
;
import
static
cn
.
iocoder
.
yudao
.
module
.
reward
.
enums
.
ErrorCodeConstants
.*;
@Service
@Validated
public
class
RedeemRewardApiImpl
implements
RedeemRewardApi
{
@Resource
private
RewardMapper
rewardMapper
;
@Resource
private
RewardRedeemMapper
rewardRedeemMapper
;
@Resource
private
MemberUserApi
memberUserApi
;
@Resource
private
RedisDistributedLock
redisDistributedLock
;
@Resource
private
MemberUserScoreApi
memberUserScoreApi
;
@Resource
private
SnowflakeGenerator
snowflakeGenerator
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
RedeemRewardRespDTO
redeemReward
(
RedeemRewardReqVO
redeemRewardReqVO
)
{
// 查询礼品
RewardDO
rewardDO
=
rewardMapper
.
selectById
(
redeemRewardReqVO
.
getRewardId
());
if
(
rewardDO
==
null
)
{
throw
exception
(
REWARD_NOT_EXISTS
);
}
// 礼品未开启
if
(
rewardDO
.
getStatus
()
!=
1
)
{
throw
exception
(
REWARD_NOT_ENABLE
);
}
// 礼品数量不够
if
(
rewardDO
.
getQuantityRemain
()
<
redeemRewardReqVO
.
getRewardCount
())
{
throw
exception
(
REWARD_COUNT_NOT_ENOUGH
);
}
// 兑换方式不匹配
if
(!
Objects
.
equals
(
rewardDO
.
getPickMethod
(),
redeemRewardReqVO
.
getRedeemType
()))
{
throw
exception
(
REWARD_PICK_METHOD_NOT_ALLOW_CREATE
);
}
verifyMemberUser
(
redeemRewardReqVO
,
rewardDO
);
boolean
lock
=
false
;
try
{
lock
=
redisDistributedLock
.
lock
(
"reward:redeem:lock:"
+
redeemRewardReqVO
.
getRewardId
());
if
(!
lock
)
{
throw
exception
(
GET_LOCK_FAILED
);
}
// 更新礼品
redeemReward
(
rewardDO
,
redeemRewardReqVO
.
getRewardCount
());
// 添加兑换记录
Long
redeemId
=
addRedeemRecord
(
redeemRewardReqVO
);
// 更新会员积分
updateMemberScore
(
redeemRewardReqVO
,
rewardDO
,
redeemId
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
finally
{
redisDistributedLock
.
releaseLock
(
"reward:redeem:lock:"
+
redeemRewardReqVO
.
getRewardId
());
}
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
())
.
extParam
(
extParam
)
.
build
());
}
private
Long
addRedeemRecord
(
RedeemRewardReqVO
redeemRewardReqVO
)
{
RewardRedeemDO
rewardRedeemDO
=
BeanUtil
.
copyProperties
(
redeemRewardReqVO
,
RewardRedeemDO
.
class
);
rewardRedeemDO
.
setId
(
snowflakeGenerator
.
next
());
rewardRedeemDO
.
setStatus
(
RewardRedeemStatusEnum
.
REDEEMING
.
getValue
());
rewardRedeemMapper
.
insert
(
rewardRedeemDO
);
return
rewardRedeemDO
.
getId
();
}
@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
);
// 礼品未开启
if
(
rewardDO
.
getStatus
()
!=
1
)
{
throw
exception
(
REWARD_NOT_ENABLE
);
}
int
totalCount
=
0
;
for
(
RedeemRewardReqVO
redeemRewardReqVO
:
redeemRewardReqVOList
)
{
// 每个兑换VO校验一遍
// 兑换方式不匹配
if
(!
Objects
.
equals
(
rewardDO
.
getPickMethod
(),
redeemRewardReqVO
.
getRedeemType
()))
{
throw
exception
(
REWARD_PICK_METHOD_NOT_ALLOW_CREATE
);
}
verifyMemberUser
(
redeemRewardReqVO
,
rewardDO
);
// 记录兑换总数
totalCount
+=
redeemRewardReqVO
.
getRewardCount
();
// 判断兑换总数是否大于礼物数量
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
{
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/redeem/RewardRedeemDO.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
dal
.
dataobject
.
redeem
;
import
cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.*
;
import
java.math.BigDecimal
;
import
java.util.Date
;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName
(
"ecw_reward_redeem"
)
@EqualsAndHashCode
(
callSuper
=
true
)
@ToString
(
callSuper
=
true
)
public
class
RewardRedeemDO
extends
BaseDO
{
/**
* 主键
*/
@TableId
private
Long
id
;
/**
* 会员id
*/
private
Long
memberId
;
/**
* 礼品id
*/
private
Long
rewardId
;
/**
* 兑换状态
*/
private
Integer
status
;
/**
* 兑换数量
*/
private
Integer
rewardCount
;
/**
* 兑换方式
*/
private
Integer
redeemType
;
/**
* 兑换入口
*/
private
Integer
entrance
;
/**
* 费用
*/
private
BigDecimal
expenses
;
/**
* 币种
*/
private
Integer
currency
;
/**
* 收件人姓名
*/
private
String
recipientName
;
/**
* 收件人电话
*/
private
String
recipientPhoneNum
;
/**
* 收件人地址
*/
private
String
recipientAddress
;
/**
* 兑换人
*/
private
String
redeemer
;
/**
* 兑换时间
*/
private
Date
redemptionTime
;
/**
* 快递公司
*/
private
String
courierCompany
;
/**
* 快递单号
*/
private
String
expressNo
;
/**
* 快递日期
*/
private
String
expressDate
;
/**
* 快递寄出人
*/
private
String
expressSender
;
/**
* 上传附件
*/
private
String
annex
;
/**
* 备注
*/
private
String
remark
;
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/dal/dataobject/reward/RewardDO.java
View file @
1e09e12b
...
...
@@ -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/dal/mysql/redeem/RewardRedeemMapper.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
dal
.
mysql
.
redeem
;
import
cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper
;
import
cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO
;
import
org.apache.ibatis.annotations.Mapper
;
/**
* 礼品 Mapper
* @author 系统管理员
*/
@Mapper
public
interface
RewardRedeemMapper
extends
AbstractMapper
<
RewardRedeemDO
>
{
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/service/redeem/RewardRedeemService.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
service
.
redeem
;
import
cn.iocoder.yudao.framework.mybatis.core.service.IService
;
import
cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO
;
/**
* 礼品兑换 Service 接口
*
* @author 系统管理员
*/
public
interface
RewardRedeemService
extends
IService
<
RewardRedeemDO
>
{
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/service/redeem/RewardRedeemServiceImpl.java
0 → 100644
View file @
1e09e12b
package
cn
.
iocoder
.
yudao
.
module
.
reward
.
service
.
redeem
;
import
cn.iocoder.yudao.framework.mybatis.core.service.AbstractService
;
import
cn.iocoder.yudao.framework.mybatis.core.service.IService
;
import
cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO
;
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.service.reward.RewardService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
/**
* 礼品兑换 Service
*
* @author 系统管理员
*/
@Service
@Slf4j
public
class
RewardRedeemServiceImpl
extends
AbstractService
<
RewardRedeemMapper
,
RewardRedeemDO
>
implements
RewardRedeemService
{
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/service/reward/RewardServiceImpl.java
View file @
1e09e12b
...
...
@@ -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
());
...
...
@@ -271,12 +276,15 @@ public class RewardServiceImpl extends AbstractService<RewardMapper, RewardDO> i
}
//校验礼品是否过期并修改礼品状态
//TODO:异步更新礼品状态
private
void
validateExpire
(
RewardDO
rewardDO
)
{
if
(
rewardDO
.
getStatus
()
==
1
&&
rewardDO
.
getEndTime
().
toInstant
().
isBefore
(
Instant
.
now
()))
{
RewardDO
expireReward
=
new
RewardDO
();
expireReward
.
setId
(
rewardDO
.
getId
());
expireReward
.
setStatus
(
4
);
rewardMapper
.
updateById
(
expireReward
);
if
(
rewardDO
.
getEndTime
()
!=
null
){
if
(
rewardDO
.
getStatus
()
==
1
&&
rewardDO
.
getEndTime
().
toInstant
().
isBefore
(
Instant
.
now
()))
{
RewardDO
expireReward
=
new
RewardDO
();
expireReward
.
setId
(
rewardDO
.
getId
());
expireReward
.
setStatus
(
4
);
rewardMapper
.
updateById
(
expireReward
);
}
}
}
}
yudao-module-reward/yudao-module-reward-impl/src/main/java/cn/iocoder/yudao/module/reward/vo/reward/RewardUpdateReqVO.java
View file @
1e09e12b
...
...
@@ -51,6 +51,7 @@ public class RewardUpdateReqVO {
private
Integer
nodeId
;
@ApiModelProperty
(
value
=
"剩余数量"
)
@NotNull
(
message
=
"剩余数量不能为空"
)
@Min
(
value
=
0
)
private
Integer
quantityRemain
;
...
...
yudao-module-reward/yudao-module-reward-impl/src/main/resources/mapper/RewardRedeemMapper.xml
0 → 100644
View file @
1e09e12b
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.iocoder.yudao.module.reward.dal.mysql.redeem.RewardRedeemMapper"
>
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>
yudao-server/src/main/resources/i18n/messages_en.properties
View file @
1e09e12b
...
...
@@ -1009,4 +1009,5 @@ reward.status.not.allow.close=Not enable reward can not close
reward.status.change.error
=
The reward status change error
reward.status.not.allow.delay
=
Only enable status can delay
reward.status.not.allow.create
=
Only enabled or disabled reward status can be created
reward.time.not.allow
=
The reward time is not allow
\ No newline at end of file
reward.time.not.allow
=
The reward time is not allow
get.lock.failed
=
The service is busy, please try again later
\ No newline at end of file
yudao-server/src/main/resources/i18n/messages_zh.properties
View file @
1e09e12b
...
...
@@ -1013,4 +1013,5 @@ reward.status.not.allow.close=\u672A\u542F\u7528\u793C\u54C1\u4E0D\u53EF\u5173\u
reward.status.change.error
=
\u
793C
\u
54C1
\u
72B6
\u6001\u
64CD
\u
4F5C
\u
4E0D
\u
7B26
\u5408\u
89C4
\u5219
reward.status.not.allow.delay
=
\u
53EA
\u5141\u
8BB8
\u
5EF6
\u
671F
\u
542F
\u7528\u
72B6
\u6001\u
793C
\u
54C1
reward.status.not.allow.create
=
\u
521B
\u
5EFA
\u7684\u
793C
\u
54C1
\u
72B6
\u6001\u
53EA
\u
80FD
\u
662F
\u
542F
\u7528\u6216\u
672A
\u
542F
\u7528
reward.time.not.allow
=
\u
6D3B
\u
52A8
\u
65F6
\u
95F4
\u
4E0D
\u5408\u
6CD5
\ No newline at end of file
reward.time.not.allow
=
\u
6D3B
\u
52A8
\u
65F6
\u
95F4
\u
4E0D
\u5408\u
6CD5
get.lock.failed
=
\u
670D
\u
52A1
\u
7E41
\u
5FD9
\u
FF0C
\u
8BF7
\u
7A0D
\u
540E
\u
91CD
\u
8BD5
\ No newline at end of file
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