diff --git a/mobile-web/src/api/promotion.js b/mobile-web/src/api/promotion.js index 4b74b1b7a..37a96ff50 100644 --- a/mobile-web/src/api/promotion.js +++ b/mobile-web/src/api/promotion.js @@ -20,4 +20,24 @@ export function getProductRecommendList() { // Coupon Template +export function getCouponTemplate(id) { + return request({ + url: '/promotion-api/users/coupon/template/get', + method: 'get', + params: { + id, + } + }); +} + +export function doAddCouponCard(templateId) { + return request({ + url: '/promotion-api/users/coupon/card/add', + method: 'post', + params: { + templateId, + } + }); +} + // Coupon Card diff --git a/mobile-web/src/api/user.js b/mobile-web/src/api/user.js index d0f768ddf..f9c7ec30e 100644 --- a/mobile-web/src/api/user.js +++ b/mobile-web/src/api/user.js @@ -81,7 +81,7 @@ export function getUserInfo() { export function doUserUpdateNickname(nickname) { return request({ - url: 'user-api/users/user/update_nickname', + url: '/user-api/users/user/update_nickname', method: 'post', params: { nickname, @@ -91,7 +91,7 @@ export function doUserUpdateNickname(nickname) { export function doPassportMobileRegister(mobile, code) { return request({ - url: 'user-api/users/passport/mobile/register', + url: '/user-api/users/passport/mobile/register', method: 'post', params: { mobile, @@ -102,7 +102,7 @@ export function doPassportMobileRegister(mobile, code) { export function doPassportMobileSendRegisterCode(mobile) { return request({ - url: 'user-api/users/passport/mobile/send_register_code', + url: '/user-api/users/passport/mobile/send_register_code', method: 'post', params: { mobile, diff --git a/mobile-web/src/page/coupon/fetch.vue b/mobile-web/src/page/coupon/fetch.vue index 03165896a..ceff598e7 100644 --- a/mobile-web/src/page/coupon/fetch.vue +++ b/mobile-web/src/page/coupon/fetch.vue @@ -1,9 +1,54 @@ diff --git a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java index 6474ea705..b7ee655c4 100644 --- a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java +++ b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java @@ -2,6 +2,11 @@ package cn.iocoder.mall.promotion.application.config; import cn.iocoder.common.framework.config.GlobalExceptionHandler; import cn.iocoder.common.framework.servlet.CorsFilter; +import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor; +import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor; +import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor; +import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -14,23 +19,31 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc @Configuration @Import(value = {GlobalExceptionHandler.class, // 统一全局返回 -// AdminSecurityInterceptor.class + AdminSecurityInterceptor.class, UserAccessLogInterceptor.class, + UserSecurityInterceptor.class, AdminAccessLogInterceptor.class, }) public class MVCConfiguration implements WebMvcConfigurer { // @Autowired // private UserSecurityInterceptor securityInterceptor; -// @Autowired -// private AdminSecurityInterceptor adminSecurityInterceptor; -// @Autowired -// private AdminAccessLogInterceptor adminAccessLogInterceptor; + @Autowired + private UserSecurityInterceptor userSecurityInterceptor; + @Autowired + private UserAccessLogInterceptor userAccessLogInterceptor; + @Autowired + private AdminSecurityInterceptor adminSecurityInterceptor; + @Autowired + private AdminAccessLogInterceptor adminAccessLogInterceptor; // @Override public void addInterceptors(InterceptorRegistry registry) { -// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口 -// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**"); -// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**"); + // 用户 + registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**"); + registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口 + // 管理员 + registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**"); + registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**"); } @Override @@ -48,4 +61,4 @@ public class MVCConfiguration implements WebMvcConfigurer { return registrationBean; } -} \ No newline at end of file +} diff --git a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/users/UsersCouponController.java b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/users/UsersCouponController.java index 4dc623315..fcf5eb157 100644 --- a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/users/UsersCouponController.java +++ b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/users/UsersCouponController.java @@ -8,18 +8,16 @@ import cn.iocoder.mall.promotion.application.convert.CouponCardConvert; import cn.iocoder.mall.promotion.application.convert.CouponTemplateConvert; import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardVO; import cn.iocoder.mall.promotion.application.vo.users.UsersCouponTemplateVO; +import cn.iocoder.mall.user.sdk.annotation.PermitAll; import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder; import com.alibaba.dubbo.config.annotation.Reference; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("admins/coupon") +@RequestMapping("users/coupon") @Api("优惠劵(码)模块") public class UsersCouponController { @@ -31,6 +29,7 @@ public class UsersCouponController { @GetMapping("/template/get") @ApiOperation(value = "优惠劵(码)模板信息") @ApiImplicitParam(name = "id", value = "优惠劵(码)模板编号", required = true, example = "10") + @PermitAll public CommonResult templateGet(@RequestParam("id") Integer id) { CouponTemplateBO template = couponService.getCouponTemplate(id).getData(); return CommonResult.success(CouponTemplateConvert.INSTANCE.convert2(template)); @@ -38,7 +37,7 @@ public class UsersCouponController { // ========== 优惠劵 ========== - @GetMapping("/card/add") + @PostMapping("/card/add") @ApiOperation(value = "领取优惠劵") @ApiImplicitParam(name = "templateId", value = "优惠劵(码)模板编号", required = true, example = "10") public CommonResult cardAdd(@RequestParam("templateId") Integer templateId) { diff --git a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/PromotionErrorCodeEnum.java b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/PromotionErrorCodeEnum.java index 999b663f2..af574195b 100644 --- a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/PromotionErrorCodeEnum.java +++ b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/PromotionErrorCodeEnum.java @@ -22,7 +22,8 @@ public enum PromotionErrorCodeEnum { PRODUCT_TEMPLATE_NOT_CODE(1006002002, "不是优惠码模板"), PRODUCT_TEMPLATE_TOTAL_CAN_NOT_REDUCE(1006002003, "优惠劵(码)模板的发放数量不能减小"), PRODUCT_TEMPLATE_STATUS_NOT_ENABLE(1006002004, "优惠劵模板(码)未开启"), - + PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH(1006002005, "优惠劵(码)模板的发放量不足"), + PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA(1006002006, "优惠劵领取到达上限"), ; private final int code; diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java index 8560c2e7c..78df37962 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java @@ -15,6 +15,9 @@ public interface CouponCardMapper { Integer selectCountByPage(@Param("status") Integer status); + int selectCountByUserIdAndTemplateId(@Param("userId") Integer userId, + @Param("templateId") Integer templateId); + void insert(CouponCardDO couponCardDO); int update(CouponCardDO couponCardDO); diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java index 7bf2f1639..23195949c 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java @@ -27,4 +27,6 @@ public interface CouponTemplateMapper { int update(CouponTemplateDO couponTemplate); + int updateStatFetchNumIncr(@Param("id") Integer id); + } diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java index 5cd78f229..490057175 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java @@ -19,6 +19,7 @@ import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO; import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.Calendar; import java.util.Date; @@ -176,6 +177,7 @@ public class CouponServiceImpl implements CouponService { // ========== 优惠劵 ========== @Override + @Transactional public CommonResult addCouponCard(Integer userId, Integer couponTemplateId) { // 校验 CouponCardTemplate 存在 CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId); @@ -190,6 +192,19 @@ public class CouponServiceImpl implements CouponService { if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) { return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_STATUS_NOT_ENABLE.getCode()); } + // 校验 CouponCardTemplate 是否到达可领取的上限 + if (template.getStatFetchNum() > template.getTotal()) { + return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH.getCode()); + } + // 校验单人可领取优惠劵是否到达上限 + if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) { + return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode()); + } + // 增加优惠劵已领取量 + int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId); + if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量 + return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode()); + } // 创建优惠劵 // 1. 基本信息 + 领取情况 CouponCardDO card = new CouponCardDO() diff --git a/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml b/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml index 1082ebe80..670822568 100644 --- a/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml +++ b/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml @@ -56,6 +56,20 @@ + + INSERT INTO coupon_card ( template_id, status, user_id, take_type, diff --git a/promotion/promotion-service-impl/src/main/resources/mapper/CouponTemplateMapper.xml b/promotion/promotion-service-impl/src/main/resources/mapper/CouponTemplateMapper.xml index 8a4938ded..3f323a821 100644 --- a/promotion/promotion-service-impl/src/main/resources/mapper/CouponTemplateMapper.xml +++ b/promotion/promotion-service-impl/src/main/resources/mapper/CouponTemplateMapper.xml @@ -149,4 +149,11 @@ WHERE id = #{id} + + UPDATE coupon_template + SET stat_fetch_Num = stat_fetch_Num + 1 + WHERE id = #{id} + AND total > stat_fetch_Num + + diff --git a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java b/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java index 6ac5b0a5c..ac6ff8cbc 100644 --- a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java +++ b/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java @@ -49,4 +49,4 @@ public class MVCConfiguration implements WebMvcConfigurer { return registrationBean; } -} \ No newline at end of file +} diff --git a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserAccessLogAddDTO.java b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserAccessLogAddDTO.java index 1b50edb8a..015ce0d01 100644 --- a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserAccessLogAddDTO.java +++ b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserAccessLogAddDTO.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.experimental.Accessors; import javax.validation.constraints.NotNull; +import java.io.Serializable; import java.util.Date; /** @@ -11,7 +12,7 @@ import java.util.Date; */ @Data @Accessors(chain = true) -public class UserAccessLogAddDTO { +public class UserAccessLogAddDTO implements Serializable { /** * 用户编号 - 空