Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
order-group
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
order-group-application
order-group
Commits
3175c831
Commit
3175c831
authored
Sep 29, 2020
by
刘鹏飞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
拼单购物车方法判断修改
parent
df54eac0
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
106 additions
and
58 deletions
+106
-58
assortment-shoppingcart-sdk/src/main/java/com/freemud/sdk/api/assortment/shoppingcart/service/impl/CollageCartBaseServiceImpl.java
+76
-20
shopping-cart-application-service/src/main/java/cn/freemud/controller/ShoppingCartCollageController.java
+7
-10
shopping-cart-application-service/src/main/java/cn/freemud/factory/AbstractShoppingCartImpl.java
+1
-4
shopping-cart-application-service/src/main/java/cn/freemud/service/ShoppingCartCollageService.java
+8
-3
shopping-cart-application-service/src/main/java/cn/freemud/service/impl/ShoppingCartCollageServiceImpl.java
+14
-21
No files found.
assortment-shoppingcart-sdk/src/main/java/com/freemud/sdk/api/assortment/shoppingcart/service/impl/CollageCartBaseServiceImpl.java
View file @
3175c831
...
...
@@ -64,14 +64,17 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
@Override
public
BaseResponse
<
List
<
CartGoods
>>
getCartGoodsList
(
CartParamDto
cartParamDto
,
String
trackingNo
)
{
doCheck
(
cartParamDto
);
// 构建缓存key
String
collageCartHashKey
=
genCollageCarHashKey
(
cartParamDto
.
getPartnerId
(),
cartParamDto
.
getStoreId
(),
cartParamDto
.
getUserId
());
BoundHashOperations
<
String
,
String
,
CartGoods
>
operations
=
redisTemplate
.
boundHashOps
(
collageCartHashKey
);
List
<
CartGoods
>
cartGoodsList
=
operations
.
values
();
//对创建时间进行排序
cartGoodsList
.
sort
(
Comparator
.
comparingLong
(
CartGoods:
:
getCreateTimeMili
));
return
CartResponseUtil
.
success
(
cartGoodsList
);
try
{
doCheck
(
cartParamDto
);
// 构建缓存key
String
collageCartHashKey
=
genCollageCarHashKey
(
cartParamDto
.
getPartnerId
(),
cartParamDto
.
getStoreId
(),
cartParamDto
.
getUserId
());
BoundHashOperations
<
String
,
String
,
CartGoods
>
operations
=
redisTemplate
.
boundHashOps
(
collageCartHashKey
);
List
<
CartGoods
>
cartGoodsList
=
operations
.
values
();
return
CartResponseUtil
.
success
(
cartGoodsList
);
}
catch
(
Exception
e
)
{
ErrorLog
.
printErrorLog
(
"获取拼单购物车异常"
,
"CollageCartBaseServiceImpl/getCartGoodsList"
,
cartParamDto
,
e
);
return
CartResponseUtil
.
error
(
"获取拼单购物车异常"
);
}
}
private
void
doCheck
(
CartParamDto
cartParamDto
)
{
...
...
@@ -98,14 +101,23 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
try
{
String
redisKey
=
genCollageCarHashKey
(
cartParamDto
.
getPartnerId
(),
cartParamDto
.
getStoreId
(),
cartParamDto
.
getUserId
());
BoundHashOperations
<
String
,
String
,
CartGoods
>
operations
=
redisTemplate
.
boundHashOps
(
redisKey
);
// 获取拼单购物车的有效期
// 如果购物车已经存在则获取剩余的时间,如果不存在,则设置有效期为1小时(拼单的有效期为1小时)
Long
expire
=
3600L
;
if
(
redisTemplate
.
hasKey
(
redisKey
)){
expire
=
operations
.
getExpire
();
}
this
.
clear
(
cartParamDto
,
trackingNo
);
Map
<
String
,
CartGoods
>
cartGoodsMap
=
cartParamDto
.
getCartGoodsList
().
parallelStream
()
.
filter
(
k
->
org
.
apache
.
commons
.
lang
.
StringUtils
.
isNotEmpty
(
k
.
getCartGoodsUid
()))
.
collect
(
Collectors
.
toMap
(
CartGoods:
:
getCartGoodsUid
,
Function
.
identity
(),
(
k1
,
k2
)
->
k1
));
operations
.
putAll
(
cartGoodsMap
);
operations
.
expire
(
expire
,
TimeUnit
.
SECONDS
);
return
CartResponseUtil
.
success
();
}
catch
(
Exception
e
)
{
ErrorLog
.
printErrorLog
(
"
assortment-shoppingcart-sdk"
,
trackingNo
,
e
.
getMessage
(),
"setCartGoodsList"
,
cartParamDto
,
e
,
Level
.
ERROR
);
ErrorLog
.
printErrorLog
(
"
设置拼单购物车异常"
,
"CollageCartBaseServiceImpl/setCartGoodsList"
,
cartParamDto
,
e
);
return
null
;
}
}
...
...
@@ -118,7 +130,7 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
redisCache
.
delete
(
collageCartHashKey
);
return
new
BaseResponse
(
VersionUtils
.
VER_1
,
CartResponseConstant
.
SUCCESS
.
getCode
(),
CartResponseConstant
.
SUCCESS
.
getMessage
());
}
catch
(
Exception
e
)
{
ErrorLog
.
printErrorLog
(
"
assortment-shoppingcart-sdk"
,
trackingNo
,
e
.
getMessage
(),
"setCartGoodsList"
,
cartParamDto
,
e
,
Level
.
ERROR
);
ErrorLog
.
printErrorLog
(
"
清空拼单购物车异常"
,
"CollageCartBaseServiceImpl/clear"
,
cartParamDto
,
e
);
return
null
;
}
}
...
...
@@ -163,7 +175,7 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
}
return
this
.
getCartGoodsList
(
cartParamDto
,
trackingNo
);
}
catch
(
Exception
e
)
{
ErrorLog
.
printErrorLog
(
"
assortment-shoppingcart-sdk"
,
trackingNo
,
e
.
getMessage
(),
"updateGoodsQty"
,
cartParamDto
,
e
,
Level
.
ERROR
);
ErrorLog
.
printErrorLog
(
"
更新拼单购物车商品数量异常"
,
"CollageCartBaseServiceImpl/updateGoodsQty"
,
cartParamDto
,
e
);
return
null
;
}
}
...
...
@@ -175,7 +187,14 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
* @return
*/
public
Integer
getCartVersion
(
String
key
)
{
Integer
value
=
redisCache
.
getValue
(
key
);
Integer
value
=
null
;
try
{
value
=
redisCache
.
getValue
(
key
);
}
catch
(
Exception
e
)
{
Map
<
String
,
String
>
request
=
new
HashMap
<>();
request
.
put
(
"key"
,
key
);
ErrorLog
.
printErrorLog
(
"获取当前购物车版本信息异常"
,
"CollageCartBaseServiceImpl/getCartVersion"
,
request
,
e
);
}
return
value
==
null
?
1
:
value
;
}
...
...
@@ -198,8 +217,17 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
* @return
*/
public
Map
<
String
,
String
>
getCollageBase
(
String
partnerId
,
String
storeId
,
String
userId
)
{
String
collageBaseKey
=
genCollageBaseHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGetAll
(
collageBaseKey
);
try
{
String
collageBaseKey
=
genCollageBaseHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGetAll
(
collageBaseKey
);
}
catch
(
Exception
e
)
{
Map
<
String
,
String
>
request
=
new
HashMap
<>();
request
.
put
(
"partnerId"
,
partnerId
);
request
.
put
(
"storeId"
,
storeId
);
request
.
put
(
"userId"
,
userId
);
ErrorLog
.
printErrorLog
(
"获取拼单基础信息异常"
,
"CollageCartBaseServiceImpl/getCollageBase"
,
request
,
e
);
return
null
;
}
}
/**
...
...
@@ -221,8 +249,17 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
* @return
*/
public
Boolean
getCollageLock
(
String
partnerId
,
String
storeId
,
String
userId
)
{
String
collageLockKey
=
genCollageLockKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
getValue
(
collageLockKey
);
try
{
String
collageLockKey
=
genCollageLockKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
getValue
(
collageLockKey
);
}
catch
(
Exception
e
)
{
Map
<
String
,
String
>
request
=
new
HashMap
<>();
request
.
put
(
"partnerId"
,
partnerId
);
request
.
put
(
"storeId"
,
storeId
);
request
.
put
(
"userId"
,
userId
);
ErrorLog
.
printErrorLog
(
"获取拼单锁定状态异常"
,
"CollageCartBaseServiceImpl/getCollageLock"
,
request
,
e
);
return
null
;
}
}
/**
...
...
@@ -244,8 +281,17 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
* @return
*/
public
List
<
String
>
getCollageMemberHashKey
(
String
partnerId
,
String
storeId
,
String
userId
,
String
sessionId
)
{
String
collageMemberHashKey
=
genCollageMemberHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGet
(
collageMemberHashKey
,
sessionId
);
try
{
String
collageMemberHashKey
=
genCollageMemberHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGet
(
collageMemberHashKey
,
sessionId
);
}
catch
(
Exception
e
)
{
Map
<
String
,
String
>
request
=
new
HashMap
<>();
request
.
put
(
"partnerId"
,
partnerId
);
request
.
put
(
"storeId"
,
storeId
);
request
.
put
(
"userId"
,
userId
);
ErrorLog
.
printErrorLog
(
"获取获取拼单点餐位异常"
,
"CollageCartBaseServiceImpl/getCollageMemberHashKey"
,
request
,
e
);
return
null
;
}
}
/**
...
...
@@ -267,8 +313,18 @@ public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {
* @return
*/
public
Boolean
getCollageMemStateHashKey
(
String
partnerId
,
String
storeId
,
String
userId
,
String
sessionId
)
{
String
collageMemberHashKey
=
genCollageMemberStateHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGet
(
collageMemberHashKey
,
sessionId
);
try
{
String
collageMemberHashKey
=
genCollageMemberStateHashKey
(
partnerId
,
storeId
,
userId
);
return
redisCache
.
hashGet
(
collageMemberHashKey
,
sessionId
);
}
catch
(
Exception
e
)
{
Map
<
String
,
String
>
request
=
new
HashMap
<>();
request
.
put
(
"partnerId"
,
partnerId
);
request
.
put
(
"storeId"
,
storeId
);
request
.
put
(
"userId"
,
userId
);
request
.
put
(
"sessionId"
,
sessionId
);
ErrorLog
.
printErrorLog
(
"获取拼单用户选好的状态异常"
,
"CollageCartBaseServiceImpl/getCollageMemStateHashKey"
,
request
,
e
);
return
null
;
}
}
/**
...
...
shopping-cart-application-service/src/main/java/cn/freemud/controller/ShoppingCartCollageController.java
View file @
3175c831
...
...
@@ -5,37 +5,34 @@
* @Package cn.freemud.controller
* @Description:
* @author: ping.wu
* @date: 20
18/5/18 18:07
* @date: 20
20/09/29
* @version V1.0
* @Copyright: 20
18
www.freemud.cn Inc. All rights reserved.
* @Copyright: 20
20
www.freemud.cn Inc. All rights reserved.
* 注意:本内容仅限于上海非码科技内部传阅,禁止外泄以及用于其他的商业目
*/
package
cn
.
freemud
.
controller
;
import
cn.freemud.base.entity.BaseResponse
;
import
cn.freemud.entities.vo.*
;
import
cn.freemud.enums.ResponseResult
;
import
cn.freemud.service.impl.ShoppingCartCollageServiceImpl
;
import
cn.freemud.utils.ResponseUtil
;
import
com.freemud.api.assortment.datamanager.enums.IappIdType
;
import
com.freemud.application.sdk.api.base.SDKCommonBaseContextWare
;
import
com.freemud.application.sdk.api.log.ApiAnnotation
;
import
com.freemud.application.sdk.api.log.LogParams
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.MediaType
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
@RequestMapping
(
value
=
"/shoppingCart/collage"
,
consumes
=
MediaType
.
APPLICATION_JSON_UTF8_VALUE
)
@Api
(
value
=
"购物车 controller"
,
tags
=
{
"拼单购物车管理接口"
})
@Slf4j
public
class
ShoppingCartCollageController
{
/**
* 向拼单购物车中添加商品
*/
...
...
shopping-cart-application-service/src/main/java/cn/freemud/factory/AbstractShoppingCartImpl.java
View file @
3175c831
...
...
@@ -114,9 +114,6 @@ public abstract class AbstractShoppingCartImpl implements ShoppingCartNewService
}
public
UserLoginInfoDto
convert2UserLoginInfoDto
(
CustomerInfoVo
assortmentCustomerInfoVo
)
{
if
(
assortmentCustomerInfoVo
==
null
||
assortmentCustomerInfoVo
.
getMemberId
()
==
null
)
{
throw
new
ServiceException
(
ResponseResult
.
NOT_LOGIN
);
}
UserLoginInfoDto
userLoginInfoDto
=
new
UserLoginInfoDto
();
userLoginInfoDto
.
setMemberId
(
assortmentCustomerInfoVo
.
getMemberId
());
...
...
@@ -133,7 +130,7 @@ public abstract class AbstractShoppingCartImpl implements ShoppingCartNewService
}
/**
* 汇总
sku
数量
* 汇总
商品
数量
*
* @param allCartGoodsList
* @param cartGoods
...
...
shopping-cart-application-service/src/main/java/cn/freemud/service/ShoppingCartCollageService.java
View file @
3175c831
...
...
@@ -28,13 +28,18 @@ import java.util.stream.Collectors;
* @Title:
* @Package cn.freemud.service
* @Description:
* @author: p
ing.w
u
* @date: 20
18/5/18 19:4
9
* @Copyright: 20
18
www.freemud.cn Inc. All rights reserved.
* @author: p
engfei.li
u
* @date: 20
20/9/2
9
* @Copyright: 20
20
www.freemud.cn Inc. All rights reserved.
* 注意:本内容仅限于上海非码科技内部传阅,禁止外泄以及用于其他的商业目
*/
public
interface
ShoppingCartCollageService
{
/**
* 清除自己的购物车
* @param shoppingCartCollageClearRequestVo
* @return
*/
BaseResponse
clearPartCarGoods
(
ShoppingCartCollageClearRequestVo
shoppingCartCollageClearRequestVo
);
}
shopping-cart-application-service/src/main/java/cn/freemud/service/impl/ShoppingCartCollageServiceImpl.java
View file @
3175c831
...
...
@@ -76,9 +76,6 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
private
ActivityAdapter
activityAdapter
;
@Autowired
private
CollageOrderAdapter
collageOrderAdapter
;
@Autowired
private
RedisCache
redisCache
;
@Autowired
...
...
@@ -109,7 +106,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
// 获取当前登陆用户信息
CustomerInfoVo
currentUserInfoVo
=
getCustomerInfoVo
(
addShoppingCartGoodsRequestVo
.
getSessionId
());
// 当前用户必须登陆
if
(
currentUserInfoVo
.
getMemberId
()
==
null
)
{
if
(
null
==
currentUserInfoVo
||
StringUtils
.
isEmpty
(
currentUserInfoVo
.
getMemberId
())
)
{
throw
new
ServiceException
(
ResponseResult
.
NOT_LOGIN
);
}
UserLoginInfoDto
userLoginInfoDto
=
convert2UserLoginInfoDto
(
currentUserInfoVo
);
...
...
@@ -129,7 +126,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
String
crateUserId
=
addShoppingCartGoodsRequestVo
.
getCreateCollageUserId
();
// 拼单相关条件校验
check
(
partnerId
,
storeId
,
crateUserId
,
addShoppingCartGoodsRequestVo
.
getShopId
(),
spuId
,
addShoppingCartGoodsRequestVo
.
getCreateCollageUserId
()
,
currentSessionId
);
check
(
partnerId
,
storeId
,
crateUserId
,
spuId
,
currentSessionId
);
CartGoods
cartGoods
=
ShoppingCartConvertAdapter
.
convent2CartGoods
(
addShoppingCartGoodsRequestVo
);
cartGoods
.
setSessionId
(
currentSessionId
);
...
...
@@ -167,7 +164,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
// 当商品数量被设为0时
if
(
Objects
.
equals
(
cartGoods
.
getQty
(),
0
))
{
assortmentSdkService
.
updateGoodsQtyBySdk
(
partnerId
,
currentUserId
,
storeId
,
cartGoods
.
getCartGoodsUid
(),
0
,
""
,
shopping
CartBaseService
);
assortmentSdkService
.
updateGoodsQtyBySdk
(
partnerId
,
currentUserId
,
storeId
,
cartGoods
.
getCartGoodsUid
(),
0
,
""
,
collage
CartBaseService
);
}
}
catch
(
Exception
e
)
{
...
...
@@ -224,7 +221,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
String
crateUserId
=
updateShoppingCartGoodsQtyRequestVo
.
getCreateCollageUserId
();
// 拼单相关条件校验
check
(
partnerId
,
storeId
,
crateUserId
,
updateShoppingCartGoodsQtyRequestVo
.
getShopId
(),
null
,
crateUserId
,
currentSessionId
);
check
(
partnerId
,
storeId
,
crateUserId
,
null
,
currentSessionId
);
// 购物车版本加锁
dolock
(
partnerId
,
storeId
,
crateUserId
,
updateShoppingCartGoodsQtyRequestVo
.
getCarVer
());
...
...
@@ -572,12 +569,6 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
// 如果购物车中有商品券,则当前添加的商品是特价商品时,需要提示“已选商品券,与其他优惠商品不同享,商品将恢复原价”
// 拼单没有商品券、换购券
/* boolean haveCouponProduct = allCartGoodsList.parallelStream().anyMatch(k -> k.getCartGoodsUid().startsWith(CommonsConstant.COUPON_PREFIX));
if (haveCouponProduct && isSpecialGoods(addShoppingCartGoodsRequestVo.getPartnerId(), addShoppingCartGoodsRequestVo.getShopId(), userId, addShoppingCartGoodsRequestVo.getAppId(), goodsId, addShoppingCartGoodsRequestVo.getOrderType())) {
// 如果购物车先加入商品券,再加入促销商品,toast提示“已选商品券,与其他优惠商品不同享,商品将恢复原价”
setToastMsgIfNotExist(shoppingCartGoodsResponseVo, ShoppingCartConstant.HAS_GOODS_COUPON_WHEN_ADD_SPECIAL_GOODS);
}*/
return
cartGoodsList
;
}
...
...
@@ -593,15 +584,13 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
* @param partnerId
* @param storeId
* @param crateUserId
* @param shopId
* @param spuId
* @param createCollageUserId
* @param currentSessionId
*/
public
void
check
(
String
partnerId
,
String
storeId
,
String
crateUserId
,
String
s
hopId
,
String
spuId
,
String
createCollageUser
Id
,
String
currentSessionId
){
public
void
check
(
String
partnerId
,
String
storeId
,
String
crateUserId
,
String
s
pu
Id
,
String
currentSessionId
){
//店铺id不能为空
if
(
StringUtils
.
isEmpty
(
s
hop
Id
)){
if
(
StringUtils
.
isEmpty
(
s
tore
Id
)){
throw
new
ServiceException
(
ResponseResult
.
SHOPPING_CART_SHOP_ID_NOT_EMPTY
);
}
...
...
@@ -611,7 +600,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
}
// 拼单发起人id不能为空
// 拼单购物相关的redis的key都需要拼单发起人id,所以这个值是不能为空的
if
(
StringUtils
.
isEmpty
(
cr
eateCollag
eUserId
)){
if
(
StringUtils
.
isEmpty
(
cr
at
eUserId
)){
throw
new
ServiceException
(
ResponseResult
.
COLLAGE_NOT_EXIST
);
}
...
...
@@ -664,7 +653,7 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
if
(!
carVer
.
equals
(
cartVersion
))
{
throw
new
ServiceException
(
ResponseResult
.
SHOPPING_CART_VERSION_ERROR
);
}
redisCache
.
getValue
(
collageCartVerKey
);
boolean
lock
=
RedisLock
.
getInstance
(
redisCache
.
getRedisTemplate
()).
lock
(
collageCartVerKey
);
if
(!
lock
)
{
//加锁失败
...
...
@@ -679,8 +668,12 @@ public class ShoppingCartCollageServiceImpl extends AbstractShoppingCartImpl imp
* @param crateUserId
*/
private
void
doUnlock
(
String
partnerId
,
String
storeId
,
String
crateUserId
)
{
String
collageCartVerKey
=
genCollageCarVerKey
(
partnerId
,
storeId
,
crateUserId
);
RedisLock
.
getInstance
(
redisCache
.
getRedisTemplate
()).
unlock
(
collageCartVerKey
);
try
{
String
collageCartVerKey
=
genCollageCarVerKey
(
partnerId
,
storeId
,
crateUserId
);
RedisLock
.
getInstance
(
redisCache
.
getRedisTemplate
()).
unlock
(
collageCartVerKey
);
}
catch
(
Exception
e
)
{
ErrorLog
.
errorConvertJson
(
SDKCommonBaseContextWare
.
getAppName
(),
LogThreadLocal
.
getTrackingNo
(),
getClass
(),
"购物车版本解锁解锁失败"
,
e
);
}
}
/**
...
...
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