记得上下班打卡 | git大法好,push需谨慎

Commit 6939d3d0 authored by 张国柄's avatar 张国柄

fix:mq;

会员订单存储key调整;
parent 20344615
......@@ -78,11 +78,11 @@ public interface IAdamRdmService {
String getMemberAgreement();
boolean setShotMemberOrderVoByOrderNo(String uid, String orderNo, AdamMemberOrderVo vo);
boolean setShotMemberOrderVoByOrderNo(String orderNo, AdamMemberOrderVo vo);
AdamMemberOrderVo getShotMemberOrderVoByOrderNo(String uid, String orderNo);
AdamMemberOrderVo getShotMemberOrderVoByOrderNo(String orderNo);
void delShotMemberOrderVoByOrderNo(String uid, String orderNo);
void delShotMemberOrderVoByOrderNo(String orderNo);
boolean setMaxMemberNo(int val);
......
......@@ -177,14 +177,14 @@ public class AdamMemberOrderController {
@ApiOperation(value = "会员订单详情")
@GetMapping("info/{orderNo}")
public ResponseDto<AdamMemberOrderVo> getMemberOrderList(@NotBlank @PathVariable String orderNo) {
return ResponseDto.success(adamRdmService.getShotMemberOrderVoByOrderNo(CurrentUtil.getCurrentUid(), orderNo));
return ResponseDto.success(adamRdmService.getShotMemberOrderVoByOrderNo(orderNo));
}
@ApiOperationSupport(order = 6)
@ApiOperation(value = "会员订单状态")
@GetMapping("check")
public ResponseDto<Integer> checkOrderResult(@NotBlank @RequestParam String orderNo) {
AdamMemberOrderVo memberOrderInfo = adamRdmService.getShotMemberOrderVoByOrderNo(CurrentUtil.getCurrentUid(), orderNo);
AdamMemberOrderVo memberOrderInfo = adamRdmService.getShotMemberOrderVoByOrderNo(orderNo);
if (null == memberOrderInfo) {
return ResponseDto.failure(ErrorMapping.get("10211"));
}
......
......@@ -132,7 +132,7 @@ public class AdamMemberOrderServiceImpl extends ServiceImpl<AdamMemberOrderMappe
memberOrderVo.setVersion(CurrentUtil.getCliVersion());
memberOrderVo.setSource(CurrentUtil.getCliSource());
if (!adamRdmService.setShotMemberOrderVoByOrderNo(memberOrderVo.getUid(), orderNo, memberOrderVo)) {
if (!adamRdmService.setShotMemberOrderVoByOrderNo(orderNo, memberOrderVo)) {
log.warn("###购买会员创建订单失败[memberOrderVo:{}]", JsonUtils.toJson(memberOrderVo));
return ResponseDto.failure(ErrorMapping.get("10210"));
}
......@@ -153,7 +153,7 @@ public class AdamMemberOrderServiceImpl extends ServiceImpl<AdamMemberOrderMappe
return ResponseDto.failure(ErrorMapping.get("10203"));
}
adamRdmService.setShotMemberOrderVoByOrderNo(memberOrderVo.getUid(), orderNo, memberOrderVo);
adamRdmService.setShotMemberOrderVoByOrderNo(orderNo, memberOrderVo);
result.setOrderNo(memberOrderVo.getOrderNo());
result.setShowUrl(param.getShowUrl());
......@@ -163,7 +163,7 @@ public class AdamMemberOrderServiceImpl extends ServiceImpl<AdamMemberOrderMappe
@Override
public ResponseDto<Object> paymentNotifyCallBack(AdamMemberOrderCallbackParam parameter) {
AdamMemberOrderVo handleMemberOrderVo = adamRdmService.getShotMemberOrderVoByOrderNo(CurrentUtil.getCurrentUid(), parameter.getOrderCode());
AdamMemberOrderVo handleMemberOrderVo = adamRdmService.getShotMemberOrderVoByOrderNo(parameter.getOrderCode());
// AdamMemberConst.STATUS_*:0-待支付,1-已支付,2-已过期,3-超时付,4-退款中,5-退款完成
if (1 == handleMemberOrderVo.getState() || 3 == handleMemberOrderVo.getState()) {
return ResponseDto.failure(ErrorMapping.get("10502"), parameter);
......@@ -282,7 +282,7 @@ public class AdamMemberOrderServiceImpl extends ServiceImpl<AdamMemberOrderMappe
handleMemberOrderVo.getCreatedAt(), handleMemberOrderVo.getClientIp(), handleMemberOrderVo.getSource(), handleMemberOrderVo.getVersion()
});
adamRdmService.setShotMemberOrderVoByOrderNo(handleMemberOrderVo.getUid(), handleMemberOrderVo.getOrderNo(), handleMemberOrderVo);
adamRdmService.setShotMemberOrderVoByOrderNo(handleMemberOrderVo.getOrderNo(), handleMemberOrderVo);
rabbitTemplate.convertSendAndReceive(MQConst.EX_LNS_SQL_UCENTER, MQConst.RK_SQL_UMEMBER,
SqlMapping.gets(toMqSqls, operationObjs, updateMemberOrderObjs));
......
......@@ -345,17 +345,17 @@ public class AdamRdmServiceImpl implements IAdamRdmService {
}
@Override
public boolean setShotMemberOrderVoByOrderNo(String uid, String orderNo, AdamMemberOrderVo vo) {
return redisUtil.set(AdamRedisConst.SHOT_MEMBER_ORDER + uid + ":" + orderNo, vo);
public boolean setShotMemberOrderVoByOrderNo(String orderNo, AdamMemberOrderVo vo) {
return redisUtil.set(AdamRedisConst.SHOT_MEMBER_ORDER + orderNo, vo);
}
@Override
public AdamMemberOrderVo getShotMemberOrderVoByOrderNo(String uid, String orderNo) {
String key = AdamRedisConst.SHOT_MEMBER_ORDER + uid + ":" + orderNo;
public AdamMemberOrderVo getShotMemberOrderVoByOrderNo(String orderNo) {
String key = AdamRedisConst.SHOT_MEMBER_ORDER + orderNo;
AdamMemberOrderVo vo = (AdamMemberOrderVo) redisUtil.get(key);
if (null == vo) {
vo = mongoTemplate.findOne(
Query.query(Criteria.where("orderNo").is(orderNo).and("uid").is(uid)),
Query.query(Criteria.where("orderNo").is(orderNo)),
AdamMemberOrderVo.class, AdamMemberOrderVo.class.getSimpleName()
);
......@@ -365,8 +365,8 @@ public class AdamRdmServiceImpl implements IAdamRdmService {
}
@Override
public void delShotMemberOrderVoByOrderNo(String uid, String orderNo) {
redisUtil.del(AdamRedisConst.SHOT_MEMBER_ORDER + uid + ":" + orderNo);
public void delShotMemberOrderVoByOrderNo(String orderNo) {
redisUtil.del(AdamRedisConst.SHOT_MEMBER_ORDER + orderNo);
}
@Override
......
package com.liquidnet.service.consumer.service.impl;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.consumer.service.IBaseDao;
import org.slf4j.Logger;
......@@ -53,6 +52,7 @@ public class BaseDao implements IBaseDao {
@Override
public Boolean batchSqls(final LinkedList<String> sql,
final LinkedList<Object[]>... values) {
try {
TransactionCallback<Boolean> callback = new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(final TransactionStatus transactionStatus) {
......@@ -63,19 +63,13 @@ public class BaseDao implements IBaseDao {
}
if (!o.isEmpty()) {
jdbcTemplate.batchUpdate(sql.get(i), o);
// for (int c : ints) {
// if (c <= 0) {
// throw new LiquidnetServiceException("NON.SQL", sql.get(i));
// }
// }
}
i++;
}
return true;
}
};
try {
TransactionTemplate tt = new TransactionTemplate(transactionManager);
return tt.execute(callback);
} catch (Exception ex) {
......
......@@ -56,15 +56,10 @@ public class ConsumerProcessor {
// }
// }
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EX_LNS_SQL_UCENTER), key = MQConst.RK_SQL_UCENTER,
value = @Queue(MQConst.QUEUES_SQL_UCENTER)
))
public void consumerSqlForURegister(Message msg, Channel channel) {
private void consumerSqlDaoHandler(Message msg, Channel channel) {
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("consumer sql result of execution:{}", rstBatchSqls);
......@@ -73,249 +68,94 @@ public class ConsumerProcessor {
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
} catch (IOException e) {
log.error("error:consumer sql:Channel.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), e);
}
}
// 用户注册
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EX_LNS_SQL_UCENTER), key = MQConst.RK_SQL_UREGISTER,
value = @Queue(MQConst.QUEUES_SQL_UREGISTER)
))
public void consumerSqlForUCenter(Message msg, Channel channel) {
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("consumer sql result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
public void consumerSqlForURegister(Message msg, Channel channel) {
this.consumerSqlDaoHandler(msg, channel);
}
// 用户信息
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EX_LNS_SQL_UCENTER), key = MQConst.RK_SQL_UCENTER,
value = @Queue(MQConst.QUEUES_SQL_UCENTER)
))
public void consumerSqlForUCenter(Message msg, Channel channel) {
this.consumerSqlDaoHandler(msg, channel);
}
// 会员购买
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EX_LNS_SQL_UCENTER), key = MQConst.RK_SQL_UMEMBER,
value = @Queue(MQConst.QUEUES_SQL_UMEMBER)
))
public void consumerSqlForUMember(Message msg, Channel channel) {
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("consumer sql result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
// 验票更新
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EX_LNS_SQL_STATION), key = MQConst.RK_SQL_STATION,
value = @Queue(MQConst.QUEUES_SQL_STATION)
))
public void consumerSqlForStation(Message msg, Channel channel) {
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("consumer sql result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
// 订单创建
// @RabbitListener(queues = MQConst.QUEUES_SQL_ORDER_CREATE)
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CREADE),
key = MQConst.ROUTING_KEY_SQL_ORDER_CREATE,
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CREADE), key = MQConst.ROUTING_KEY_SQL_ORDER_CREATE,
value = @Queue(MQConst.QUEUES_SQL_ORDER_CREATE)
))
public void consumerOrderCreate(Message msg, Channel channel) {
log.info("=== CONSUMER_ORDER_CREATE ===");
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql_order_create ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql_order_create ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("CONSUMER_ORDER_CREATE result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql2:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql2:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
//订单再次支付
// @RabbitListener(queues = MQConst.QUEUES_SQL_ORDER_AGAIN)
// 订单再次支付
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_AGAIN),
key = MQConst.ROUTING_KEY_SQL_ORDER_AGAIN,
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_AGAIN), key = MQConst.ROUTING_KEY_SQL_ORDER_AGAIN,
value = @Queue(MQConst.QUEUES_SQL_ORDER_AGAIN)
))
public void consumerOrderPayAgain(Message msg, Channel channel) {
log.info("=== CONSUMER_ORDER_PAY_AGAIN ===");
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql_order_create ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql_order_create ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("CONSUMER_ORDER_PAY_AGAIN result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql2:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql2:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
//订单关闭
// @RabbitListener(queues = MQConst.QUEUES_SQL_ORDER_CLOSE)
// 订单关闭
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CLOSE),
key = MQConst.ROUTING_KEY_SQL_ORDER_CLOSE,
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CLOSE), key = MQConst.ROUTING_KEY_SQL_ORDER_CLOSE,
value = @Queue(MQConst.QUEUES_SQL_ORDER_CLOSE)
))
public void consumerOrderClose(Message msg, Channel channel) {
log.info("=== CONSUMER_ORDER_CLOSE ===");
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql_order_create ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql_order_create ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("CONSUMER_ORDER_CLOSE result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql2:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql2:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
//订单支付
// @RabbitListener(queues = MQConst.QUEUES_SQL_ORDER_PAY)
// 订单支付
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_PAY),
key = MQConst.ROUTING_KEY_SQL_ORDER_PAY,
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_PAY), key = MQConst.ROUTING_KEY_SQL_ORDER_PAY,
value = @Queue(MQConst.QUEUES_SQL_ORDER_PAY)
))
public void consumerOrderPay(Message msg, Channel channel) {
log.info("=== CONSUMER_ORDER_PAY ===");
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql_order_create ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql_order_create ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("CONSUMER_ORDER_PAY result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql2:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql2:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
//缺票登记
// @RabbitListener(queues = MQConst.QUEUES_SQL_PERFORMANCE_LACK)
// 缺票登记
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_PERFORMANCE_LACK),
key = MQConst.ROUTING_KEY_SQL_PERFORMANCE_LACK,
exchange = @Exchange(MQConst.EXCHANGES_LIQUIDNET_SQL_PERFORMANCE_LACK), key = MQConst.ROUTING_KEY_SQL_PERFORMANCE_LACK,
value = @Queue(MQConst.QUEUES_SQL_PERFORMANCE_LACK)
))
public void consumerPerformanceLack(Message msg, Channel channel) {
log.info("=== CONSUMER_PERFORMANCE_LACK ===");
SqlMapping.SqlMessage sqlMessage = JsonUtils.fromJson(new String(msg.getBody()), SqlMapping.SqlMessage.class);
log.debug("consumer sql_performance_lack ==> Preparing:{}", JsonUtils.toJson(sqlMessage.getSqls()));
log.debug("consumer sql_performance_lack ==> Parameters:{}", JsonUtils.toJson(sqlMessage.getArgs()));
try {
Boolean rstBatchSqls = baseDao.batchSqls(sqlMessage.getSqls(), sqlMessage.getArgs());
log.debug("CONSUMER_PERFORMANCE_LACK result of execution:{}", rstBatchSqls);
if (rstBatchSqls) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
}
} catch (Exception e) {
log.error("error:consumer sql2:{}", JsonUtils.toJson(sqlMessage), e);
try {
channel.basicReject(msg.getMessageProperties().getDeliveryTag(), true);
} catch (IOException ioException) {
log.error("error:consumer sql2:basicReject.msg.tag:{}", msg.getMessageProperties().getDeliveryTag(), ioException);
}
}
this.consumerSqlDaoHandler(msg, channel);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment