Toggle navigation
Toggle navigation
This project
Loading...
Sign in
ufo
/
yohoufo-fore
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Email Patches
Plain Diff
Browse Files
Authored by
tanling
6 years ago
Commit
9dd79dcdde7104a236e18c51a40693a7616abf84
1 parent
0c5daaf9
优惠券
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
1003 additions
and
107 deletions
common/src/main/java/com/yohoufo/common/cache/CacheClient.java
common/src/main/java/com/yohoufo/common/cache/RedisGwCacheClient.java
common/src/main/java/com/yohoufo/common/utils/DateUtil.java
dal/src/main/java/com/yohoufo/dal/promotion/CouponMapper.java
dal/src/main/java/com/yohoufo/dal/promotion/CouponTypeMapper.java
dal/src/main/java/com/yohoufo/dal/promotion/UserCouponMapper.java
dal/src/main/java/com/yohoufo/dal/promotion/model/Coupon.java
dal/src/main/java/com/yohoufo/dal/promotion/model/CouponAndType.java
dal/src/main/java/com/yohoufo/dal/promotion/model/CouponType.java
dal/src/main/java/com/yohoufo/dal/promotion/model/UserCoupon.java
dal/src/main/resources/META-INF/mybatis/promotion/CouponMapper.xml
dal/src/main/resources/META-INF/mybatis/promotion/CouponTypeMapper.xml
dal/src/main/resources/META-INF/mybatis/promotion/UserCouponMapper.xml
promotion/src/main/java/com/yohoufo/promotion/cache/ExpiredTime.java
promotion/src/main/java/com/yohoufo/promotion/cache/KeyBuilder.java
promotion/src/main/java/com/yohoufo/promotion/common/CouponsStatusEnum.java
promotion/src/main/java/com/yohoufo/promotion/common/ProductLimitType.java
promotion/src/main/java/com/yohoufo/promotion/common/UseLimitType.java
promotion/src/main/java/com/yohoufo/promotion/controller/CouponController.java
promotion/src/main/java/com/yohoufo/promotion/convert/CouponConvert.java
promotion/src/main/java/com/yohoufo/promotion/model/response/CouponInfo.java
promotion/src/main/java/com/yohoufo/promotion/service/CouponCodeGenerate.java
promotion/src/main/java/com/yohoufo/promotion/service/CouponServiceImpl.java
promotion/src/main/java/com/yohoufo/promotion/service/ICouponCacheService.java
promotion/src/main/java/com/yohoufo/promotion/service/ICouponService.java
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponCacheServiceImpl.java
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponCodeGenerateImpl.java
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponServiceImpl.java
common/src/main/java/com/yohoufo/common/cache/CacheClient.java
View file @
9dd79dc
package
com
.
yohoufo
.
common
.
cache
;
import
com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
/**
...
...
@@ -8,6 +11,9 @@ import java.util.Map;
*/
public
interface
CacheClient
{
public
void
mset
(
Map
<
RedisKeyBuilder
,
?
extends
Object
>
map
,
long
timeout
);
public
<
T
>
Map
<
String
,
T
>
mget
(
List
<
RedisKeyBuilder
>
keys
,
Class
<
T
>
clazz
);
/**
* 设置cache
...
...
@@ -51,12 +57,15 @@ public interface CacheClient {
*/
public
void
delete
(
String
key
);
public
void
mset
(
Map
<
String
,
?
extends
Object
>
map
,
long
timeout
);
public
<
T
>
void
hashPut
(
String
key
,
String
field
,
T
value
,
long
timeout
);
public
<
T
>
T
hashGet
(
String
key
,
String
field
,
Class
<
T
>
clazz
);
boolean
setNx
(
String
key
,
int
expireInSeconds
,
Object
o
);
public
void
setEx
(
RedisKeyBuilder
key
,
Object
value
,
long
timeout
);
public
<
T
>
T
get
(
RedisKeyBuilder
key
,
Class
<
T
>
clazz
);
}
...
...
common/src/main/java/com/yohoufo/common/cache/RedisGwCacheClient.java
View file @
9dd79dc
package
com
.
yohoufo
.
common
.
cache
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
...
...
@@ -33,6 +29,41 @@ public class RedisGwCacheClient implements CacheClient {
@Redis
(
"gwNoSyncRedis"
)
private
YHHashOperations
hashOperations
;
public
<
T
>
Map
<
String
,
T
>
mget
(
List
<
RedisKeyBuilder
>
keys
,
Class
<
T
>
clazz
)
{
long
beginTime
=
System
.
currentTimeMillis
();
try
{
List
<
String
>
multiGet
=
valueOperations
.
multiGet
(
keys
);
int
size
=
multiGet
.
size
();
Map
<
String
,
T
>
result
=
new
HashMap
<
String
,
T
>(
size
);
String
curItem
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
curItem
=
multiGet
.
get
(
i
);
if
(
null
==
curItem
)
{
result
.
put
(
keys
.
get
(
i
).
getKey
(),
null
);
LOGGER
.
debug
(
"cache miss key:{}"
,
keys
.
get
(
i
));
}
else
{
//基本类型直接返回
if
(
String
.
class
.
equals
(
clazz
))
{
result
.
put
(
keys
.
get
(
i
).
getKey
(),
(
T
)
curItem
);
}
else
{
result
.
put
(
keys
.
get
(
i
).
getKey
(),
JSON
.
parseObject
(
curItem
,
clazz
));
}
LOGGER
.
debug
(
"cache hit key:{}"
,
keys
.
get
(
i
));
}
}
return
result
;
}
catch
(
Exception
e
)
{
LOGGER
.
warn
(
"get from cache failed!!! keys is: "
+
keys
,
e
);
HashMap
<
String
,
T
>
hashMap
=
new
HashMap
<
String
,
T
>(
keys
.
size
());
for
(
RedisKeyBuilder
key
:
keys
)
{
hashMap
.
put
(
key
.
getKey
(),
null
);
}
return
hashMap
;
}
}
@Override
public
void
set
(
String
key
,
int
expireInSeconds
,
Object
o
)
{
...
...
@@ -49,6 +80,28 @@ public class RedisGwCacheClient implements CacheClient {
}
}
/**
* @param key
* @param value
* @param timeout 默认单位秒
*/
public
void
setEx
(
RedisKeyBuilder
key
,
Object
value
,
long
timeout
)
{
String
redisValue
=
null
;
if
(
value
instanceof
String
)
{
redisValue
=
(
String
)
value
;
}
else
{
redisValue
=
JSON
.
toJSONString
(
value
);
}
long
beginTime
=
System
.
currentTimeMillis
();
try
{
valueOperations
.
set
(
key
,
redisValue
,
timeout
,
TimeUnit
.
SECONDS
);
}
catch
(
Exception
e
)
{
LOGGER
.
warn
(
"add cache failed!!! cachekey:{}"
,
key
,
e
);
}
}
@Override
public
void
setAndSync
(
String
key
,
int
expireInSeconds
,
Object
o
)
{
if
(
expireInSeconds
>
120
)
{
...
...
@@ -64,6 +117,36 @@ public class RedisGwCacheClient implements CacheClient {
}
}
/**
* @param key
* @param clazz
* @return
*/
public
<
T
>
T
get
(
RedisKeyBuilder
key
,
Class
<
T
>
clazz
)
{
long
beginTime
=
System
.
currentTimeMillis
();
T
t
=
null
;
try
{
String
value
=
valueOperations
.
get
(
key
);
if
(
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isBlank
(
value
))
{
LOGGER
.
debug
(
"cache miss key:{}"
,
key
);
return
null
;
}
if
(
clazz
.
equals
(
String
.
class
))
{
t
=
(
T
)
value
;
}
else
{
t
=
JSON
.
parseObject
(
value
,
clazz
);
}
LOGGER
.
debug
(
"cache hit key:{}"
,
key
);
return
t
;
}
catch
(
Exception
e
)
{
LOGGER
.
warn
(
"get from cache failed!!! key:{},error:{}"
,
key
,
e
.
getMessage
());
return
null
;
}
}
@Override
public
<
T
>
T
get
(
String
key
,
Class
<
T
>
clazz
)
{
try
{
...
...
@@ -113,28 +196,33 @@ public class RedisGwCacheClient implements CacheClient {
}
}
@Override
public
void
mset
(
Map
<
String
,
?
extends
Object
>
map
,
long
timeout
)
{
/**
* @param map
* @param timeout
*/
public
void
mset
(
Map
<
RedisKeyBuilder
,
?
extends
Object
>
map
,
long
timeout
)
{
if
(
MapUtils
.
isEmpty
(
map
))
{
return
;
}
Map
<
RedisKeyBuilder
,
String
>
cacheMap
=
new
HashMap
<
RedisKeyBuilder
,
String
>(
map
.
size
());
try
{
Map
<
RedisKeyBuilder
,
String
>
cacheMap
=
new
HashMap
(
map
.
size
());
for
(
String
key
:
map
.
keySet
())
{
Object
value
=
map
.
get
(
key
);
RedisKeyBuilder
keyBuilder
=
RedisKeyBuilder
.
newInstance
().
appendFixed
(
key
);
if
(
value
instanceof
String
)
{
cacheMap
.
put
(
keyBuilder
,
(
String
)
value
);
}
else
if
(
value
instanceof
Integer
)
{
cacheMap
.
put
(
keyBuilder
,
value
+
""
);
}
else
{
cacheMap
.
put
(
keyBuilder
,
JSON
.
toJSONString
(
value
));
}
Set
<?
extends
Map
.
Entry
<
RedisKeyBuilder
,
?>>
entries
=
map
.
entrySet
();
for
(
Map
.
Entry
<
RedisKeyBuilder
,
?>
entry
:
entries
)
{
RedisKeyBuilder
key
=
entry
.
getKey
();
Object
value
=
entry
.
getValue
();
if
(
value
instanceof
String
)
{
cacheMap
.
put
(
key
,
(
String
)
value
);
}
else
if
(
value
instanceof
Integer
)
{
cacheMap
.
put
(
key
,
value
+
""
);
}
else
{
cacheMap
.
put
(
key
,
JSON
.
toJSONString
(
value
));
}
redis
.
mset
(
cacheMap
,
timeout
);
}
catch
(
Exception
e
){
LOGGER
.
warn
(
"mset cache failed!!! e is: {}"
,
e
);
}
long
beginTime
=
System
.
currentTimeMillis
();
try
{
redis
.
mset
(
cacheMap
,
timeout
);
}
catch
(
Exception
e
)
{
LOGGER
.
warn
(
"add cache failed!!! map is: {}"
,
map
,
e
);
}
}
...
...
common/src/main/java/com/yohoufo/common/utils/DateUtil.java
View file @
9dd79dc
...
...
@@ -62,6 +62,19 @@ public class DateUtil {
return
currentTime
>=
startTime
.
intValue
()
&&
currentTime
<=
endTime
.
intValue
();
}
public
static
String
getDateFormat
(
Integer
time
)
{
if
(
time
==
null
)
{
return
""
;
}
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
yyyy_MM_dd
);
Calendar
c
=
Calendar
.
getInstance
();
c
.
setTimeInMillis
((
time
.
longValue
()*
1000
));
return
sdf
.
format
(
c
.
getTime
());
}
/**
* 判断当前时间是否在 开始日期跟结束日期之间
*
...
...
dal/src/main/java/com/yohoufo/dal/promotion/CouponMapper.java
View file @
9dd79dc
...
...
@@ -15,7 +15,11 @@ public interface CouponMapper {
Coupon
selectByPrimaryKey
(
Integer
id
);
List
<
Coupon
>
selectByIds
(
@Param
(
"ids"
)
List
<
Integer
>
id
);
Coupon
selectByCouponToken
(
@Param
(
"couponToken"
)
String
couponToken
);
List
<
Coupon
>
selectByCouponIds
(
@Param
(
"ids"
)
List
<
Integer
>
id
);
List
<
Coupon
>
selectByCouponTokens
(
@Param
(
"list"
)
List
<
String
>
couponTokens
);
int
updateByPrimaryKeySelective
(
Coupon
record
);
...
...
dal/src/main/java/com/yohoufo/dal/promotion/CouponTypeMapper.java
View file @
9dd79dc
...
...
@@ -14,7 +14,7 @@ public interface CouponTypeMapper {
int
insertSelective
(
CouponType
record
);
CouponType
selectByPrimaryKey
(
Byte
id
);
CouponType
selectByPrimaryKey
(
Integer
id
);
int
updateByPrimaryKeySelective
(
CouponType
record
);
...
...
dal/src/main/java/com/yohoufo/dal/promotion/UserCouponMapper.java
View file @
9dd79dc
...
...
@@ -13,10 +13,14 @@ public interface UserCouponMapper {
int
insertSelective
(
UserCoupon
record
);
UserCoupon
selectByUidAndToken
(
@Param
(
"uid"
)
Integer
id
,
@Param
(
"couponToken"
)
String
couponToken
);
UserCoupon
selectByPrimaryKey
(
Integer
id
);
List
<
UserCoupon
>
selectUsableCouponByUid
(
@Param
(
"uid"
)
Integer
uid
,
@Param
(
"now"
)
int
now
);
int
selectCntUsableCouponByUid
(
@Param
(
"uid"
)
Integer
uid
,
@Param
(
"now"
)
int
now
);
int
updateByPrimaryKeySelective
(
UserCoupon
record
);
int
updateByPrimaryKey
(
UserCoupon
record
);
...
...
dal/src/main/java/com/yohoufo/dal/promotion/model/Coupon.java
View file @
9dd79dc
...
...
@@ -11,7 +11,7 @@ public class Coupon {
private
BigDecimal
couponAmount
;
private
Byte
couponType
;
private
Integer
couponType
;
private
Integer
couponNum
;
...
...
@@ -71,11 +71,11 @@ public class Coupon {
this
.
couponAmount
=
couponAmount
;
}
public
Byte
getCouponType
()
{
public
Integer
getCouponType
()
{
return
couponType
;
}
public
void
setCouponType
(
Byte
couponType
)
{
public
void
setCouponType
(
Integer
couponType
)
{
this
.
couponType
=
couponType
;
}
...
...
dal/src/main/java/com/yohoufo/dal/promotion/model/CouponAndType.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
dal
.
promotion
.
model
;
import
lombok.Data
;
import
lombok.experimental.Builder
;
@Data
@Builder
public
class
CouponAndType
{
private
Coupon
coupon
;
private
CouponType
couponType
;
}
...
...
dal/src/main/java/com/yohoufo/dal/promotion/model/CouponType.java
View file @
9dd79dc
...
...
@@ -5,6 +5,17 @@ public class CouponType {
private
String
caption
;
private
String
alphabet
;
public
String
getAlphabet
()
{
return
alphabet
;
}
public
void
setAlphabet
(
String
alphabet
)
{
this
.
alphabet
=
alphabet
;
}
public
Integer
getId
()
{
return
id
;
}
...
...
dal/src/main/java/com/yohoufo/dal/promotion/model/UserCoupon.java
View file @
9dd79dc
...
...
@@ -7,7 +7,7 @@ public class UserCoupon {
private
Integer
couponId
;
private
Byte
couponType
;
private
Integer
couponType
;
private
String
couponCode
;
...
...
@@ -23,6 +23,16 @@ public class UserCoupon {
private
Integer
createTime
;
private
String
couponToken
;
public
String
getCouponToken
()
{
return
couponToken
;
}
public
void
setCouponToken
(
String
couponToken
)
{
this
.
couponToken
=
couponToken
;
}
public
Integer
getId
()
{
return
id
;
}
...
...
@@ -47,11 +57,11 @@ public class UserCoupon {
this
.
couponId
=
couponId
;
}
public
Byte
getCouponType
()
{
public
Integer
getCouponType
()
{
return
couponType
;
}
public
void
setCouponType
(
Byte
couponType
)
{
public
void
setCouponType
(
Integer
couponType
)
{
this
.
couponType
=
couponType
;
}
...
...
dal/src/main/resources/META-INF/mybatis/promotion/CouponMapper.xml
View file @
9dd79dc
...
...
@@ -6,7 +6,7 @@
<result
column=
"coupon_token"
jdbcType=
"VARCHAR"
property=
"couponToken"
/>
<result
column=
"coupon_name"
jdbcType=
"VARCHAR"
property=
"couponName"
/>
<result
column=
"coupon_amount"
jdbcType=
"DECIMAL"
property=
"couponAmount"
/>
<result
column=
"coupon_type"
jdbcType=
"TINYINT
"
property=
"couponType"
/>
<result
column=
"coupon_type"
jdbcType=
"INTEGER
"
property=
"couponType"
/>
<result
column=
"coupon_num"
jdbcType=
"INTEGER"
property=
"couponNum"
/>
<result
column=
"use_num"
jdbcType=
"SMALLINT"
property=
"useNum"
/>
<result
column=
"send_num"
jdbcType=
"INTEGER"
property=
"sendNum"
/>
...
...
@@ -33,7 +33,15 @@
where id = #{id,jdbcType=INTEGER}
</select>
<select
id=
"selectByIds"
parameterType=
"java.lang.Integer"
resultMap=
"BaseResultMap"
>
<select
id=
"selectByCouponToken"
parameterType=
"java.lang.String"
resultMap=
"BaseResultMap"
>
select
<include
refid=
"Base_Column_List"
/>
from coupon
where coupon_token = #{couponToken,jdbcType=VARCHAR}
</select>
<select
id=
"selectByCouponIds"
parameterType=
"java.lang.Integer"
resultMap=
"BaseResultMap"
>
select
<include
refid=
"Base_Column_List"
/>
from coupon
...
...
@@ -45,6 +53,18 @@
</foreach>
</select>
<select
id=
"selectByCouponTokens"
parameterType=
"java.lang.String"
resultMap=
"BaseResultMap"
>
select
<include
refid=
"Base_Column_List"
/>
from coupon
where 1=1
AND coupon_token IN
<foreach
item=
"token"
index=
"index"
collection=
"list"
open=
"("
separator=
","
close=
")"
>
#{id}
</foreach>
</select>
<delete
id=
"deleteByPrimaryKey"
parameterType=
"java.lang.Integer"
>
delete from coupon
where id = #{id,jdbcType=INTEGER}
...
...
dal/src/main/resources/META-INF/mybatis/promotion/CouponTypeMapper.xml
View file @
9dd79dc
...
...
@@ -4,9 +4,10 @@
<resultMap
id=
"BaseResultMap"
type=
"com.yohoufo.dal.promotion.model.CouponType"
>
<id
column=
"id"
property=
"id"
jdbcType=
"INTEGER"
/>
<result
column=
"caption"
property=
"caption"
jdbcType=
"VARCHAR"
/>
<result
column=
"alphabet"
property=
"alphabet"
jdbcType=
"VARCHAR"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
id, caption
id, caption
, alphabet
</sql>
<select
id=
"selectByPrimaryKey"
resultMap=
"BaseResultMap"
parameterType=
"java.lang.Integer"
>
select
...
...
dal/src/main/resources/META-INF/mybatis/promotion/UserCouponMapper.xml
View file @
9dd79dc
...
...
@@ -5,7 +5,8 @@
<id
column=
"id"
property=
"id"
jdbcType=
"INTEGER"
/>
<result
column=
"uid"
property=
"uid"
jdbcType=
"INTEGER"
/>
<result
column=
"coupon_id"
property=
"couponId"
jdbcType=
"INTEGER"
/>
<result
column=
"coupon_type"
property=
"couponType"
jdbcType=
"TINYINT"
/>
<result
column=
"coupon_token"
property=
"couponToken"
jdbcType=
"VARCHAR"
/>
<result
column=
"coupon_type"
property=
"couponType"
jdbcType=
"INTEGER"
/>
<result
column=
"coupon_code"
property=
"couponCode"
jdbcType=
"VARCHAR"
/>
<result
column=
"status"
property=
"status"
jdbcType=
"TINYINT"
/>
<result
column=
"order_code"
property=
"orderCode"
jdbcType=
"BIGINT"
/>
...
...
@@ -16,7 +17,7 @@
</resultMap>
<sql
id=
"Base_Column_List"
>
id, uid, coupon_id, coupon_type, coupon_code, status, order_code, use_time, start_time,
end_time, create_time
end_time, create_time
, coupon_token
</sql>
<select
id=
"selectByPrimaryKey"
resultMap=
"BaseResultMap"
parameterType=
"java.lang.Integer"
>
...
...
@@ -27,16 +28,39 @@
</select>
<select
id=
"selectByUidAndToken"
resultMap=
"BaseResultMap"
>
select
<include
refid=
"Base_Column_List"
/>
from user_coupon
where uid = #{uid,jdbcType=INTEGER}
and coupon_token = #{couponToken,jdbcType=VARCHAR}
limit 1
</select>
<select
id=
"selectUsableCouponByUid"
resultMap=
"BaseResultMap"
parameterType=
"java.lang.Integer"
>
select
<include
refid=
"Base_Column_List"
/>
from user_coupon
where uid = #{uid,jdbcType=INTEGER}
<include
refid=
"CouponsLogsQueryUsable"
/>
</select>
<sql
id=
"CouponsLogsQueryUsable"
>
<!-- 在有效时间范围内 -->
and
<![CDATA[ start_time > #{now, jdbcType=INTEGER} ]]>
and
<![CDATA[ end_time < #{now, jdbcType=INTEGER} ]]>
<!-- 未使用-->
and status = 0
</sql>
<select
id=
"selectCntUsableCouponByUid"
resultType=
"int"
parameterType=
"java.lang.Integer"
>
select
count(1)
from user_coupon
where uid = #{uid,jdbcType=INTEGER}
<include
refid=
"CouponsLogsQueryUsable"
/>
</select>
...
...
@@ -57,7 +81,7 @@
order_code, use_time, start_time,
end_time, create_time)
values (#{id,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER}, #{couponId,jdbcType=INTEGER},
#{couponType,jdbcType=
TINYINT}, #{couponCode,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT},
#{couponType,jdbcType=
INTEGER}, #{couponCode,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT},
#{orderCode,jdbcType=BIGINT}, #{useTime,jdbcType=INTEGER}, #{startTime,jdbcType=INTEGER},
#{endTime,jdbcType=INTEGER}, #{createTime,jdbcType=INTEGER})
</insert>
...
...
promotion/src/main/java/com/yohoufo/promotion/cache/ExpiredTime.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
cache
;
public
interface
ExpiredTime
{
/**
* coupons ---缓存时间
*/
int
COUPON_CACHE_TIME
=
300
;
/**
* coupons_type ---缓存时间
*/
int
COUPON_TYPE_CACHE_TIME
=
3600
;
}
...
...
promotion/src/main/java/com/yohoufo/promotion/cache/KeyBuilder.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
cache
;
import
com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder
;
public
class
KeyBuilder
{
public
static
RedisKeyBuilder
buildCouponCacheKey
(
String
couponToken
)
{
return
RedisKeyBuilder
.
newInstance
().
appendFixed
(
"ufo:promotion:coupons:couponToken:"
).
appendVar
(
couponToken
);
}
public
static
RedisKeyBuilder
buildCouponTypeCacheKey
(
int
id
)
{
return
RedisKeyBuilder
.
newInstance
().
appendFixed
(
"ufo:promotion:coupontype:id:"
).
appendVar
(
id
);
}
/**
* 服务节点 (此key不可以修改为非同步缓存)
*/
public
static
RedisKeyBuilder
promotionServerNode
()
{
return
RedisKeyBuilder
.
newInstance
().
appendFixed
(
"ufo:promotion:coupons:serverNode"
);
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/common/CouponsStatusEnum.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
common
;
/**
* 描述:券状态
* Created by pangjie@yoho.cn on 2016/5/24.
*/
public
enum
CouponsStatusEnum
{
//ERP中老的状态为: 0:未启用 1:启用 3:作废
/**
待审核:通过、驳回、查看详情
通过:查看详情、作废
驳回:修改
作废:查看详情
*/
/**
* 新建之后是待审核
*/
NEED_REVIEW
(
0
,
"待审核"
),
/**
* 审核通过之后是有效的(对应原来的启用状态)
*/
VALID
(
1
,
"有效"
),
/**
* 审核通过之后可作废
*/
INVALID
(
3
,
"作废"
),
/**
* 审批未通过的是驳回状态,驳回状态可编辑,编辑之后变成待审核
*/
REJECT
(
2
,
"审核驳回"
);
/**
* 编码
*/
private
int
code
;
/**
* 描述
*/
private
String
desc
;
/**
* 操作列表
*
* @param code
* @param desc
* @return
*/
CouponsStatusEnum
(
int
code
,
String
desc
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
}
public
int
getCode
()
{
return
code
;
}
public
String
getDesc
()
{
return
desc
;
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/common/ProductLimitType.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
common
;
public
enum
ProductLimitType
{
PRODUCT
(
1
,
"特定商品"
,
"限特定商品"
);
int
code
;
String
desc
;
/**
* 显示给前端的文案
*/
String
text
;
ProductLimitType
(
int
code
,
String
desc
,
String
text
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
this
.
text
=
text
;
}
public
int
getCode
()
{
return
code
;
}
public
String
getText
()
{
return
text
;
}
}
\ No newline at end of file
...
...
promotion/src/main/java/com/yohoufo/promotion/common/UseLimitType.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
common
;
public
enum
UseLimitType
{
NO_LIMIT
(
0
,
"无限制"
,
""
),
AMOUNT_LIMIT
(
1
,
"金额"
,
"满{0}可用"
);
int
code
;
String
desc
;
/**
* 给前端的显示文案
*/
String
text
;
UseLimitType
(
int
code
,
String
desc
,
String
text
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
this
.
text
=
text
;
}
public
String
getText
()
{
return
text
;
}
public
int
getCode
()
{
return
code
;
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/controller/CouponController.java
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
controller
;
import
com.yohoufo.common.ApiResponse
;
import
com.yohoufo.promotion.model.response.CouponInfo
;
import
com.yohoufo.promotion.model.response.CouponInfoListBO
;
import
com.yohoufo.promotion.service.ICouponService
;
import
org.slf4j.Logger
;
...
...
@@ -11,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestParam;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
@RestController
@RequestMapping
(
value
=
"/coupon"
)
public
class
CouponController
{
...
...
@@ -29,9 +32,9 @@ public class CouponController {
@ResponseBody
public
ApiResponse
queryCouponList
(
@RequestParam
(
value
=
"uid"
)
Integer
uid
)
{
logger
.
info
(
"query user coupons, uid: {}"
,
uid
);
CouponInfoListBO
couponInfoListBo
=
couponService
.
queryCouponList
(
uid
);
logger
.
info
(
"query user coupons uid: {}, response: {}"
,
uid
,
couponInfoListBo
);
logger
.
info
(
"query user coupons list, uid: {}"
,
uid
);
List
<
CouponInfo
>
couponInfoListBo
=
couponService
.
queryCouponList
(
uid
);
logger
.
info
(
"query user coupons list uid: {}, response: {}"
,
uid
,
couponInfoListBo
);
return
new
ApiResponse
.
ApiResponseBuilder
().
code
(
200
).
data
(
couponInfoListBo
).
build
();
}
...
...
@@ -45,9 +48,26 @@ public class CouponController {
@ResponseBody
public
ApiResponse
queryCouponCnt
(
@RequestParam
(
value
=
"uid"
)
Integer
uid
)
{
logger
.
info
(
"query user coupons, uid: {}"
,
uid
);
logger
.
info
(
"query user coupons
cnt
, uid: {}"
,
uid
);
int
couponCnt
=
couponService
.
queryCouponCnt
(
uid
);
logger
.
info
(
"query user coupons
uid: {}, response
: {}"
,
uid
,
couponCnt
);
logger
.
info
(
"query user coupons
cnt uid: {}, v
: {}"
,
uid
,
couponCnt
);
return
new
ApiResponse
.
ApiResponseBuilder
().
code
(
200
).
data
(
couponCnt
).
build
();
}
/**
* 领券接口
* @param uid
* @return
*/
@RequestMapping
(
params
=
"method=app.coupons.send"
)
@ResponseBody
public
ApiResponse
sendCoupon
(
@RequestParam
(
value
=
"uid"
)
Integer
uid
,
@RequestParam
(
value
=
"coupon_token"
)
String
couponToken
)
{
logger
.
info
(
"send coupons enter, uid: {}"
,
uid
);
String
couponCode
=
couponService
.
senCoupon
(
uid
,
couponToken
);
logger
.
info
(
"send coupons success uid: {}, couponCode: {}"
,
uid
,
couponCode
);
return
new
ApiResponse
.
ApiResponseBuilder
().
code
(
200
).
data
(
couponCode
).
build
();
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/convert/CouponConvert.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
convert
;
import
com.yohoufo.common.utils.DateUtil
;
import
com.yohoufo.dal.promotion.model.Coupon
;
import
com.yohoufo.dal.promotion.model.CouponAndType
;
import
com.yohoufo.dal.promotion.model.CouponType
;
import
com.yohoufo.dal.promotion.model.UserCoupon
;
import
com.yohoufo.promotion.common.ProductLimitType
;
import
com.yohoufo.promotion.common.UseLimitType
;
import
com.yohoufo.promotion.model.response.CouponInfo
;
import
java.text.MessageFormat
;
import
java.util.Arrays
;
public
class
CouponConvert
{
/**
* 用户优惠券信息
* @param userCoupon 用户优惠券
* @param coupon 优惠券
* @param couponType 优惠券类型
* @return
*/
public
static
CouponInfo
convertCouponInfo
(
UserCoupon
userCoupon
,
Coupon
coupon
,
CouponType
couponType
)
{
CouponInfo
couponInfo
=
new
CouponInfo
();
couponInfo
.
setCoupon_code
(
userCoupon
.
getCouponCode
());
StringBuilder
coupon_validity
=
new
StringBuilder
();
coupon_validity
.
append
(
DateUtil
.
getDateFormat
(
userCoupon
.
getStartTime
()));
coupon_validity
.
append
(
"-"
);
coupon_validity
.
append
(
DateUtil
.
getDateFormat
(
userCoupon
.
getEndTime
()));
couponInfo
.
setCoupon_validity
(
coupon_validity
.
toString
());
// 优惠券信息
if
(
coupon
!=
null
){
couponInfo
.
setCoupon_name
(
coupon
.
getCouponName
());
couponInfo
.
setCoupon_token
(
coupon
.
getCouponToken
());
couponInfo
.
setCoupon_value
(
coupon
.
getCouponAmount
());
// use_limit_type use_limit_value 满多少元可用
if
(
coupon
.
getUseLimitType
()!=
null
&&
coupon
.
getUseLimitType
().
intValue
()
==
UseLimitType
.
AMOUNT_LIMIT
.
getCode
()){
couponInfo
.
setUse_rule
(
MessageFormat
.
format
(
UseLimitType
.
AMOUNT_LIMIT
.
getText
(),
coupon
.
getUseLimitValue
().
intValue
()));
}
// product_limit_type product_limit_value 特定商品
if
(
coupon
.
getProductLimitType
()!=
null
&&
coupon
.
getProductLimitType
().
intValue
()
==
ProductLimitType
.
PRODUCT
.
getCode
()){
couponInfo
.
setNotes
(
Arrays
.
asList
(
ProductLimitType
.
PRODUCT
.
getText
()));
}
}
// 优惠券类型信息
if
(
couponType
!=
null
){
couponInfo
.
setCoupon_type
(
couponType
.
getId
());
couponInfo
.
setCoupon_type_name
(
couponType
.
getCaption
());
}
return
couponInfo
;
}
/**
* 领取优惠券时构造信息
* @param uid
* @param couponAndType
* @param couponCode
* @return
*/
public
static
UserCoupon
convertUserCoupon
(
Integer
uid
,
String
couponCode
,
CouponAndType
couponAndType
)
{
UserCoupon
userCoupon
=
new
UserCoupon
();
userCoupon
.
setUid
(
uid
);
userCoupon
.
setCouponId
(
couponAndType
.
getCoupon
().
getId
());
userCoupon
.
setCouponType
(
couponAndType
.
getCouponType
().
getId
());
userCoupon
.
setCouponCode
(
couponCode
);
int
now
=
DateUtil
.
getCurrentTimeSecond
();
userCoupon
.
setStartTime
(
now
);
// TODO
userCoupon
.
setEndTime
(
couponAndType
.
getCoupon
().
getEndTime
());
userCoupon
.
setCreateTime
(
now
);
userCoupon
.
setCouponToken
(
couponAndType
.
getCoupon
().
getCouponToken
());
return
userCoupon
;
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/model/response/CouponInfo.java
View file @
9dd79dc
...
...
@@ -16,8 +16,6 @@ public class CouponInfo {
private
BigDecimal
coupon_value
;
private
String
coupon_value_str
;
private
String
use_rule
;
private
String
coupon_validity
;
...
...
promotion/src/main/java/com/yohoufo/promotion/service/CouponCodeGenerate.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
;
/**
* 描述:券号生成服务
* Created by pangjie@yoho.cn on 2016/5/14.
*/
public
interface
CouponCodeGenerate
{
/**
* 获取券号
*
* @return
*/
String
getCode
();
}
...
...
promotion/src/main/java/com/yohoufo/promotion/service/CouponServiceImpl.java
deleted
100644 → 0
View file @
0c5daaf
package
com
.
yohoufo
.
promotion
.
service
;
import
com.google.common.collect.Lists
;
import
com.yohoufo.common.utils.DateUtil
;
import
com.yohoufo.dal.promotion.CouponMapper
;
import
com.yohoufo.dal.promotion.CouponTypeMapper
;
import
com.yohoufo.dal.promotion.UserCouponMapper
;
import
com.yohoufo.dal.promotion.model.Coupon
;
import
com.yohoufo.dal.promotion.model.CouponType
;
import
com.yohoufo.dal.promotion.model.UserCoupon
;
import
com.yohoufo.promotion.model.response.CouponInfoListBO
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
@Service
public
class
CouponServiceImpl
implements
ICouponService
{
@Autowired
UserCouponMapper
userCouponMapper
;
@Autowired
CouponMapper
couponMapper
;
@Autowired
CouponTypeMapper
couponTypeMapper
;
@Override
public
CouponInfoListBO
queryCouponList
(
Integer
uid
)
{
// 获取未使用未过期的优惠券
List
<
UserCoupon
>
list
=
userCouponMapper
.
selectUsableCouponByUid
(
uid
,
DateUtil
.
getCurrentTimeSecond
());
if
(
CollectionUtils
.
isEmpty
(
list
)){
return
CouponInfoListBO
.
builder
().
build
();
}
// 获取 coupon
List
<
Integer
>
couponIdList
=
list
.
stream
().
map
(
UserCoupon:
:
getCouponId
).
collect
(
Collectors
.
toList
());
List
<
Coupon
>
couponList
=
couponMapper
.
selectByIds
(
couponIdList
);
Map
<
Integer
,
Coupon
>
couponMap
=
couponList
.
stream
().
collect
(
Collectors
.
toMap
(
Coupon:
:
getId
,
Function
.
identity
()));
// 获取 couponTyoe
List
<
Integer
>
couponTypeIdList
=
list
.
stream
().
map
(
UserCoupon:
:
getCouponType
).
map
(
Byte:
:
intValue
).
collect
(
Collectors
.
toList
());
List
<
CouponType
>
couponTypeList
=
couponTypeMapper
.
selectByIds
(
couponTypeIdList
);
Map
<
Integer
,
CouponType
>
couponTypeMap
=
couponTypeList
.
stream
().
collect
(
Collectors
.
toMap
(
CouponType:
:
getId
,
Function
.
identity
()));
return
null
;
}
@Override
public
int
queryCouponCnt
(
Integer
uid
)
{
return
0
;
}
}
promotion/src/main/java/com/yohoufo/promotion/service/ICouponCacheService.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
;
import
com.yohoufo.dal.promotion.model.Coupon
;
import
com.yohoufo.dal.promotion.model.CouponAndType
;
import
com.yohoufo.dal.promotion.model.CouponType
;
import
java.util.List
;
public
interface
ICouponCacheService
{
public
CouponType
getCouponTypeWithCache
(
Integer
id
);
public
List
<
Coupon
>
getCouponsWithCache
(
List
<
String
>
couponTokenList
);
/**
* 根据couponToken获取优惠券模板和类型
* @param couponToken
* @return
*/
public
CouponAndType
getCouponAndType
(
String
couponToken
);
}
...
...
promotion/src/main/java/com/yohoufo/promotion/service/ICouponService.java
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
;
import
com.yohoufo.promotion.model.response.CouponInfo
;
import
com.yohoufo.promotion.model.response.CouponInfoListBO
;
import
java.util.List
;
public
interface
ICouponService
{
public
CouponInfoListBO
queryCouponList
(
Integer
uid
);
public
List
<
CouponInfo
>
queryCouponList
(
Integer
uid
);
public
int
queryCouponCnt
(
Integer
uid
);
/**
* 领取优惠券
* @param uid
* @param couponToken
* @return
*/
public
String
senCoupon
(
Integer
uid
,
String
couponToken
);
}
...
...
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponCacheServiceImpl.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
.
impl
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder
;
import
com.yohoufo.common.cache.CacheClient
;
import
com.yohoufo.dal.promotion.CouponMapper
;
import
com.yohoufo.dal.promotion.CouponTypeMapper
;
import
com.yohoufo.dal.promotion.model.Coupon
;
import
com.yohoufo.dal.promotion.model.CouponAndType
;
import
com.yohoufo.dal.promotion.model.CouponType
;
import
com.yohoufo.promotion.cache.ExpiredTime
;
import
com.yohoufo.promotion.cache.KeyBuilder
;
import
com.yohoufo.promotion.service.ICouponCacheService
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.collections.MapUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
@Service
public
class
CouponCacheServiceImpl
implements
ICouponCacheService
{
@Autowired
CouponMapper
couponMapper
;
@Autowired
CouponTypeMapper
couponTypeMapper
;
@Autowired
private
CacheClient
cacheClient
;
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
/**
* 获取couponType
* @param id
* @return
*/
public
CouponType
getCouponTypeWithCache
(
Integer
id
){
if
(
id
==
null
){
return
null
;
}
CouponType
couponType
=
cacheClient
.
get
(
KeyBuilder
.
buildCouponTypeCacheKey
(
id
),
CouponType
.
class
);
if
(
couponType
==
null
)
{
couponType
=
couponTypeMapper
.
selectByPrimaryKey
(
id
);
if
(
couponType
!=
null
)
{
cacheClient
.
setEx
(
KeyBuilder
.
buildCouponTypeCacheKey
(
id
),
couponType
,
ExpiredTime
.
COUPON_TYPE_CACHE_TIME
);
}
}
return
couponType
;
}
/**
* 根据couponToken获取优惠券模板和类型
* @param couponToken
* @return
*/
public
CouponAndType
getCouponAndType
(
String
couponToken
){
Coupon
coupon
=
getCouponWithCache
(
couponToken
);
if
(
coupon
==
null
){
logger
.
warn
(
"getCouponAndType coupon not exist. couponToken is {}"
,
couponToken
);
return
null
;
}
CouponType
couponType
=
getCouponTypeWithCache
(
coupon
.
getCouponType
());
if
(
couponType
==
null
){
logger
.
warn
(
"getCouponAndType coupon not exist. couponToken is {}, couponType is {}"
,
couponToken
,
coupon
.
getCouponType
());
return
null
;
}
return
CouponAndType
.
builder
().
coupon
(
coupon
).
couponType
(
couponType
).
build
();
}
/**
* 获取coupon
* @param couponToken
* @return
*/
public
Coupon
getCouponWithCache
(
String
couponToken
){
Coupon
coupon
=
cacheClient
.
get
(
KeyBuilder
.
buildCouponCacheKey
(
couponToken
),
Coupon
.
class
);
if
(
coupon
!=
null
){
return
coupon
;
}
coupon
=
couponMapper
.
selectByCouponToken
(
couponToken
);
if
(
coupon
==
null
)
{
return
null
;
}
cacheClient
.
setEx
(
KeyBuilder
.
buildCouponCacheKey
(
couponToken
),
coupon
,
ExpiredTime
.
COUPON_CACHE_TIME
);
return
coupon
;
}
/**
* 批量获取coupon
* @param couponTokenList
* @return
*/
public
List
<
Coupon
>
getCouponsWithCache
(
List
<
String
>
couponTokenList
)
{
//构造缓存key对象
List
<
RedisKeyBuilder
>
coupCacheKeys
=
couponTokenList
.
stream
().
map
(
KeyBuilder:
:
buildCouponCacheKey
).
collect
(
Collectors
.
toList
());
Map
<
String
,
Coupon
>
couponsMap
=
cacheClient
.
mget
(
coupCacheKeys
,
Coupon
.
class
);
if
(
MapUtils
.
isEmpty
(
couponsMap
))
{
logger
.
warn
(
"query coupon rule info is empty:{}"
,
couponTokenList
);
return
Lists
.
newArrayList
();
}
List
<
String
>
missCouponsTokens
=
Lists
.
newArrayList
();
List
<
Coupon
>
couponses
=
Lists
.
newArrayList
();
for
(
Map
.
Entry
<
String
,
Coupon
>
entry
:
couponsMap
.
entrySet
())
{
if
(
entry
.
getValue
()
==
null
)
{
String
key
=
entry
.
getKey
();
missCouponsTokens
.
add
(
key
.
substring
(
key
.
lastIndexOf
(
":"
)
+
1
));
}
else
{
couponses
.
add
(
entry
.
getValue
());
}
}
if
(
CollectionUtils
.
isEmpty
(
missCouponsTokens
))
{
return
couponses
;
}
List
<
Coupon
>
dbCouponses
=
couponMapper
.
selectByCouponTokens
(
missCouponsTokens
);
if
(
CollectionUtils
.
isEmpty
(
dbCouponses
))
{
return
couponses
;
}
for
(
Coupon
coupons
:
dbCouponses
)
{
couponses
.
add
(
coupons
);
}
setCoupons2Cache
(
dbCouponses
);
return
couponses
;
}
/**
* 设置券缓存
*
* @param couponses
*/
private
void
setCoupons2Cache
(
List
<
Coupon
>
couponses
)
{
if
(
CollectionUtils
.
isEmpty
(
couponses
))
{
return
;
}
//设置缓存异常不影响正常流程
try
{
Map
<
RedisKeyBuilder
,
Coupon
>
map
=
Maps
.
newHashMap
();
couponses
.
forEach
(
c
->
map
.
put
(
KeyBuilder
.
buildCouponCacheKey
(
c
.
getCouponToken
()),
c
));
cacheClient
.
mset
(
map
,
ExpiredTime
.
COUPON_CACHE_TIME
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"set couponses cache error:{}"
,
e
.
getMessage
());
}
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponCodeGenerateImpl.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
.
impl
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.Lists
;
import
com.yoho.core.common.utils.LocalIp
;
import
com.yoho.core.redis.cluster.annotation.Redis
;
import
com.yoho.core.redis.cluster.operations.nosync.YHValueOperations
;
import
com.yohoufo.promotion.cache.KeyBuilder
;
import
com.yohoufo.promotion.service.CouponCodeGenerate
;
import
org.apache.commons.lang3.math.NumberUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.context.annotation.Lazy
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.PostConstruct
;
import
java.security.SecureRandom
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
/**
* 描述:券号生成服务
* Created by pangjie@yoho.cn on 2016/5/16.
*/
@Service
(
"couponCodeGenerate"
)
@Lazy
(
false
)
public
class
CouponCodeGenerateImpl
implements
CouponCodeGenerate
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
CouponCodeGenerateImpl
.
class
);
private
static
final
List
<
String
>
NODES
=
Lists
.
newArrayList
(
"0"
,
"1"
,
"2"
,
"3"
,
"4"
,
"5"
,
"6"
,
"7"
,
"8"
,
"9"
,
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
,
"j"
,
"k"
,
"l"
,
"m"
,
"n"
,
"o"
,
"p"
,
"q"
,
"r"
,
"s"
,
"t"
,
"u"
,
"v"
,
"w"
,
"x"
,
"y"
,
"z"
);
private
static
final
char
[]
HEX_CHARS
=
new
char
[]{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
private
static
final
AtomicInteger
NEXT_COUNTER
=
new
AtomicInteger
((
new
SecureRandom
()).
nextInt
());
private
static
final
int
RADIX_36
=
36
;
@Redis
(
"yohoNoSyncRedis"
)
private
YHValueOperations
valueOperations
;
/**
* 标示机器节点
*/
private
String
node
;
public
static
String
toHexString
(
byte
[]
bytes
)
{
char
[]
chars
=
new
char
[
bytes
.
length
*
2
];
int
i
=
0
;
int
var4
=
bytes
.
length
;
for
(
int
var5
=
0
;
var5
<
var4
;
++
var5
)
{
byte
b
=
bytes
[
var5
];
chars
[
i
++]
=
HEX_CHARS
[
b
>>
4
&
15
];
chars
[
i
++]
=
HEX_CHARS
[
b
&
15
];
}
return
new
String
(
chars
);
}
private
static
int
dateToTimestampSeconds
(
Date
time
)
{
return
(
int
)
(
time
.
getTime
()
/
1000L
);
}
/**
* 初始化标示节点,用redis的一个自增值+ip地址
*/
@PostConstruct
public
void
init
()
{
while
(
true
)
{
try
{
Long
test
=
valueOperations
.
increment
(
KeyBuilder
.
promotionServerNode
(),
1
);
long
position
=
test
%
NODES
.
size
();
String
localIp
=
LocalIp
.
getLocalIp
();
String
ipLast
=
localIp
.
substring
(
localIp
.
lastIndexOf
(
"."
)+
1
);
node
=
NODES
.
get
((
int
)
position
)+
Strings
.
padStart
(
Integer
.
toString
(
NumberUtils
.
toInt
(
ipLast
),
RADIX_36
),
2
,
'0'
);
return
;
}
catch
(
Exception
e
)
{
logger
.
error
(
"acquire node exception:{}"
,
e
);
}
}
}
@Override
public
String
getCode
()
{
int
timestamp
=
dateToTimestampSeconds
(
new
Date
());
int
counter
=
NEXT_COUNTER
.
getAndIncrement
()
&
1048575
;
//时间戳(当前时间到2038-12-24都是6位)+节点+自增(1048575,36进制为4位转换为定长4位)
return
Integer
.
toString
(
timestamp
,
RADIX_36
)
+
node
+
Strings
.
padStart
(
Integer
.
toString
(
counter
,
RADIX_36
),
4
,
'0'
);
}
}
...
...
promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponServiceImpl.java
0 → 100644
View file @
9dd79dc
package
com
.
yohoufo
.
promotion
.
service
.
impl
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder
;
import
com.yoho.error.ServiceError
;
import
com.yoho.error.exception.ServiceException
;
import
com.yohoufo.common.cache.CacheClient
;
import
com.yohoufo.common.utils.DateUtil
;
import
com.yohoufo.dal.promotion.CouponMapper
;
import
com.yohoufo.dal.promotion.CouponTypeMapper
;
import
com.yohoufo.dal.promotion.UserCouponMapper
;
import
com.yohoufo.dal.promotion.model.Coupon
;
import
com.yohoufo.dal.promotion.model.CouponAndType
;
import
com.yohoufo.dal.promotion.model.CouponType
;
import
com.yohoufo.dal.promotion.model.UserCoupon
;
import
com.yohoufo.promotion.cache.ExpiredTime
;
import
com.yohoufo.promotion.cache.KeyBuilder
;
import
com.yohoufo.promotion.common.CouponsStatusEnum
;
import
com.yohoufo.promotion.common.ProductLimitType
;
import
com.yohoufo.promotion.common.UseLimitType
;
import
com.yohoufo.promotion.convert.CouponConvert
;
import
com.yohoufo.promotion.model.response.CouponInfo
;
import
com.yohoufo.promotion.model.response.CouponInfoListBO
;
import
com.yohoufo.promotion.service.CouponCodeGenerate
;
import
com.yohoufo.promotion.service.ICouponCacheService
;
import
com.yohoufo.promotion.service.ICouponService
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.collections.MapUtils
;
import
org.apache.commons.lang.math.NumberUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.text.MessageFormat
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
@Service
public
class
CouponServiceImpl
implements
ICouponService
{
@Autowired
UserCouponMapper
userCouponMapper
;
@Autowired
ICouponCacheService
couponCacheService
;
@Autowired
CouponCodeGenerate
couponCodeGenerate
;
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
/**
* 领取优惠券
* @param uid
* @param couponToken
* @return
*/
public
String
senCoupon
(
Integer
uid
,
String
couponToken
){
// 根据 couponToken 获取coupon&couponType信息
CouponAndType
couponAndType
=
couponCacheService
.
getCouponAndType
(
couponToken
);
if
(
couponAndType
==
null
){
logger
.
warn
(
"query coupon info,coupontype is null:{}"
,
couponToken
);
throw
new
ServiceException
(
ServiceError
.
PROMOTION_COUPON_HAS_NOT_EXISTS
);
}
// 校验是否可以领取(重复领取,时间是否合法,状态)
checkCanAcquire
(
uid
,
couponToken
,
couponAndType
);
// 校验 优惠券发放总数
String
couponCode
=
couponAndType
.
getCouponType
().
getAlphabet
()
+
couponCodeGenerate
.
getCode
();
// 发送优惠券
UserCoupon
userCoupon
=
CouponConvert
.
convertUserCoupon
(
uid
,
couponCode
,
couponAndType
);
int
count
=
userCouponMapper
.
insert
(
userCoupon
);
// 插入失败
if
(
count
!=
1
){
logger
.
info
(
"senCoupon failed,{},{},{}"
,
uid
,
couponToken
,
couponCode
);
return
null
;
}
logger
.
info
(
"senCoupon success,{},{},{}"
,
uid
,
couponToken
,
couponCode
);
// TODO 清理缓存
return
couponCode
;
}
private
void
checkCanAcquire
(
Integer
uid
,
String
couponToken
,
CouponAndType
couponAndType
)
{
// 验证该用户是否重复领取
UserCoupon
userCoupon
=
userCouponMapper
.
selectByUidAndToken
(
uid
,
couponToken
);
if
(
userCoupon
!=
null
){
logger
.
warn
(
"user has acquried this coupon before:{},{}"
,
uid
,
couponToken
);
throw
new
ServiceException
(
ServiceError
.
PROMOTION_COUPON_HAS_RECEIVED
);
}
// 验证优惠券的领取时间(开始时间没到,结束时间已过,状态不对)
int
now
=
DateUtil
.
getCurrentTimeSecond
();
if
(
couponAndType
.
getCoupon
().
getStartTime
()
>
now
){
logger
.
info
(
"couponrulebo not arrive get start time:{},{}"
,
uid
,
couponToken
);
throw
new
ServiceException
(
ServiceError
.
PROMOTION_COUPON_NOT_ARRIVE_GET_START_TIME
);
}
if
(
couponAndType
.
getCoupon
().
getEndTime
()
>
now
){
logger
.
info
(
"couponrulebo is expired:{},{}"
,
uid
,
couponToken
);
throw
new
ServiceException
(
ServiceError
.
PROMOTION_COUPON_TIME_OUT_CAN_NOT_GET
);
}
if
(
couponAndType
.
getCoupon
().
getStatus
()
!=
CouponsStatusEnum
.
VALID
.
getCode
()){
logger
.
info
(
"couponrulebo status is not valid:{},{}"
,
uid
,
couponToken
);
throw
new
ServiceException
(
ServiceError
.
PROMOTION_COUPON_IS_NOT_VAILD
);
}
}
@Override
public
List
<
CouponInfo
>
queryCouponList
(
Integer
uid
)
{
// 获取未使用未过期的优惠券
List
<
UserCoupon
>
list
=
userCouponMapper
.
selectUsableCouponByUid
(
uid
,
DateUtil
.
getCurrentTimeSecond
());
if
(
CollectionUtils
.
isEmpty
(
list
)){
return
Lists
.
newArrayList
();
}
// 批量获取coupon
List
<
String
>
couponIdList
=
list
.
stream
().
map
(
UserCoupon:
:
getCouponToken
).
collect
(
Collectors
.
toList
());
List
<
Coupon
>
couponList
=
couponCacheService
.
getCouponsWithCache
(
couponIdList
);
Map
<
Integer
,
Coupon
>
couponMap
=
couponList
.
stream
().
collect
(
Collectors
.
toMap
(
Coupon:
:
getId
,
Function
.
identity
()));
List
<
CouponInfo
>
couponInfoList
=
list
.
stream
().
map
(
userCoupon
->
{
Coupon
coupon
=
couponMap
.
get
(
userCoupon
.
getCouponId
());
// 单个获取couponType
CouponType
couponType
=
couponCacheService
.
getCouponTypeWithCache
(
userCoupon
.
getCouponType
()!=
null
?
userCoupon
.
getCouponType
().
intValue
()
:
null
);
CouponInfo
couponInfo
=
CouponConvert
.
convertCouponInfo
(
userCoupon
,
coupon
,
couponType
);
return
couponInfo
;
}).
collect
(
Collectors
.
toList
());
return
couponInfoList
;
}
@Override
public
int
queryCouponCnt
(
Integer
uid
)
{
int
cnt
=
userCouponMapper
.
selectCntUsableCouponByUid
(
uid
,
DateUtil
.
getCurrentTimeSecond
());
return
cnt
;
}
}
...
...
Please
register
or
login
to post a comment