Authored by tanling

Merge branch 'test6.9.14' of http://git.yoho.cn/ufo/yohoufo-fore into test6.9.14

package com.yohoufo.dal.promotion.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.math.BigDecimal;
@ToString
public class Coupon {
private Integer id;
... ... @@ -27,6 +32,9 @@ public class Coupon {
private String productLimitValue;
@Getter@Setter
private Integer receiveStartTime;
private Integer startTime;
private Integer endTime;
... ...
package com.yohoufo.dal.resource;
import com.yohoufo.dal.resource.model.ActivtyTemplatedFloor;
import java.util.List;
public interface ActivtyTemplatedFloorMapper {
List<ActivtyTemplatedFloor> selectByTemplatedId(Integer templatedId);
}
\ No newline at end of file
... ...
package com.yohoufo.dal.resource;
import com.yohoufo.dal.resource.model.ActivtyTemplated;
public interface ActivtyTemplatedMapper {
ActivtyTemplated selectByPrimaryKey(Integer id);
}
\ No newline at end of file
... ...
package com.yohoufo.dal.resource.model;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString
public class ActivtyTemplated {
private Integer id;
private String title;
private Integer status;
private Integer isDel;
private Integer createTime;
private Integer updateTime;
private String updateUser;
private List<ActivtyTemplatedFloor> floors;
}
\ No newline at end of file
... ...
package com.yohoufo.dal.resource.model;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class ActivtyTemplatedFloor {
private Integer id;
private Integer activtyTemplatedId;
private Integer order;
private Integer isDel;
private String moduleData;
}
\ No newline at end of file
... ...
... ... @@ -276,7 +276,7 @@
(select id from (select id ,storage_id
from storage_price FORCE INDEX (`idx_storage_id_price`)
where status = 1 and product_id = #{productId} and is_hide = 0 and region = 0 and pre_sale_flag = 0
order by storage_id,price asc limit 100000 )a
order by storage_id,price asc limit 1000000 )a
group by storage_id) b
where t.id = b.id
</select>
... ...
... ... @@ -23,11 +23,13 @@
<result column="skup_forbid_type" jdbcType="VARCHAR" property="skupForbidType" />
<result column="skup_allow_type" jdbcType="VARCHAR" property="skupAllowType" />
<result column="business_client" jdbcType="VARCHAR" property="businessClient" />
<result column="receive_start_time" property="receiveStartTime" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List">
id, coupon_token, coupon_name, coupon_amount, coupon_type, coupon_num, use_num, send_num,
use_limit_type, use_limit_value, product_limit_type, product_limit_value, start_time,
end_time, status, create_time, pid, remark,skup_forbid_type,skup_allow_type,business_client
end_time, status, create_time, pid, remark,skup_forbid_type,skup_allow_type,business_client,
receive_start_time
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
... ...
<?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="com.yohoufo.dal.resource.ActivtyTemplatedFloorMapper" >
<resultMap id="BaseResultMap" type="com.yohoufo.dal.resource.model.ActivtyTemplatedFloor" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="activty_templated_id" property="activtyTemplatedId" jdbcType="INTEGER" />
<result column="order" property="order" jdbcType="INTEGER" />
<result column="is_del" property="isDel" jdbcType="INTEGER" />
</resultMap>
<resultMap id="ResultMapWithBLOBs" type="com.yohoufo.dal.resource.model.ActivtyTemplatedFloor" extends="BaseResultMap" >
<result column="module_data" property="moduleData" jdbcType="LONGVARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, activty_templated_id, `order`, is_del
</sql>
<sql id="Blob_Column_List" >
module_data
</sql>
<select id="selectByTemplatedId" resultMap="ResultMapWithBLOBs" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from activty_templated_floor
where activty_templated_id = #{activtyTemplatedId,jdbcType=INTEGER} AND is_del = 0 ORDER BY `order` ASC
</select>
</mapper>
\ No newline at end of file
... ...
<?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="com.yohoufo.dal.resource.ActivtyTemplatedMapper" >
<resultMap id="BaseResultMap" type="com.yohoufo.dal.resource.model.ActivtyTemplated" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="title" property="title" jdbcType="VARCHAR" />
<result column="status" property="status" jdbcType="INTEGER" />
<result column="is_del" property="isDel" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="update_user" property="updateUser" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, title, status, is_del, create_time, update_time, update_user
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from activty_templated
where id = #{id,jdbcType=INTEGER} AND is_del = 0 AND status = 1
</select>
</mapper>
\ No newline at end of file
... ...
package com.yohoufo.order.controller;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.order.constants.CouponConstants;
import com.yohoufo.order.model.request.OfflineShoppingRequest;
import com.yohoufo.order.model.response.ComputeResponse;
import com.yohoufo.order.model.response.OfflinePaymentResponse;
... ... @@ -32,12 +33,15 @@ public class OfflineShoppingController {
public ApiResponse offlinePayment(@RequestParam(name = "uid") Integer uid,
@RequestParam(name = "skup") Integer skup,
@RequestParam(name = "store_id") Integer storeId,
@RequestParam(value = "business_client", required = false,defaultValue = "ufo") String businessClient){
@RequestParam(value = "business_client", required = false,defaultValue = "ufo") String businessClient,
@RequestParam(name = "api_version", required = false, defaultValue = "0") int apiVersion){
OfflineShoppingRequest req = new OfflineShoppingRequest();
req.setUid(uid);
req.setSkup(skup);
req.setStoreId(storeId);
req.setCouponCodes(CouponConstants.AUTO_RECOMMENDED_COUPON_CODES);
req.setBusinessClient(businessClient);
req.setApiVersion(apiVersion);
logger.info("in ufo.order.offlinePayment, req {}", req);
OfflinePaymentResponse paymentResponse = offlineShoppingService.offlinePayment(req);
return new ApiResponse.ApiResponseBuilder().code(200).data(paymentResponse).build();
... ... @@ -53,12 +57,14 @@ public class OfflineShoppingController {
public ApiResponse offlineCompute(@RequestParam(name = "uid") Integer uid,
@RequestParam(name = "skup") Integer skup,
@RequestParam(name = "coupon_code",required = false) String couponCode,
@RequestParam(name="promotionId", required = false)Integer promotionId,
@RequestParam(value = "business_client", required = false,defaultValue = "ufo") String businessClient) {
OfflineShoppingRequest req = new OfflineShoppingRequest();
req.setUid(uid);
req.setSkup(skup);
req.setCouponCodes(CouponCodeUtils.asList(couponCode));
req.setPromotionId(promotionId);
req.setBusinessClient(businessClient);
logger.info("in ufo.order.offlineCompute, req {}", req);
... ... @@ -74,6 +80,7 @@ public class OfflineShoppingController {
public ApiResponse offlineSubmit(@RequestParam(name = "uid") Integer uid,
@RequestParam(name = "skup") Integer skup,
@RequestParam(name = "coupon_code",required = false) String couponCode,
@RequestParam(name="promotionId", required = false)Integer promotionId,
@RequestParam(name = "channelNo", required = false) String channelNo,
@RequestParam(name = "store_id") Integer storeId,
@RequestParam(name = "user_longitude") Double userLongitude,
... ... @@ -88,6 +95,7 @@ public class OfflineShoppingController {
request.setUid(uid);
request.setSkup(skup);
request.setCouponCodes(CouponCodeUtils.asList(couponCode));
request.setPromotionId(promotionId);
request.setChannelNo(channelNo);
request.setAddressId("0"); //门店自提,不需addressId
request.setStoreId(storeId);
... ...
... ... @@ -18,6 +18,10 @@ public class OfflinePaymentResponse extends PaymentResponse {
offlinePaymentResponse.setPaymentWay(paymentResponse.getPaymentWay());
offlinePaymentResponse.setDeliveryWay(paymentResponse.getDeliveryWay());
offlinePaymentResponse.setPromotionFormulaList(paymentResponse.getPromotionFormulaList());
offlinePaymentResponse.setRecommendedCouponInfo(paymentResponse.getRecommendedCouponInfo());
offlinePaymentResponse.setCouponList(paymentResponse.getCouponList());
offlinePaymentResponse.setPromotionList(paymentResponse.getPromotionList());
offlinePaymentResponse.setPromotionTips(paymentResponse.getPromotionTips());
offlinePaymentResponse.setDamagesDesc("店内闪购:请确保您可到指定地点进行提货,并在支付前检查商品是否完好。店内购买商品若无质量问题不支持退换。");
return offlinePaymentResponse;
... ...
... ... @@ -8,8 +8,6 @@ import com.yoho.tools.docs.ApiOperation;
import com.yoho.tools.docs.ApiParam;
import com.yoho.tools.docs.ApiResp;
import com.yoho.tools.docs.ApiRespCode;
import com.yohobuy.ufo.model.GoodsBO;
import com.yohobuy.ufo.model.GoodsSize;
import com.yohobuy.ufo.model.ProductInfo;
import com.yohobuy.ufo.model.request.SeekToBuyStorageBo;
import com.yohobuy.ufo.model.request.StoragePriceBo;
... ... @@ -21,16 +19,12 @@ import com.yohobuy.ufo.model.response.StorageInfoResp;
import com.yohobuy.ufo.model.response.StorageCheckResp;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.common.alarm.EventBusPublisher;
import com.yohoufo.common.annotation.IgnoreSession;
import com.yohoufo.common.annotation.IgnoreSignature;
import com.yohoufo.common.cache.Cachable;
import com.yohoufo.common.cache.ControllerCacheAop;
import com.yohoufo.common.caller.UfoServiceCaller;
import com.yohoufo.common.utils.StringUtil;
import com.yohoufo.dal.product.model.Goods;
import com.yohoufo.dal.product.model.StoragePrice;
import com.yohoufo.product.event.StoragePriceUpdateEvent;
import com.yohoufo.product.model.SkupInfo;
import com.yohoufo.product.response.*;
import com.yohoufo.product.service.ProductService;
... ... @@ -42,7 +36,6 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
... ... @@ -53,8 +46,6 @@ import org.springframework.web.servlet.ModelAndView;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
@RestController
... ... @@ -391,7 +382,6 @@ public class ProductController {
//清缓存
LOG.info("sellerUpdateStatus success and async clearProductCache skupList = {}", skupList);
clearBatchProductCache(skupList);
return new ApiResponse(200, "更新成功!", Boolean.TRUE);
} catch (Exception e) {
LOG.error("sellerBatchUpdateStatus失败!", e);
... ... @@ -601,14 +591,14 @@ public class ProductController {
private void clearBatchProductCache(List<Integer> skupList) {
try {
LOG.info("in clearBatchProductCache skupList = {}", skupList);
List<StoragePrice> spList = productService.getStoragePriceBySkupList(skupList);
List<Integer> productIdList = spList.stream().map(StoragePrice::getProductId).distinct().collect(Collectors.toList());
List<Integer> storageIdList = spList.stream().map(StoragePrice::getStorageId).distinct().collect(Collectors.toList());
List<StoragePrice> storagePriceList = productService.getStoragePriceBySkupList(skupList);
List<Integer> productIdList = storagePriceList.stream().map(StoragePrice::getProductId).distinct().collect(Collectors.toList());
List<Integer> storageIdList = storagePriceList.stream().map(StoragePrice::getStorageId).distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(productIdList)) {
for (Integer productId : productIdList) {
LOG.info("Batch clearCache queryProductDetailById productId = {}, ", productId);
storagePriceService.publishPriceUpdateEvent(productId);
storagePriceService.publishPriceUpdateEventOfClearCache(productId);
//商品详情
cacheAop.clearCache(
... ... @@ -659,7 +649,7 @@ public class ProductController {
}
}
Map<String, StoragePrice> distinctStorage = new HashMap<>();
for(StoragePrice sp : spList) {
for(StoragePrice sp : storagePriceList) {
Integer skup = sp.getSkup();
Integer storageId = sp.getStorageId();
if (sp.getPreSaleFlag() != null && (sp.getPreSaleFlag() == 5 || sp.getPreSaleFlag() == 6)) {
... ...
... ... @@ -13,11 +13,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
... ... @@ -97,6 +97,13 @@ public class StoragePriceService {
return true;
}
public void publishPriceUpdateEventIf(Integer productId, Predicate<List<StoragePrice>> predicate) {
List<StoragePrice> sizePriceCacheList = productCacheService.getListCacheByString(UfoProductCacheKeyEnum.STORAGE_PRICE_IN_STOCK_INFO_KEY, StoragePrice.class, productId);
if (predicate.test(sizePriceCacheList)) {
publishPriceUpdateEvent(productId);
}
}
public void publishPriceUpdateEvent(Integer productId) {
LOGGER.info("method com.yohoufo.product.service.impl.StoragePriceService.publishPriceUpdateEvent in productId is 【{}】", productId);
... ... @@ -108,4 +115,14 @@ public class StoragePriceService {
public List<StoragePrice> selectLeastPricesByProductId(Integer productId) {
return storagePriceMapper.selectLeastPricesByProductId(productId);
}
public void publishPriceUpdateEventOfClearCache(Integer productId) {
LOGGER.info("method com.yohoufo.product.service.impl.StoragePriceService.publishPriceUpdateEvent in productId is 【{}】", productId);
StoragePriceUpdateEvent storagePriceUpdateEvent = new StoragePriceUpdateEvent(event->{
productCacheService.deleteCacheByString(UfoProductCacheKeyEnum.STORAGE_PRICE_IN_STOCK_INFO_KEY, productId.toString());
return true;
});
storagePriceUpdateEvent.setProductId(productId);
EventBusPublisher.publishEvent(storagePriceUpdateEvent);
}
}
... ...
package com.yohoufo.product.util;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolFactory {
private final static ExecutorService cacheCleanExecutorService;
static {
int numberOfProcessorsAvailable = Runtime.getRuntime().availableProcessors();
cacheCleanExecutorService = new ThreadPoolExecutor(
numberOfProcessorsAvailable,
numberOfProcessorsAvailable * 2,
60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
NamedThreadFactory.newThreadFactory("cache-clean"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
public static ExecutorService cacheCleanExecutorService() {
return cacheCleanExecutorService;
}
public static class NamedThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private final ThreadGroup group;
public static ThreadFactory newThreadFactory(String bizName) {
return new NamedThreadFactory(bizName);
}
private NamedThreadFactory(String bizName) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "product-pool-" + bizName + "-processor-" + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon())
t.setDaemon(true);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
}
... ...
... ... @@ -2,6 +2,7 @@ package com.yohoufo.promotion.service.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
... ... @@ -14,6 +15,9 @@ import com.yohobuy.ufo.model.promotion.request.UserCouponListReq;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
import com.yohobuy.ufo.model.promotion.response.CouponInfoListBo;
import com.yohobuy.ufo.model.promotion.response.CouponSendBo;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.common.lock.RedisLock;
import com.yohoufo.common.lock.RedisLockFactory;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.promotion.CouponMapper;
import com.yohoufo.dal.promotion.UserCouponMapper;
... ... @@ -32,6 +36,7 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
... ... @@ -53,6 +58,9 @@ public class CouponServiceImpl implements ICouponService {
@Autowired
SingleCentCouponService singleCentSyncCoupNumService;
@Autowired
private RedisLockFactory redisLockFactory;
private final Logger logger = LoggerFactory.getLogger(getClass());
... ... @@ -109,7 +117,7 @@ public class CouponServiceImpl implements ICouponService {
validityRange = Range.open(now, end);
}
return sendCoupons(uid, couponTokens.stream().collect(Collectors.joining(",")), repeatable, validityRange);
return sendCoupons(uid, couponTokens.stream().collect(Collectors.joining(",")), repeatable, validityRange, true);
}
... ... @@ -118,6 +126,8 @@ public class CouponServiceImpl implements ICouponService {
// 允许重复发放
boolean repeatable;
//是否需要校验可领取时间
boolean receiveStartTimeChkNecessary = false;
// 有效期
Range<Integer> validityRange;
... ... @@ -129,15 +139,20 @@ public class CouponServiceImpl implements ICouponService {
}else if(CouponSendType.PLATFORM_SEND_COUPON.equals(sendType)){
repeatable = true;
validityRange = null;
} else {
} else {//用户领取
repeatable = false;
validityRange = null;
receiveStartTimeChkNecessary = true;
}
return sendCoupons(uid, couponTokens, repeatable, validityRange);
return sendCoupons(uid, couponTokens, repeatable, validityRange, receiveStartTimeChkNecessary);
}
private List<CouponSendBo> sendCoupons(Integer uid, String couponTokens, boolean repeatable, Range<Integer> validityRange) {
private List<CouponSendBo> sendCoupons(Integer uid,
String couponTokens,
boolean repeatable,
Range<Integer> validityRange,
boolean receiveStartTimeChkNecessary) {
if (uid == null || uid.intValue() <=0
|| StringUtils.isEmpty(couponTokens)){
... ... @@ -154,12 +169,16 @@ public class CouponServiceImpl implements ICouponService {
CouponSendBo couponSendBo = new CouponSendBo();
couponSendBo.setCouponToken(couponToken);
try {
couponSendBo.setCouponCode(sendPerCoupon(uid, couponToken, repeatable,validityRange));
couponSendBo.setCouponCode(sendPerCoupon(uid, couponToken, repeatable,validityRange, receiveStartTimeChkNecessary));
couponSendBo.setSuccess(true);
} catch (ServiceException ex) {
logger.info("happened serviceException,uid:{},couponTokens:{}", uid, couponTokens, ex);
couponSendBo.setErrCode(ex.getCode());
couponSendBo.setErrMsg(ex.getServiceError().getMappingGatewayError().getRight());
} catch (UfoServiceException e) {
logger.warn("happened ufoServiceException,uid:{},couponTokens:{}", uid, couponTokens, e);
couponSendBo.setErrCode(e.getCode());
couponSendBo.setErrMsg(e.getErrorMessage());
} catch (Exception e) {
logger.warn("happened exception,uid:{},couponTokens:{}", uid, couponTokens, e);
couponSendBo.setErrCode(ServiceError.PROMOTION_COUPON_SEND_FAIL.getCode());
... ... @@ -171,23 +190,45 @@ public class CouponServiceImpl implements ICouponService {
return couponSendBoList;
}
private String sendPerCoupon(Integer uid, String couponToken, boolean repeatable, Range<Integer> validityRange) {
private void checkReceiveStartTime(int uid, Coupon coupon){
Integer receiveStartTime;
Integer currentDT = DateUtil.getCurrentTimeSecond();
if (Objects.nonNull(receiveStartTime = coupon.getReceiveStartTime())
&& currentDT < receiveStartTime){
logger.warn("sendCoupon find current time not reach receiveStartTime,uid {} couponToken {} [{} {}]", uid, coupon.getCouponToken(), currentDT, receiveStartTime);
throw new ServiceException(ServiceError.PROMOTION_COUPON_NOT_ARRIVE_GET_START_TIME);
}
}
private String sendPerCoupon(Integer uid,
String couponToken,
boolean repeatable,
Range<Integer> validityRange,
boolean receiveStartTimeChkNecessary) {
logger.info("senCoupon enter,{},{},{}", uid, couponToken, repeatable);
logger.info("sendCoupon enter,{},{},{},{},{}", uid, couponToken, repeatable, validityRange, receiveStartTimeChkNecessary);
// 根据 couponToken 获取coupon&couponType信息
CouponAndType couponAndType = couponCacheService.getCouponAndType(couponToken);
if (couponAndType == null){
logger.warn("query coupon info,coupontype is null:{}", couponToken);
logger.warn("sendCoupon query coupon info,coupontype is null:{}", couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_NOT_EXISTS);
}
Coupon coupon = couponAndType.getCoupon();
//check receive start time
if(receiveStartTimeChkNecessary){
//
checkReceiveStartTime(uid, coupon);
}
RedisLock redisLock = null;
if(!repeatable){
// 校验是否可以领取(重复领取,时间是否合法,状态)
checkCanAcquire(uid, couponToken, couponAndType);
redisLock = checkCanAcquire(uid, couponToken, couponAndType);
}
if (couponAndType.getCoupon().getStatus() != CouponsStatusEnum.VALID.getCode()){
if (coupon.getStatus() != CouponsStatusEnum.VALID.getCode()){
logger.info("couponrulebo status is not valid:{},{}",uid, couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_IS_NOT_VAILD);
}
... ... @@ -208,19 +249,16 @@ public class CouponServiceImpl implements ICouponService {
}
int count = 0;
// 不可重复
if (!repeatable){
count = userCouponMapper.insertWhere(userCoupon);
}else{
count = userCouponMapper.insert(userCoupon);
}
count = userCouponMapper.insert(userCoupon);
if (count == 0){
logger.info("can not repeatable acquire coupon. uid is {}, coupon is {}", uid, couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
}
logger.info("senCoupon success,{},{},{},{}", uid, couponToken, couponCode, count);
if(Objects.nonNull(redisLock)){
redisLock.unlock();
}
return couponCode;
}
... ... @@ -317,13 +355,22 @@ public class CouponServiceImpl implements ICouponService {
}
private void checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
private RedisLock checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
// 验证该用户是否重复领取
UserCoupon userCoupon = userCouponMapper.selectByUidAndToken(uid, couponToken);
RedisLock redisLock = redisLockFactory.newLock(RedisKeyBuilder.newInstance()
.appendFixed("ufo:promotion:coupons:checkCanAcquire:")
.appendVar(uid + "-" + couponToken), 3, TimeUnit.SECONDS);
if (!redisLock.tryLock()) {
logger.info("{} checkCanAcquire fail, it already in the process", uid);
throw new UfoServiceException(400, "优惠券领取中");
}
if (userCoupon != null){
logger.warn("user has acquried this coupon before:{},{}", uid, couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
}
return redisLock;
}
... ...
package com.yohoufo.resource.controller;
import com.yoho.tools.docs.ApiOperation;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.common.annotation.IgnoreSession;
import com.yohoufo.dal.resource.model.ActivtyTemplated;
import com.yohoufo.dal.resource.model.ActivtyTemplatedFloor;
import com.yohoufo.resource.request.ResourcesRequest;
import com.yohoufo.resource.service.IResourcesService;
import com.yohoufo.resource.service.impl.ActivtyTemplatedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
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;
/**
* Created by li.ma on 2019/10/25.
*/
@RestController
public class ActivtyTemplatedController {
private static final Logger logger = LoggerFactory.getLogger(ActivtyTemplatedController.class);
@Autowired
private ActivtyTemplatedService activtyTemplatedService;
/**
* <p>根据templated_id返回活动模板信息</p>
*
* @param activty templated_id
* @return
* @date: Created on 2018年9月18日 上午10:36:49
*/
@ApiOperation(name = "ufo.activty.get", desc="活动模板获取")
@RequestMapping(params = "method=ufo.activty.get")
@IgnoreSession
@ResponseBody
public ApiResponse getResource(@RequestParam(name = "templated_id") Integer templatedId) {
logger.info("Get activty by content templatedId[{}]", templatedId);
ActivtyTemplated data = activtyTemplatedService.get(templatedId);
logger.info("Get activty by content templatedId[{}] success.", templatedId);
return new ApiResponse.ApiResponseBuilder().data(data).code(200).message("activty data").build();
}
}
... ...
package com.yohoufo.resource.service.impl;
import com.google.common.collect.Lists;
import com.yohoufo.dal.resource.ActivtyTemplatedFloorMapper;
import com.yohoufo.dal.resource.ActivtyTemplatedMapper;
import com.yohoufo.dal.resource.model.ActivtyTemplated;
import com.yohoufo.dal.resource.model.ActivtyTemplatedFloor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created by li.ma on 2019/10/25.
*/
@Service
public class ActivtyTemplatedService {
@Autowired
private ActivtyTemplatedFloorMapper activtyTemplatedFloorMapper;
@Autowired
private ActivtyTemplatedMapper activtyTemplatedMapper;
public ActivtyTemplated get(Integer templatedId) {
ActivtyTemplated activtyTemplated = activtyTemplatedMapper.selectByPrimaryKey(templatedId);
if (null == activtyTemplated) {
return null;
}
activtyTemplated.setFloors(activtyTemplatedFloorMapper.selectByTemplatedId(templatedId));
return activtyTemplated;
}
}
... ...
... ... @@ -157,6 +157,8 @@ datasources:
- com.yohoufo.dal.resource.ResourcesMapper
- com.yohoufo.dal.resource.ConfigTypeMapper
- com.yohoufo.dal.resource.ResourcesGoodsPoolMapper
- com.yohoufo.dal.resource.ActivtyTemplatedMapper
- com.yohoufo.dal.resource.ActivtyTemplatedFloorMapper
line_shops:
servers:
... ...