From 19112a545edc40747971710d9a0ede815c528937 Mon Sep 17 00:00:00 2001 From: Burce Date: Thu, 22 Aug 2019 19:02:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E6=88=B7=E6=B3=A8=E5=88=B8->=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=BA=93=E5=AD=98=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../market/WxCouponSendConfigController.java | 6 +- .../controller/WxCouponSendController.java | 56 ++++++++++-- .../iformall/schedule/CouponSendSchedule.java | 4 +- .../iformall/mapper/WxCouponSendMapper.java | 18 ++++ .../iformall/service/WxCouponSendService.java | 18 +++- .../com/iformall/service/WxOrderService.java | 4 +- .../impl/WxCouponInjectServiceImpl.java | 2 +- .../service/impl/WxCouponSendServiceImpl.java | 37 +++++++- .../service/impl/WxOrderServiceImpl.java | 86 ++++++++++++++++++- .../resources/mapper/WxCouponSendMapper.xml | 9 +- 10 files changed, 214 insertions(+), 26 deletions(-) diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponSendConfigController.java b/mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponSendConfigController.java index d14b77756..001d88799 100644 --- a/mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponSendConfigController.java +++ b/mallinkAdmin/src/main/java/com/iformall/controller/market/WxCouponSendConfigController.java @@ -38,12 +38,8 @@ public class WxCouponSendConfigController extends BaseController { PageInfo page = wxCouponSendConfigService.listAsPage(wxCouponSendConfig, 1, 1); if (page.getSize() > 0) { return new ResultData(page.getList().get(0)); - } else { - //默认停用 - wxCouponSendConfig.setRemark(EnumCouponSendSendType.getEnum(wxCouponSendConfig.getSendType()).getMessage() + "开关"); - wxCouponSendConfig.setValue(0); - return new ResultData(wxCouponSendConfig); } + return new ResultData(); } diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxCouponSendController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxCouponSendController.java index a36bf3942..52a3041d8 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxCouponSendController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxCouponSendController.java @@ -4,16 +4,25 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; import com.iformall.domain.po.BaseEntity; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.WxCouponOrder; import com.iformall.domain.po.WxCouponSend; import com.iformall.domain.vo.WxCouponSendVo; +import com.iformall.enums.EnumCouponSendSendType; import com.iformall.enums.EnumCouponSendStatus; import com.iformall.exception.MallinkException; +import com.iformall.mapper.WxCUserMapper; +import com.iformall.mapper.WxCouponActionLogMapper; +import com.iformall.mapper.WxCouponSendMapper; import com.iformall.service.WxCouponActionLogService; import com.iformall.service.WxCouponSendService; +import com.iformall.service.WxCouponService; +import com.iformall.service.WxOrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +31,10 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; import java.util.Objects; @RestController @@ -30,18 +42,25 @@ import java.util.Objects; @Api(description = "商户注券相关接口") public class WxCouponSendController extends BaseController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); - + @Resource + private WxCouponSendMapper wxCouponSendMapper; @Autowired private WxCouponSendService wxCouponSendService; @Autowired private WxCouponActionLogService wxCouponActionLogService; + @Autowired + private WxOrderService wxOrderService; + + @Resource + private WxCUserMapper wxCUserMapper; + @ApiOperation("查询商户注券列表") @GetMapping("/list") @ApiImplicitParams({ @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), - @ApiImplicitParam(name = "merchantId", value = "商户ID", dataType = "long", paramType = "query",required = true), + @ApiImplicitParam(name = "merchantId", value = "商户ID", dataType = "long", paramType = "query", required = true), }) public ResultData list(WxCouponSend wxCouponSend, Integer pageNum, Integer pageSize) { logger.debug("[" + getIpAddr() + "] WxCouponSendController::list"); @@ -64,13 +83,36 @@ public class WxCouponSendController extends BaseController { @ApiOperation("商户注券") @GetMapping("/handSel") @ApiImplicitParams({ - @ApiImplicitParam(name = "wxCouponSendId", value = "wxCouponSendId", dataType = "long", paramType = "query",required = true), - @ApiImplicitParam(name = "cUserId", value = "用户ID", dataType = "long", paramType = "query",required = true), + @ApiImplicitParam(name = "wxCouponSendId", value = "wxCouponSendId", dataType = "long", paramType = "query", required = true), + @ApiImplicitParam(name = "cUserId", value = "用户ID", dataType = "long", paramType = "query", required = true), }) - public ResultData handSel(Long[] wxCouponSendIds,Long cUserId) { - if(ArrayUtils.isEmpty(wxCouponSendIds)||Objects.isNull(cUserId)) { - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL); + public ResultData handSel(Long[] wxCouponSendIds, Long cUserId) { + WxCUser cu = wxCUserMapper.selectByPrimaryKey(cUserId); + if (Objects.isNull(cu)) { + throw new MallinkException(ErrorCode.USER_IS_EMPTY); } + if (ArrayUtils.isEmpty(wxCouponSendIds) || Objects.isNull(cUserId)) { + throw new MallinkException(ErrorCode.COUPON_IS_EMPTY); + } + WxCouponSend wxCouponSend = new WxCouponSend(); + wxCouponSend.setIds(Arrays.asList(wxCouponSendIds)); + wxCouponSend.setTenantId(getTenantId()); + wxCouponSend.setSendType(EnumCouponSendSendType.MERCHANT.getCode()); + wxCouponSend.setStatus(EnumCouponSendStatus.VALID.getCode()); + List couponSendList = wxCouponSendMapper.findListVo(wxCouponSend); + if (CollectionUtils.isEmpty(couponSendList)) { + throw new MallinkException(ErrorCode.COUPON_IS_EMPTY); + } + couponSendList.forEach(cs -> { + // 发放免费券 + try { + WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(), cs); + wxCouponActionLogService.addOne(cu.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId()); + } catch (Exception e) { + logger.error("定时发券:发券失败 levelId=" + cu.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage()); + } + }); + return new ResultData(); } diff --git a/mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java b/mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java index 8981125bf..688c3b984 100644 --- a/mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java +++ b/mallinkSchedule/src/main/java/com/iformall/schedule/CouponSendSchedule.java @@ -180,7 +180,7 @@ public class CouponSendSchedule { // 发放免费券 try { - WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId()); + WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(),null); wxCouponActionLogService.addOne(l.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId()); } catch (Exception e) { logger.error("定时发券:发券失败 levelId=" + l.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage()); @@ -304,7 +304,7 @@ public class CouponSendSchedule { } // 发放免费券 try { - WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId()); + WxCouponOrder couponOrder = wxOrderService.sendFreeCouponToUser(cu.getId(), cs.getCouponId(),null); wxCouponActionLogService.addOne(cu.getTenantId(), cs.getCouponId(), couponOrder.getId(), cs.getSendType(), cs.getId()); } catch (Exception e) { logger.error("定时发券:发券失败 levelId=" + cu.getId() + " couponId=" + cs.getCouponId() + " userId=" + cu.getId() + e.getMessage()); diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxCouponSendMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxCouponSendMapper.java index aaff7dba7..bef0407fb 100644 --- a/mallinkService/src/main/java/com/iformall/mapper/WxCouponSendMapper.java +++ b/mallinkService/src/main/java/com/iformall/mapper/WxCouponSendMapper.java @@ -16,4 +16,22 @@ public interface WxCouponSendMapper extends CommonMapper { void updateBirthdayConfig(WxCouponSend wxCouponSend); + /** + * 商户注券 库存减少 + * + * @param id 券ID + * @param remainInventory 当前库存 + * @param number 减少数量 + */ + Integer reduceMerchantRemainInventory(Long id, Integer remainInventory, Integer number); + + /** + * 商户注券 库存退回 + * + * @param id 券ID + * @param remainInventory 当前库存 + * @param number 回退数量 + */ + Integer backMerchantRemainInventory(Long id, Integer remainInventory, Integer number); + } diff --git a/mallinkService/src/main/java/com/iformall/service/WxCouponSendService.java b/mallinkService/src/main/java/com/iformall/service/WxCouponSendService.java index e3416082e..722f8f5ad 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCouponSendService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCouponSendService.java @@ -72,9 +72,23 @@ public interface WxCouponSendService { */ WxCouponSend getConfig(Integer sendType,String tenantId) ; + /** + * 商户注券 库存减少 + * + * @param id 券ID + * @param remainInventory 当前库存 + * @param number 减少数量 + */ + void reduceMerchantRemainInventory(Long id, Integer remainInventory, Integer number); + /** + * 商户注券 库存退回 + * + * @param id 券ID + * @param remainInventory 当前库存 + * @param number 回退数量 + */ + void backMerchantRemainInventory(Long id, Integer remainInventory, Integer number); - - } diff --git a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java index ce026d370..6158c90eb 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java @@ -4,6 +4,7 @@ import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; import com.iformall.domain.dto.OrderSaveDto; import com.iformall.domain.po.*; +import com.iformall.domain.vo.WxCouponSendVo; import com.iformall.domain.vo.WxOrderCouponPressVo; import com.iformall.domain.vo.WxOrderCouponVo; import com.iformall.domain.vo.WxOrderQueryVo; @@ -55,9 +56,10 @@ public interface WxOrderService { * 免费券订单接口 * @param userId * @param couponId + * @param wxCouponSendVo 商户注券时必须指定 * @return WxCouponOrder */ - WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId); + WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId, WxCouponSendVo wxCouponSendVo); /** * orderSuccess 订单已支付 diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java index 03112a7e6..3b983a92b 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java @@ -272,7 +272,7 @@ public class WxCouponInjectServiceImpl implements WxCouponInjectService { // 发放免费券 WxCouponOrder couponOrder = null; try { - couponOrder = wxOrderService.sendFreeCouponToUser(tempCUser.getId(), wxCoupon.getId()); + couponOrder = wxOrderService.sendFreeCouponToUser(tempCUser.getId(), wxCoupon.getId(),null); if (couponOrder != null) { wxCouponActionLogService.addOne(tempCUser.getTenantId(), wxCoupon.getId(), couponOrder.getId(), EnumCouponSendSendType.INJECT.getCode(), couponInjectId); } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java index 39b39c4ef..dc306421b 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCouponSendServiceImpl.java @@ -25,6 +25,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -63,6 +64,8 @@ import java.util.*; WxAuthorizerInfoMapper authorizerInfoMapper; @Autowired WxMsgLimitService wxMsgLimitService; + @Autowired + WxCouponMerchantMapper wxCouponMerchantMapper ; @Override public PageInfo listAsPage(WxCouponSend record, Integer pageIndex, Integer pageSize) { @@ -109,11 +112,25 @@ import java.util.*; if(Objects.isNull(wxCouponOfDb)) { throw new MallinkException(ErrorCode.COUPON_IS_EMPTY) ; } + String merchantIdStr = jo.getString("id") ; + if(Objects.isNull(merchantIdStr)) { + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND) ; + } + WxCouponMerchant couponMerchantQ = new WxCouponMerchant(); + couponMerchantQ.setTenantId(record.getTenantId()); + couponMerchantQ.setProductId(record.getCouponId()); + couponMerchantQ.setMerchantId(Long.parseLong(merchantIdStr)); + couponMerchantQ.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode()); + WxCouponMerchant couponMerchant = wxCouponMerchantMapper.selectOne(couponMerchantQ) ; + if(Objects.isNull(couponMerchant)) { + throw new MallinkException(ErrorCode.COUPON_MERCHANT_NOT_FOUND) ; + } int merchantLnventory = jo.getInteger(WxCouponSend.KEY_MERCHANT_LNVENTORY) ; //商家购券数不能大于总库存 if(merchantLnventory > wxCouponOfDb.getRemainInventory()) { throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY) ; } + //更新库存 wxCouponService.reduceRemainInventory(wxCouponOfDb.getId(),wxCouponOfDb.getRemainInventory(),merchantLnventory); } @@ -146,7 +163,7 @@ import java.util.*; throw new MallinkException(ErrorCode.COUPON_SEND_LIMIT_VERIFY) ; } int merchantLnventory = jo.getInteger(WxCouponSend.KEY_MERCHANT_LNVENTORY) ; - //退回库存 + //退回coupon库存 wxCouponService.backRemainInventory(queryById.getId(),wxCouponOfDb.getRemainInventory(),merchantLnventory); } wxCouponSendMapper.updateByPrimaryKeySelective(record); @@ -298,7 +315,7 @@ import java.util.*; // 发放免费券 WxCouponOrder couponOrder = null; try { - couponOrder = wxOrderService.sendFreeCouponToUser(cUserId, send.getCouponId()); + couponOrder = wxOrderService.sendFreeCouponToUser(cUserId, send.getCouponId(),null); if (couponOrder != null) { bRet = true; @@ -517,4 +534,20 @@ import java.util.*; } return wxCouponSendList.get(0); } + + @Override + public void reduceMerchantRemainInventory(Long id, Integer remainInventory, Integer number) { + int num = wxCouponSendMapper.reduceMerchantRemainInventory(id, remainInventory, number); + if (num == 0) { + throw new MallinkException(ErrorCode.ORDER_IS_FAIL); + } + } + + @Override + public void backMerchantRemainInventory(Long id, Integer remainInventory, Integer number) { + int num = wxCouponSendMapper.backMerchantRemainInventory(id, remainInventory, number); + if (num == 0) { + throw new MallinkException(ErrorCode.ORDER_IS_FAIL); + } + } } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java index bccba4d51..cb0b05064 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java @@ -121,6 +121,9 @@ public class WxOrderServiceImpl implements WxOrderService { @Autowired private WxMsgLimitService wxMsgLimitService; + @Autowired + private WxCouponSendService wxCouponSendService; + @Override public PageInfo listAsPage(WxOrder record, Integer pageIndex, Integer pageSize) { return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxOrderMapper.findList(record)); @@ -302,6 +305,78 @@ public class WxOrderServiceImpl implements WxOrderService { } + /** + * 商户注券减库存 + * @param user + * @param coupon + * @param couponIdStr + * @param wxCouponSendVo + */ + private void stockMerchantReduce(WxCUser user, WxCoupon coupon, String couponIdStr, WxCouponSendVo wxCouponSendVo) { + long time = System.currentTimeMillis() + RedisLock.TIMEOUT; + String timeStr = String.valueOf(time); + // 库存加锁 + if (!redisLock.lock(couponIdStr, timeStr)) { + logger.error("此券被锁定, couponId: " + couponIdStr); + throw new MallinkException(ErrorCode.TOO_MANY_REQUEST); + } + + JSONObject jo = JSONObject.parseObject(wxCouponSendVo.getConditions()) ; + int merchantLnventory = jo.getInteger(WxCouponSend.KEY_MERCHANT_LNVENTORY) ; + + // 检查 优惠券 库存 + if (merchantLnventory <= 0) { + //解锁 + redisLock.unlock(couponIdStr, timeStr); + logger.error("此券库存为0, couponId: " + couponIdStr); + throw new MallinkException(ErrorCode.REMAIN_IS_EMPTY); + } + + int count = 0; + // 有价券 TODO 当前只支持系统券(免费券) +// if (coupon.getSalePrice() > 0) { +// // 检查是否未支付订单 +// try { +// count = getUserOrderCount(user, coupon); +// } catch (Exception e) { +// //解锁 +// redisLock.unlock(couponIdStr, timeStr); +// throw new MallinkException(ErrorCode.DB_FAIL); +// } +// if (count > 0) { +// //解锁 +// redisLock.unlock(couponIdStr, timeStr); +// logger.error("此券有未支付的订单, couponId: " + couponIdStr + ", count: " + count); +// throw new MallinkException(ErrorCode.ORDER_UNPAID); +// } +// } + // 检查用户已购买数量 + try { + count = getUserCouponOrderCount(user, coupon); + } catch (Exception e) { + //解锁 + redisLock.unlock(couponIdStr, timeStr); + throw new MallinkException(ErrorCode.DB_FAIL); + } + if (count >= coupon.getUseLimitQuantity()) { + //解锁 + redisLock.unlock(couponIdStr, timeStr); + logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); + throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); + } + + try { + // 减库存 + wxCouponSendService.reduceMerchantRemainInventory(wxCouponSendVo.getId(),merchantLnventory,1); + } catch (RuntimeException e) { + logger.error("此券减库存失败, couponId: " + couponIdStr); + throw new MallinkException(ErrorCode.ORDER_IS_FAIL); + } finally { + //解锁 + redisLock.unlock(couponIdStr, timeStr); + } + } + /** * 减库存 @@ -612,7 +687,7 @@ public class WxOrderServiceImpl implements WxOrderService { @Override @Transactional(propagation = Propagation.NESTED, readOnly = false, rollbackFor = {Exception.class}) - public WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId) { + public WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId,WxCouponSendVo wxCouponSendVo) { // check 用户状态 WxCUser user = null; try { @@ -641,8 +716,13 @@ public class WxOrderServiceImpl implements WxOrderService { throw new MallinkException(ErrorCode.COUPON_IS_NOT_FREE); } - // 减库存操作 - stockReduce(user, coupon, couponIdStr); + if (Objects.nonNull(wxCouponSendVo) && Objects.equals(EnumCouponSendSendType.MERCHANT.getCode(), wxCouponSendVo.getSendType())) { + // 商户注券减库存操作 + stockMerchantReduce(user,coupon,couponIdStr,wxCouponSendVo); + } else { + // 减库存操作 + stockReduce(user, coupon, couponIdStr); + } int payment = coupon.getSalePrice(); diff --git a/mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml b/mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml index 9feb9b823..93dd8ed2c 100644 --- a/mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCouponSendMapper.xml @@ -143,7 +143,10 @@ where c.id = cs.coupon_id and cs.status = 0 and ((c.status = 1) or (c.valid_type = 1 and c.valid_end_date < now())) - - - + + update wx_coupon_send SET conditions = JSON_SET(conditions,'$.merchantLnventory',#{remainInventory} - #{number}) where id = #{id} and conditions->'$.merchantLnventory' = #{remainInventory} + + + update wx_coupon_send SET conditions = JSON_SET(conditions,'$.merchantLnventory',#{remainInventory} + #{number}) where id = #{id} and conditions->'$.merchantLnventory' = #{remainInventory} +