Browse Source

修复代码生成器

main
科技小王子 2 weeks ago
parent
commit
e3f3b4c4dd
  1. 2
      src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java
  2. 2
      src/main/java/com/gxwebsoft/bszx/controller/BszxPayRankingController.java
  3. 6
      src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java
  4. 14
      src/main/java/com/gxwebsoft/oa/controller/OaAppController.java
  5. 2
      src/main/java/com/gxwebsoft/project/service/impl/ProjectServiceImpl.java
  6. 19
      src/main/java/com/gxwebsoft/shop/controller/ShopCouponController.java
  7. 6
      src/main/java/com/gxwebsoft/shop/controller/ShopGoodsController.java
  8. 18
      src/main/java/com/gxwebsoft/shop/controller/ShopGoodsCouponController.java
  9. 46
      src/main/java/com/gxwebsoft/shop/entity/ShopCoupon.java
  10. 9
      src/main/java/com/gxwebsoft/shop/entity/ShopGoodsCoupon.java
  11. 11
      src/main/java/com/gxwebsoft/shop/mapper/ShopCouponMapper.java
  12. 2
      src/main/java/com/gxwebsoft/shop/mapper/ShopGoodsCouponMapper.java
  13. 24
      src/main/java/com/gxwebsoft/shop/mapper/xml/ShopCouponMapper.xml
  14. 32
      src/main/java/com/gxwebsoft/shop/param/ShopCouponParam.java
  15. 3
      src/main/java/com/gxwebsoft/shop/param/ShopGoodsCouponParam.java
  16. 27
      src/main/java/com/gxwebsoft/shop/service/ShopCouponService.java
  17. 2
      src/main/java/com/gxwebsoft/shop/service/ShopGoodsCouponService.java
  18. 433
      src/main/java/com/gxwebsoft/shop/service/impl/CouponBusinessServiceImpl.java
  19. 89
      src/main/java/com/gxwebsoft/shop/service/impl/ShopCouponServiceImpl.java
  20. 2
      src/main/java/com/gxwebsoft/shop/service/impl/ShopGoodsCouponServiceImpl.java
  21. 403
      src/main/java/com/gxwebsoft/shop/service/impl/ShopUserCouponServiceImpl.java
  22. 8
      src/test/java/com/gxwebsoft/generator/ShopGenerator.java
  23. 24
      src/test/java/com/gxwebsoft/generator/templates/controller.java.btl
  24. 7
      src/test/java/com/gxwebsoft/generator/templates/entity.java.btl
  25. 2
      src/test/java/com/gxwebsoft/generator/templates/index.ts.btl
  26. 2
      src/test/java/com/gxwebsoft/generator/templates/model.ts.btl
  27. 7
      src/test/java/com/gxwebsoft/generator/templates/param.java.btl
  28. 199
      src/test/java/com/gxwebsoft/shop/service/OrderBusinessServiceTest.java

2
src/main/java/com/gxwebsoft/bszx/controller/BszxPayController.java

@ -195,7 +195,7 @@ public class BszxPayController extends BaseController {
final HashMap<String, Object> map = new HashMap<>(); final HashMap<String, Object> map = new HashMap<>();
final LambdaQueryWrapper<BszxPay> wrapper = new LambdaQueryWrapper<>(); final LambdaQueryWrapper<BszxPay> wrapper = new LambdaQueryWrapper<>();
final BigDecimal bigDecimal = bszxPayService.sumMoney(wrapper); final BigDecimal bigDecimal = bszxPayService.sumMoney(wrapper);
Long count = bszxPayService.count(new LambdaQueryWrapper<BszxPay>());
Long count = (long) bszxPayService.count(new LambdaQueryWrapper<BszxPay>());
map.put("numbers", count); map.put("numbers", count);
map.put("totalMoney", bigDecimal); map.put("totalMoney", bigDecimal);
return success(map); return success(map);

2
src/main/java/com/gxwebsoft/bszx/controller/BszxPayRankingController.java

@ -85,7 +85,7 @@ public class BszxPayRankingController extends BaseController {
wrapper.eq(BszxPay::getFormId, item.getArticleId()); wrapper.eq(BszxPay::getFormId, item.getArticleId());
ranking.setFormId(item.getArticleId()); ranking.setFormId(item.getArticleId());
ranking.setFormName(item.getTitle()); ranking.setFormName(item.getTitle());
ranking.setNumber(bszxPayService.count(wrapper));
ranking.setNumber((long) bszxPayService.count(wrapper));
ranking.setTotalPrice(bszxPayService.sumMoney(wrapper)); ranking.setTotalPrice(bszxPayService.sumMoney(wrapper));
rankings.add(ranking); rankings.add(ranking);
}); });

6
src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java

@ -235,17 +235,17 @@ public class CmsArticleController extends BaseController {
wrapper.eq(CmsArticle::getMerchantId, param.getMerchantId()); wrapper.eq(CmsArticle::getMerchantId, param.getMerchantId());
} }
Long totalNum = cmsArticleService.count(
long totalNum = cmsArticleService.count(
wrapper.eq(CmsArticle::getDeleted, 0).eq(CmsArticle::getStatus, 0) wrapper.eq(CmsArticle::getDeleted, 0).eq(CmsArticle::getStatus, 0)
); );
data.put("totalNum", Math.toIntExact(totalNum)); data.put("totalNum", Math.toIntExact(totalNum));
Long totalNum2 = cmsArticleService.count(
long totalNum2 = cmsArticleService.count(
wrapper.eq(CmsArticle::getStatus, 1) wrapper.eq(CmsArticle::getStatus, 1)
); );
data.put("totalNum2", Math.toIntExact(totalNum2)); data.put("totalNum2", Math.toIntExact(totalNum2));
Long totalNum3 = cmsArticleService.count(
long totalNum3 = cmsArticleService.count(
wrapper.gt(CmsArticle::getStatus, 1) wrapper.gt(CmsArticle::getStatus, 1)
); );
data.put("totalNum3", Math.toIntExact(totalNum3)); data.put("totalNum3", Math.toIntExact(totalNum3));

14
src/main/java/com/gxwebsoft/oa/controller/OaAppController.java

@ -201,31 +201,31 @@ public class OaAppController extends BaseController {
@GetMapping("/data") @GetMapping("/data")
public ApiResult<Map<String, Integer>> data() { public ApiResult<Map<String, Integer>> data() {
Map<String, Integer> data = new HashMap<>(); Map<String, Integer> data = new HashMap<>();
Long totalNum = oaAppService.count(
long totalNum = oaAppService.count(
new LambdaQueryWrapper<>() new LambdaQueryWrapper<>()
); );
Long totalNum2 = oaAppService.count(
long totalNum2 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "开发中") .eq(OaApp::getAppStatus, "开发中")
); );
Long totalNum3 = oaAppService.count(
long totalNum3 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已上架") .eq(OaApp::getAppStatus, "已上架")
); );
Long totalNum4 = oaAppService.count(
long totalNum4 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已上架") .eq(OaApp::getAppStatus, "已上架")
.eq(OaApp::getShowExpiration,false) .eq(OaApp::getShowExpiration,false)
); );
Long totalNum5 = oaAppService.count(
long totalNum5 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已下架") .eq(OaApp::getAppStatus, "已下架")
); );
Long totalNum6 = oaAppService.count(
long totalNum6 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getShowCase,true) .eq(OaApp::getShowCase,true)
); );
Long totalNum7 = oaAppService.count(
long totalNum7 = oaAppService.count(
new LambdaQueryWrapper<OaApp>() new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getShowIndex, true) .eq(OaApp::getShowIndex, true)
); );

2
src/main/java/com/gxwebsoft/project/service/impl/ProjectServiceImpl.java

@ -258,7 +258,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
// 剩余天数 // 剩余天数
d.setExpiredDays(DateUtil.betweenDay(d.getExpirationTime(), DateUtil.date(), false)); d.setExpiredDays(DateUtil.betweenDay(d.getExpirationTime(), DateUtil.date(), false));
// 续费次数 // 续费次数
d.setRenewCount(projectRenewService.count(new LambdaQueryWrapper<ProjectRenew>().eq(ProjectRenew::getAppId, d.getAppId()).eq(ProjectRenew::getDeleted, 0)));
d.setRenewCount((long) projectRenewService.count(new LambdaQueryWrapper<ProjectRenew>().eq(ProjectRenew::getAppId, d.getAppId()).eq(ProjectRenew::getDeleted, 0)));
}); });
return list; return list;
} }

19
src/main/java/com/gxwebsoft/shop/controller/ShopCouponController.java

@ -1,14 +1,15 @@
package com.gxwebsoft.shop.controller; package com.gxwebsoft.shop.controller;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.entity.ShopCoupon; import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.param.ShopCouponParam; import com.gxwebsoft.shop.param.ShopCouponParam;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -21,7 +22,7 @@ import java.util.List;
* 优惠券控制器 * 优惠券控制器
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:02
*/ */
@Tag(name = "优惠券管理") @Tag(name = "优惠券管理")
@RestController @RestController
@ -31,7 +32,7 @@ public class ShopCouponController extends BaseController {
private ShopCouponService shopCouponService; private ShopCouponService shopCouponService;
@PreAuthorize("hasAuthority('shop:shopCoupon:list')") @PreAuthorize("hasAuthority('shop:shopCoupon:list')")
@Operation(summary = "批量修改优惠券")
@Operation(summary = "分页查询优惠券")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<ShopCoupon>> page(ShopCouponParam param) { public ApiResult<PageResult<ShopCoupon>> page(ShopCouponParam param) {
// 使用关联查询 // 使用关联查询
@ -104,6 +105,7 @@ public class ShopCouponController extends BaseController {
} }
@PreAuthorize("hasAuthority('shop:shopCoupon:update')") @PreAuthorize("hasAuthority('shop:shopCoupon:update')")
@OperationLog
@Operation(summary = "批量修改优惠券") @Operation(summary = "批量修改优惠券")
@PutMapping("/batch") @PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopCoupon> batchParam) { public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopCoupon> batchParam) {
@ -114,6 +116,7 @@ public class ShopCouponController extends BaseController {
} }
@PreAuthorize("hasAuthority('shop:shopCoupon:remove')") @PreAuthorize("hasAuthority('shop:shopCoupon:remove')")
@OperationLog
@Operation(summary = "批量删除优惠券") @Operation(summary = "批量删除优惠券")
@DeleteMapping("/batch") @DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {

6
src/main/java/com/gxwebsoft/shop/controller/ShopGoodsController.java

@ -136,19 +136,19 @@ public class ShopGoodsController extends BaseController {
wrapper.eq(ShopGoods::getMerchantId,param.getMerchantId()); wrapper.eq(ShopGoods::getMerchantId,param.getMerchantId());
} }
Long totalNum = shopGoodsService.count(
long totalNum = shopGoodsService.count(
wrapper.eq(ShopGoods::getStatus,0).gt(ShopGoods::getStock,0) wrapper.eq(ShopGoods::getStatus,0).gt(ShopGoods::getStock,0)
); );
data.put("totalNum", Math.toIntExact(totalNum)); data.put("totalNum", Math.toIntExact(totalNum));
wrapper.clear(); wrapper.clear();
Long totalNum2 = shopGoodsService.count(
long totalNum2 = shopGoodsService.count(
wrapper.gt(ShopGoods::getStatus,0) wrapper.gt(ShopGoods::getStatus,0)
); );
data.put("totalNum2", Math.toIntExact(totalNum2)); data.put("totalNum2", Math.toIntExact(totalNum2));
wrapper.clear(); wrapper.clear();
Long totalNum3 = shopGoodsService.count(
long totalNum3 = shopGoodsService.count(
wrapper.eq(ShopGoods::getStock,0) wrapper.eq(ShopGoods::getStock,0)
); );
data.put("totalNum3", Math.toIntExact(totalNum3)); data.put("totalNum3", Math.toIntExact(totalNum3));

18
src/main/java/com/gxwebsoft/shop/controller/ShopGoodsCouponController.java

@ -10,8 +10,8 @@ import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -22,7 +22,7 @@ import java.util.List;
* 商品优惠券表控制器 * 商品优惠券表控制器
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
@Tag(name = "商品优惠券表管理") @Tag(name = "商品优惠券表管理")
@RestController @RestController
@ -31,6 +31,7 @@ public class ShopGoodsCouponController extends BaseController {
@Resource @Resource
private ShopGoodsCouponService shopGoodsCouponService; private ShopGoodsCouponService shopGoodsCouponService;
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:list')")
@Operation(summary = "分页查询商品优惠券表") @Operation(summary = "分页查询商品优惠券表")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<ShopGoodsCoupon>> page(ShopGoodsCouponParam param) { public ApiResult<PageResult<ShopGoodsCoupon>> page(ShopGoodsCouponParam param) {
@ -38,6 +39,7 @@ public class ShopGoodsCouponController extends BaseController {
return success(shopGoodsCouponService.pageRel(param)); return success(shopGoodsCouponService.pageRel(param));
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:list')")
@Operation(summary = "查询全部商品优惠券表") @Operation(summary = "查询全部商品优惠券表")
@GetMapping() @GetMapping()
public ApiResult<List<ShopGoodsCoupon>> list(ShopGoodsCouponParam param) { public ApiResult<List<ShopGoodsCoupon>> list(ShopGoodsCouponParam param) {
@ -53,6 +55,8 @@ public class ShopGoodsCouponController extends BaseController {
return success(shopGoodsCouponService.getByIdRel(id)); return success(shopGoodsCouponService.getByIdRel(id));
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:save')")
@OperationLog
@Operation(summary = "添加商品优惠券表") @Operation(summary = "添加商品优惠券表")
@PostMapping() @PostMapping()
public ApiResult<?> save(@RequestBody ShopGoodsCoupon shopGoodsCoupon) { public ApiResult<?> save(@RequestBody ShopGoodsCoupon shopGoodsCoupon) {
@ -67,6 +71,8 @@ public class ShopGoodsCouponController extends BaseController {
return fail("添加失败"); return fail("添加失败");
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:update')")
@OperationLog
@Operation(summary = "修改商品优惠券表") @Operation(summary = "修改商品优惠券表")
@PutMapping() @PutMapping()
public ApiResult<?> update(@RequestBody ShopGoodsCoupon shopGoodsCoupon) { public ApiResult<?> update(@RequestBody ShopGoodsCoupon shopGoodsCoupon) {
@ -76,6 +82,8 @@ public class ShopGoodsCouponController extends BaseController {
return fail("修改失败"); return fail("修改失败");
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:remove')")
@OperationLog
@Operation(summary = "删除商品优惠券表") @Operation(summary = "删除商品优惠券表")
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) { public ApiResult<?> remove(@PathVariable("id") Integer id) {
@ -85,6 +93,8 @@ public class ShopGoodsCouponController extends BaseController {
return fail("删除失败"); return fail("删除失败");
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:save')")
@OperationLog
@Operation(summary = "批量添加商品优惠券表") @Operation(summary = "批量添加商品优惠券表")
@PostMapping("/batch") @PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ShopGoodsCoupon> list) { public ApiResult<?> saveBatch(@RequestBody List<ShopGoodsCoupon> list) {
@ -94,6 +104,8 @@ public class ShopGoodsCouponController extends BaseController {
return fail("添加失败"); return fail("添加失败");
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:update')")
@OperationLog
@Operation(summary = "批量修改商品优惠券表") @Operation(summary = "批量修改商品优惠券表")
@PutMapping("/batch") @PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopGoodsCoupon> batchParam) { public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopGoodsCoupon> batchParam) {
@ -103,6 +115,8 @@ public class ShopGoodsCouponController extends BaseController {
return fail("修改失败"); return fail("修改失败");
} }
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:remove')")
@OperationLog
@Operation(summary = "批量删除商品优惠券表") @Operation(summary = "批量删除商品优惠券表")
@DeleteMapping("/batch") @DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {

46
src/main/java/com/gxwebsoft/shop/entity/ShopCoupon.java

@ -1,28 +1,25 @@
package com.gxwebsoft.shop.entity; package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import java.time.LocalDate;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
/** /**
* 优惠券模板
* 优惠券
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:02
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@TableName("shop_coupon")
@Schema(name = "ShopCoupon对象", description = "优惠券模板")
@Schema(name = "ShopCoupon对象", description = "优惠券")
public class ShopCoupon implements Serializable { public class ShopCoupon implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -48,15 +45,6 @@ public class ShopCoupon implements Serializable {
@Schema(description = "最低消费金额") @Schema(description = "最低消费金额")
private BigDecimal minPrice; private BigDecimal minPrice;
@Schema(description = "发放总数量(-1表示无限制)")
private Integer totalCount;
@Schema(description = "已发放数量")
private Integer issuedCount;
@Schema(description = "每人限领数量(-1表示无限制)")
private Integer limitPerUser;
@Schema(description = "到期类型(10领取后生效 20固定时间)") @Schema(description = "到期类型(10领取后生效 20固定时间)")
private Integer expireType; private Integer expireType;
@ -75,8 +63,8 @@ public class ShopCoupon implements Serializable {
@Schema(description = "适用范围配置(json格式)") @Schema(description = "适用范围配置(json格式)")
private String applyRangeConfig; private String applyRangeConfig;
@Schema(description = "是否启用(0禁用 1启用)")
private Integer enabled;
@Schema(description = "是否过期(0未过期 1已过期)")
private Integer isExpire;
@Schema(description = "排序(数字越小越靠前)") @Schema(description = "排序(数字越小越靠前)")
private Integer sortNumber; private Integer sortNumber;
@ -95,9 +83,21 @@ public class ShopCoupon implements Serializable {
private Integer tenantId; private Integer tenantId;
@Schema(description = "创建时间") @Schema(description = "创建时间")
private Date createTime;
private LocalDateTime createTime;
@Schema(description = "修改时间") @Schema(description = "修改时间")
private Date updateTime;
private LocalDateTime updateTime;
@Schema(description = "发放总数量(-1表示无限制)")
private Integer totalCount;
@Schema(description = "已发放数量")
private Integer issuedCount;
@Schema(description = "每人限领数量(-1表示无限制)")
private Integer limitPerUser;
@Schema(description = "是否启用(0禁用 1启用)")
private Boolean enabled;
} }

9
src/main/java/com/gxwebsoft/shop/entity/ShopGoodsCoupon.java

@ -2,11 +2,10 @@ package com.gxwebsoft.shop.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.util.Date;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable; import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -14,7 +13,7 @@ import lombok.EqualsAndHashCode;
* 商品优惠券表 * 商品优惠券表
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@ -48,9 +47,9 @@ public class ShopGoodsCoupon implements Serializable {
private Integer tenantId; private Integer tenantId;
@Schema(description = "注册时间") @Schema(description = "注册时间")
private Date createTime;
private LocalDateTime createTime;
@Schema(description = "修改时间") @Schema(description = "修改时间")
private Date updateTime;
private LocalDateTime updateTime;
} }

11
src/main/java/com/gxwebsoft/shop/mapper/ShopCouponMapper.java

@ -12,7 +12,7 @@ import java.util.List;
* 优惠券Mapper * 优惠券Mapper
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:02
*/ */
public interface ShopCouponMapper extends BaseMapper<ShopCoupon> { public interface ShopCouponMapper extends BaseMapper<ShopCoupon> {
@ -34,13 +34,4 @@ public interface ShopCouponMapper extends BaseMapper<ShopCoupon> {
*/ */
List<ShopCoupon> selectListRel(@Param("param") ShopCouponParam param); List<ShopCoupon> selectListRel(@Param("param") ShopCouponParam param);
/**
* 检查用户是否已领取指定优惠券
*
* @param userId 用户ID
* @param couponId 优惠券模板ID
* @return 已领取数量
*/
int countUserReceivedCoupon(@Param("userId") Integer userId, @Param("couponId") Integer couponId);
} }

2
src/main/java/com/gxwebsoft/shop/mapper/ShopGoodsCouponMapper.java

@ -12,7 +12,7 @@ import java.util.List;
* 商品优惠券表Mapper * 商品优惠券表Mapper
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
public interface ShopGoodsCouponMapper extends BaseMapper<ShopGoodsCoupon> { public interface ShopGoodsCouponMapper extends BaseMapper<ShopGoodsCoupon> {

24
src/main/java/com/gxwebsoft/shop/mapper/xml/ShopCouponMapper.xml

@ -13,6 +13,9 @@
<if test="param.name != null"> <if test="param.name != null">
AND a.name LIKE CONCAT('%', #{param.name}, '%') AND a.name LIKE CONCAT('%', #{param.name}, '%')
</if> </if>
<if test="param.description != null">
AND a.description LIKE CONCAT('%', #{param.description}, '%')
</if>
<if test="param.type != null"> <if test="param.type != null">
AND a.type = #{param.type} AND a.type = #{param.type}
</if> </if>
@ -67,6 +70,18 @@
<if test="param.createTimeEnd != null"> <if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd} AND a.create_time &lt;= #{param.createTimeEnd}
</if> </if>
<if test="param.totalCount != null">
AND a.total_count = #{param.totalCount}
</if>
<if test="param.issuedCount != null">
AND a.issued_count = #{param.issuedCount}
</if>
<if test="param.limitPerUser != null">
AND a.limit_per_user = #{param.limitPerUser}
</if>
<if test="param.enabled != null">
AND a.enabled = #{param.enabled}
</if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
) )
@ -84,13 +99,4 @@
<include refid="selectSql"></include> <include refid="selectSql"></include>
</select> </select>
<!-- 检查用户是否已领取指定优惠券 -->
<select id="countUserReceivedCoupon" resultType="int">
SELECT COUNT(*)
FROM shop_user_coupon
WHERE deleted = 0
AND user_id = #{userId}
AND coupon_id = #{couponId}
</select>
</mapper> </mapper>

32
src/main/java/com/gxwebsoft/shop/param/ShopCouponParam.java

@ -1,20 +1,19 @@
package com.gxwebsoft.shop.param; package com.gxwebsoft.shop.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField; import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType; import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam; import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/** /**
* 优惠券查询参数 * 优惠券查询参数
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:01
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@ -30,6 +29,9 @@ public class ShopCouponParam extends BaseParam {
@Schema(description = "优惠券名称") @Schema(description = "优惠券名称")
private String name; private String name;
@Schema(description = "优惠券描述")
private String description;
@Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)") @Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer type; private Integer type;
@ -60,7 +62,7 @@ public class ShopCouponParam extends BaseParam {
@Schema(description = "有效期结束时间") @Schema(description = "有效期结束时间")
private String endTime; private String endTime;
@Schema(description = "适用范围(10全部商品 20指定商品)")
@Schema(description = "适用范围(10全部商品 20指定商品 30指定分类)")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer applyRange; private Integer applyRange;
@ -75,7 +77,7 @@ public class ShopCouponParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer sortNumber; private Integer sortNumber;
@Schema(description = "状态, 0待使用, 1已使用, 2已失效")
@Schema(description = "状态, 0正常, 1禁用")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer status; private Integer status;
@ -83,8 +85,24 @@ public class ShopCouponParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer deleted; private Integer deleted;
@Schema(description = "用户ID")
@Schema(description = "创建用户ID")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer userId; private Integer userId;
@Schema(description = "发放总数量(-1表示无限制)")
@QueryField(type = QueryType.EQ)
private Integer totalCount;
@Schema(description = "已发放数量")
@QueryField(type = QueryType.EQ)
private Integer issuedCount;
@Schema(description = "每人限领数量(-1表示无限制)")
@QueryField(type = QueryType.EQ)
private Integer limitPerUser;
@Schema(description = "是否启用(0禁用 1启用)")
@QueryField(type = QueryType.EQ)
private Boolean enabled;
} }

3
src/main/java/com/gxwebsoft/shop/param/ShopGoodsCouponParam.java

@ -6,7 +6,6 @@ import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam; import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -14,7 +13,7 @@ import lombok.EqualsAndHashCode;
* 商品优惠券表查询参数 * 商品优惠券表查询参数
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)

27
src/main/java/com/gxwebsoft/shop/service/ShopCouponService.java

@ -11,7 +11,7 @@ import java.util.List;
* 优惠券Service * 优惠券Service
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:02
*/ */
public interface ShopCouponService extends IService<ShopCoupon> { public interface ShopCouponService extends IService<ShopCoupon> {
@ -39,29 +39,4 @@ public interface ShopCouponService extends IService<ShopCoupon> {
*/ */
ShopCoupon getByIdRel(Integer id); ShopCoupon getByIdRel(Integer id);
/**
* 获取可领取的优惠券列表
*
* @param userId 用户ID
* @return List<ShopCoupon>
*/
List<ShopCoupon> getReceivableCoupons(Integer userId);
/**
* 检查优惠券是否可以发放
*
* @param couponId 优惠券ID
* @return boolean
*/
boolean canIssue(Integer couponId);
/**
* 更新优惠券发放数量
*
* @param couponId 优惠券ID
* @param increment 增量
* @return boolean
*/
boolean updateIssuedCount(Integer couponId, int increment);
} }

2
src/main/java/com/gxwebsoft/shop/service/ShopGoodsCouponService.java

@ -11,7 +11,7 @@ import java.util.List;
* 商品优惠券表Service * 商品优惠券表Service
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
public interface ShopGoodsCouponService extends IService<ShopGoodsCoupon> { public interface ShopGoodsCouponService extends IService<ShopGoodsCoupon> {

433
src/main/java/com/gxwebsoft/shop/service/impl/CouponBusinessServiceImpl.java

@ -1,433 +0,0 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import com.gxwebsoft.shop.service.CouponBusinessService;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 优惠券业务服务实现
*
* @author 科技小王子
* @since 2025-08-08 22:00:00
*/
@Slf4j
@Service
public class CouponBusinessServiceImpl implements CouponBusinessService {
@Resource
private ShopUserCouponService shopUserCouponService;
@Resource
private ShopCouponService shopCouponService;
@Resource
private UserService userService;
@Override
public List<ShopUserCoupon> getAvailableCouponsForOrder(Integer userId,
List<Map<String, Object>> goodsItems,
BigDecimal totalAmount) {
if (userId == null || goodsItems == null || goodsItems.isEmpty()) {
return new ArrayList<>();
}
// 获取用户所有可用优惠券
List<ShopUserCoupon> allCoupons = shopUserCouponService.getAvailableCoupons(
userId, null, null, totalAmount);
// 过滤出适用于当前订单的优惠券
return allCoupons.stream()
.filter(coupon -> isValidForOrder(coupon, goodsItems, totalAmount))
.collect(Collectors.toList());
}
@Override
public Map<String, Object> calculateOrderAmountWithCoupon(Long userCouponId,
List<Map<String, Object>> goodsItems,
BigDecimal totalAmount) {
Map<String, Object> result = new HashMap<>();
result.put("valid", false);
result.put("discountAmount", BigDecimal.ZERO);
result.put("finalAmount", totalAmount);
if (userCouponId == null || totalAmount == null) {
result.put("reason", "参数不能为空");
return result;
}
ShopUserCoupon userCoupon = shopUserCouponService.getById(userCouponId);
if (userCoupon == null) {
result.put("reason", "优惠券不存在");
return result;
}
if (!userCoupon.isAvailable()) {
result.put("reason", "优惠券不可用");
return result;
}
if (!isValidForOrder(userCoupon, goodsItems, totalAmount)) {
result.put("reason", "优惠券不适用于当前订单");
return result;
}
BigDecimal discountAmount = shopUserCouponService.calculateDiscountAmount(userCoupon, totalAmount);
BigDecimal finalAmount = totalAmount.subtract(discountAmount);
// 确保最终金额不为负数
if (finalAmount.compareTo(BigDecimal.ZERO) < 0) {
finalAmount = BigDecimal.ZERO;
}
result.put("valid", true);
result.put("discountAmount", discountAmount);
result.put("finalAmount", finalAmount);
result.put("coupon", userCoupon);
return result;
}
@Override
public Map<String, Object> validateCouponForOrder(Long userCouponId,
Integer userId,
List<Map<String, Object>> goodsItems,
BigDecimal totalAmount) {
Map<String, Object> result = new HashMap<>();
if (userCouponId == null || userId == null) {
result.put("valid", false);
result.put("reason", "参数不能为空");
return result;
}
ShopUserCoupon userCoupon = shopUserCouponService.getById(userCouponId);
if (userCoupon == null) {
result.put("valid", false);
result.put("reason", "优惠券不存在");
return result;
}
if (!userCoupon.getUserId().equals(userId)) {
result.put("valid", false);
result.put("reason", "优惠券不属于当前用户");
return result;
}
if (!userCoupon.isAvailable()) {
result.put("valid", false);
result.put("reason", "优惠券不可用或已过期");
return result;
}
if (!isValidForOrder(userCoupon, goodsItems, totalAmount)) {
result.put("valid", false);
result.put("reason", "优惠券不适用于当前订单商品");
return result;
}
result.put("valid", true);
result.put("reason", "优惠券可用");
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int issueWelcomeCoupons(Integer userId) {
if (userId == null) {
return 0;
}
// 查找欢迎优惠券模板(这里假设有特定的标识)
LambdaQueryWrapper<ShopCoupon> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShopCoupon::getEnabled, 1)
.eq(ShopCoupon::getStatus, 0)
.like(ShopCoupon::getName, "新用户")
.or()
.like(ShopCoupon::getName, "欢迎");
List<ShopCoupon> welcomeCoupons = shopCouponService.list(queryWrapper);
int successCount = 0;
for (ShopCoupon coupon : welcomeCoupons) {
if (shopUserCouponService.issueCouponToUser(userId, coupon.getId(), "新用户注册赠送")) {
successCount++;
}
}
log.info("为新用户{}发放欢迎优惠券{}张", userId, successCount);
return successCount;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int issueBirthdayCoupons(Integer userId) {
if (userId == null) {
return 0;
}
User user = userService.getById(userId);
if (user == null || user.getBirthday() == null) {
return 0;
}
// 检查今天是否是用户生日
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.parse((CharSequence) user.getBirthday(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
if (today.getMonthValue() != birthday.getMonthValue() ||
today.getDayOfMonth() != birthday.getDayOfMonth()) {
return 0;
}
// 查找生日优惠券模板
LambdaQueryWrapper<ShopCoupon> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShopCoupon::getEnabled, 1)
.eq(ShopCoupon::getStatus, 0)
.like(ShopCoupon::getName, "生日");
List<ShopCoupon> birthdayCoupons = shopCouponService.list(queryWrapper);
int successCount = 0;
for (ShopCoupon coupon : birthdayCoupons) {
if (shopUserCouponService.issueCouponToUser(userId, coupon.getId(), "生日祝福赠送")) {
successCount++;
}
}
log.info("为用户{}发放生日优惠券{}张", userId, successCount);
return successCount;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int issueConsumeCoupons(Integer userId, BigDecimal consumeAmount) {
if (userId == null || consumeAmount == null || consumeAmount.compareTo(BigDecimal.ZERO) <= 0) {
return 0;
}
// 根据消费金额发放不同的优惠券
List<ShopCoupon> eligibleCoupons = new ArrayList<>();
if (consumeAmount.compareTo(new BigDecimal("100")) >= 0) {
// 消费满100发放优惠券
LambdaQueryWrapper<ShopCoupon> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShopCoupon::getEnabled, 1)
.eq(ShopCoupon::getStatus, 0)
.like(ShopCoupon::getName, "消费返券");
eligibleCoupons.addAll(shopCouponService.list(queryWrapper));
}
int successCount = 0;
for (ShopCoupon coupon : eligibleCoupons) {
if (shopUserCouponService.issueCouponToUser(userId, coupon.getId(),
"消费满" + consumeAmount + "元返券")) {
successCount++;
}
}
log.info("为用户{}消费{}元发放优惠券{}张", userId, consumeAmount, successCount);
return successCount;
}
/**
* 检查优惠券是否适用于订单
*/
private boolean isValidForOrder(ShopUserCoupon userCoupon,
List<Map<String, Object>> goodsItems,
BigDecimal totalAmount) {
if (userCoupon == null || goodsItems == null || goodsItems.isEmpty()) {
return false;
}
// 检查最低消费金额
if (userCoupon.getMinPrice() != null &&
totalAmount.compareTo(userCoupon.getMinPrice()) < 0) {
return false;
}
// 检查适用范围
if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_ALL) {
return true;
} else if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_GOODS) {
// 检查是否有指定商品
return goodsItems.stream().anyMatch(item -> {
Integer goodsId = (Integer) item.get("goodsId");
return shopUserCouponService.validateCouponForGoods(userCoupon, goodsId, null);
});
} else if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_CATEGORY) {
// 检查是否有指定分类的商品
return goodsItems.stream().anyMatch(item -> {
Integer categoryId = (Integer) item.get("categoryId");
return shopUserCouponService.validateCouponForGoods(userCoupon, null, categoryId);
});
}
return false;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> batchIssueActivityCoupons(String activityName,
List<Integer> couponIds,
List<Integer> userIds) {
Map<String, Object> result = new HashMap<>();
result.put("totalUsers", 0);
result.put("totalCoupons", 0);
result.put("successCount", 0);
if (couponIds == null || couponIds.isEmpty()) {
result.put("message", "优惠券列表不能为空");
return result;
}
// 如果没有指定用户,则获取所有活跃用户
if (userIds == null || userIds.isEmpty()) {
userIds = userService.list().stream()
.filter(user -> user.getStatus() == 0) // 只给正常状态的用户发放
.map(User::getUserId)
.collect(Collectors.toList());
}
int totalUsers = userIds.size();
int totalCoupons = couponIds.size() * totalUsers;
int successCount = 0;
String source = activityName != null ? activityName + "活动赠送" : "活动赠送";
for (Integer userId : userIds) {
for (Integer couponId : couponIds) {
if (shopUserCouponService.issueCouponToUser(userId, couponId, source)) {
successCount++;
}
}
}
result.put("totalUsers", totalUsers);
result.put("totalCoupons", totalCoupons);
result.put("successCount", successCount);
result.put("message", String.format("活动优惠券发放完成,共%d个用户,%d张优惠券,成功%d张",
totalUsers, totalCoupons, successCount));
log.info("活动{}批量发放优惠券完成:用户{}个,优惠券{}张,成功{}张",
activityName, totalUsers, totalCoupons, successCount);
return result;
}
@Override
public Map<String, Object> getCouponUsageStatistics(String startDate, String endDate) {
Map<String, Object> result = new HashMap<>();
// 这里可以根据需要实现具体的统计逻辑
// 统计指定时间段内的优惠券使用情况
result.put("totalIssued", 0); // 总发放数量
result.put("totalUsed", 0); // 总使用数量
result.put("totalExpired", 0); // 总过期数量
result.put("usageRate", 0.0); // 使用率
result.put("discountAmount", BigDecimal.ZERO); // 总优惠金额
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int autoProcessExpiredCoupons() {
// 更新过期优惠券状态
int count = shopUserCouponService.updateExpiredCoupons();
log.info("自动处理过期优惠券{}张", count);
return count;
}
@Override
public int sendCouponExpiryReminder(Integer days) {
if (days == null || days <= 0) {
days = 3; // 默认提前3天提醒
}
List<ShopUserCoupon> expiringSoonCoupons = shopUserCouponService.getExpiringSoonCoupons(days);
// 按用户分组
Map<Integer, List<ShopUserCoupon>> userCouponsMap = expiringSoonCoupons.stream()
.collect(Collectors.groupingBy(ShopUserCoupon::getUserId));
int reminderCount = 0;
for (Map.Entry<Integer, List<ShopUserCoupon>> entry : userCouponsMap.entrySet()) {
Integer userId = entry.getKey();
List<ShopUserCoupon> coupons = entry.getValue();
// 这里可以发送消息提醒用户
// 例如:发送站内信、短信、推送通知等
log.info("提醒用户{}有{}张优惠券即将过期", userId, coupons.size());
reminderCount++;
}
log.info("发送优惠券到期提醒给{}个用户", reminderCount);
return reminderCount;
}
@Override
public Map<String, Object> recommendBestCouponCombination(Integer userId,
List<Map<String, Object>> goodsItems,
BigDecimal totalAmount) {
Map<String, Object> result = new HashMap<>();
result.put("coupons", new ArrayList<>());
result.put("totalDiscount", BigDecimal.ZERO);
result.put("finalAmount", totalAmount);
if (userId == null || goodsItems == null || goodsItems.isEmpty() || totalAmount == null) {
return result;
}
// 获取用户所有可用优惠券
List<ShopUserCoupon> availableCoupons = getAvailableCouponsForOrder(userId, goodsItems, totalAmount);
if (availableCoupons.isEmpty()) {
return result;
}
// 简单的贪心算法:选择优惠金额最大的优惠券
// 实际项目中可以实现更复杂的组合优化算法
ShopUserCoupon bestCoupon = null;
BigDecimal maxDiscount = BigDecimal.ZERO;
for (ShopUserCoupon coupon : availableCoupons) {
BigDecimal discount = shopUserCouponService.calculateDiscountAmount(coupon, totalAmount);
if (discount.compareTo(maxDiscount) > 0) {
maxDiscount = discount;
bestCoupon = coupon;
}
}
if (bestCoupon != null) {
List<ShopUserCoupon> recommendedCoupons = new ArrayList<>();
recommendedCoupons.add(bestCoupon);
BigDecimal finalAmount = totalAmount.subtract(maxDiscount);
if (finalAmount.compareTo(BigDecimal.ZERO) < 0) {
finalAmount = BigDecimal.ZERO;
}
result.put("coupons", recommendedCoupons);
result.put("totalDiscount", maxDiscount);
result.put("finalAmount", finalAmount);
}
return result;
}
}

89
src/main/java/com/gxwebsoft/shop/service/impl/ShopCouponServiceImpl.java

@ -1,35 +1,25 @@
package com.gxwebsoft.shop.service.impl; package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.mapper.ShopCouponMapper; import com.gxwebsoft.shop.mapper.ShopCouponMapper;
import com.gxwebsoft.shop.param.ShopCouponParam;
import com.gxwebsoft.shop.service.ShopCouponService; import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import lombok.extern.slf4j.Slf4j;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.param.ShopCouponParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List; import java.util.List;
/** /**
* 优惠券Service实现 * 优惠券Service实现
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-08-08 21:10:55
* @since 2025-08-09 15:26:02
*/ */
@Slf4j
@Service @Service
public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCoupon> implements ShopCouponService { public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCoupon> implements ShopCouponService {
@Resource
private ShopUserCouponService shopUserCouponService;
@Override @Override
public PageResult<ShopCoupon> pageRel(ShopCouponParam param) { public PageResult<ShopCoupon> pageRel(ShopCouponParam param) {
PageParam<ShopCoupon, ShopCouponParam> page = new PageParam<>(param); PageParam<ShopCoupon, ShopCouponParam> page = new PageParam<>(param);
@ -54,73 +44,4 @@ public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCou
return param.getOne(baseMapper.selectListRel(param)); return param.getOne(baseMapper.selectListRel(param));
} }
@Override
public List<ShopCoupon> getReceivableCoupons(Integer userId) {
LambdaQueryWrapper<ShopCoupon> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShopCoupon::getEnabled, 1)
.eq(ShopCoupon::getStatus, 0)
.and(wrapper -> wrapper
.isNull(ShopCoupon::getTotalCount)
.or()
.apply("IFNULL(total_count, 0) = -1")
.or()
.apply("IFNULL(issued_count, 0) < IFNULL(total_count, 0)"))
.orderByAsc(ShopCoupon::getSortNumber)
.orderByDesc(ShopCoupon::getCreateTime);
List<ShopCoupon> allCoupons = list(queryWrapper);
// 过滤掉用户已达到领取上限的优惠券
return allCoupons.stream()
.filter(coupon -> {
if (coupon.getLimitPerUser() == null || coupon.getLimitPerUser() <= 0) {
return true; // 无限制
}
// 检查用户已领取数量
int receivedCount = baseMapper.countUserReceivedCoupon(userId, coupon.getId());
return receivedCount < coupon.getLimitPerUser();
})
.collect(java.util.stream.Collectors.toList());
}
@Override
public boolean canIssue(Integer couponId) {
ShopCoupon coupon = getById(couponId);
if (coupon == null || coupon.getEnabled() != 1 || coupon.getStatus() != 0) {
return false;
}
// 检查发放数量限制
if (coupon.getTotalCount() != null && coupon.getTotalCount() > 0) {
int issuedCount = coupon.getIssuedCount() != null ? coupon.getIssuedCount() : 0;
return issuedCount < coupon.getTotalCount();
}
// 检查有效期
LocalDate now = LocalDate.now();
if (coupon.getExpireType() == 20) { // 固定时间
if (coupon.getStartTime() != null && now.isBefore(coupon.getStartTime())) {
return false; // 还未开始
}
if (coupon.getEndTime() != null && now.isAfter(coupon.getEndTime())) {
return false; // 已过期
}
}
return true;
}
@Override
public boolean updateIssuedCount(Integer couponId, int increment) {
LambdaUpdateWrapper<ShopCoupon> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ShopCoupon::getId, couponId)
.setSql("issued_count = IFNULL(issued_count, 0) + " + increment);
boolean updated = update(updateWrapper);
if (updated) {
log.debug("更新优惠券{}发放数量,增量: {}", couponId, increment);
}
return updated;
}
} }

2
src/main/java/com/gxwebsoft/shop/service/impl/ShopGoodsCouponServiceImpl.java

@ -15,7 +15,7 @@ import java.util.List;
* 商品优惠券表Service实现 * 商品优惠券表Service实现
* *
* @author 科技小王子 * @author 科技小王子
* @since 2025-01-11 10:45:12
* @since 2025-08-09 15:26:02
*/ */
@Service @Service
public class ShopGoodsCouponServiceImpl extends ServiceImpl<ShopGoodsCouponMapper, ShopGoodsCoupon> implements ShopGoodsCouponService { public class ShopGoodsCouponServiceImpl extends ServiceImpl<ShopGoodsCouponMapper, ShopGoodsCoupon> implements ShopGoodsCouponService {

403
src/main/java/com/gxwebsoft/shop/service/impl/ShopUserCouponServiceImpl.java

@ -1,403 +0,0 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import com.gxwebsoft.shop.mapper.ShopUserCouponMapper;
import com.gxwebsoft.shop.param.ShopUserCouponParam;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
/**
* 用户优惠券Service实现
*
* @author 科技小王子
* @since 2025-08-08 21:30:00
*/
@Slf4j
@Service
public class ShopUserCouponServiceImpl extends ServiceImpl<ShopUserCouponMapper, ShopUserCoupon>
implements ShopUserCouponService {
@Resource
private ShopCouponService shopCouponService;
@Override
public PageResult<ShopUserCoupon> pageRel(ShopUserCouponParam param) {
PageParam<ShopUserCoupon, ShopUserCouponParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ShopUserCoupon> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<ShopUserCoupon> listRel(ShopUserCouponParam param) {
return baseMapper.selectListRel(param);
}
@Override
public ShopUserCoupon getByIdRel(Long id) {
ShopUserCouponParam param = new ShopUserCouponParam();
param.setId(id);
List<ShopUserCoupon> list = baseMapper.selectListRel(param);
return list.isEmpty() ? null : list.get(0);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean receiveCoupon(Integer userId, Integer couponId) {
// 检查是否可以领取
Map<String, Object> checkResult = checkCanReceiveCoupon(userId, couponId);
if (!(Boolean) checkResult.get("canReceive")) {
log.warn("用户{}无法领取优惠券{}: {}", userId, couponId, checkResult.get("reason"));
return false;
}
// 获取优惠券模板
ShopCoupon coupon = shopCouponService.getById(couponId);
if (coupon == null) {
log.warn("优惠券模板不存在: {}", couponId);
return false;
}
// 创建用户优惠券
ShopUserCoupon userCoupon = createUserCouponFromTemplate(coupon, userId);
userCoupon.setObtainType(ShopUserCoupon.OBTAIN_RECEIVE);
userCoupon.setObtainSource("用户主动领取");
// 保存用户优惠券
boolean saved = save(userCoupon);
if (saved) {
// 更新优惠券模板的已发放数量
updateCouponIssuedCount(couponId, 1);
log.info("用户{}成功领取优惠券{}", userId, couponId);
}
return saved;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean issueCouponToUser(Integer userId, Integer couponId, String source) {
// 获取优惠券模板
ShopCoupon coupon = shopCouponService.getById(couponId);
if (coupon == null || coupon.getEnabled() != 1) {
log.warn("优惠券模板不存在或已禁用: {}", couponId);
return false;
}
// 检查发放数量限制
if (coupon.getTotalCount() != null && coupon.getTotalCount() > 0) {
int issuedCount = coupon.getIssuedCount() != null ? coupon.getIssuedCount() : 0;
if (issuedCount >= coupon.getTotalCount()) {
log.warn("优惠券{}发放数量已达上限", couponId);
return false;
}
}
// 创建用户优惠券
ShopUserCoupon userCoupon = createUserCouponFromTemplate(coupon, userId);
userCoupon.setObtainType(ShopUserCoupon.OBTAIN_SYSTEM);
userCoupon.setObtainSource(source != null ? source : "系统发放");
// 保存用户优惠券
boolean saved = save(userCoupon);
if (saved) {
// 更新优惠券模板的已发放数量
updateCouponIssuedCount(couponId, 1);
log.info("系统向用户{}发放优惠券{}", userId, couponId);
}
return saved;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int batchIssueCoupons(List<Integer> userIds, Integer couponId, String source) {
if (userIds == null || userIds.isEmpty()) {
return 0;
}
// 获取优惠券模板
ShopCoupon coupon = shopCouponService.getById(couponId);
if (coupon == null || coupon.getEnabled() != 1) {
log.warn("优惠券模板不存在或已禁用: {}", couponId);
return 0;
}
int successCount = 0;
for (Integer userId : userIds) {
if (issueCouponToUser(userId, couponId, source)) {
successCount++;
}
}
log.info("批量发放优惠券{}给{}个用户,成功{}个", couponId, userIds.size(), successCount);
return successCount;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean useCoupon(Long userCouponId, Long orderId, String orderNo) {
// 获取用户优惠券
ShopUserCoupon userCoupon = getById(userCouponId);
if (userCoupon == null) {
log.warn("用户优惠券不存在: {}", userCouponId);
return false;
}
// 检查优惠券状态
if (!userCoupon.isAvailable()) {
log.warn("优惠券不可用: {}", userCouponId);
return false;
}
// 更新优惠券状态
LambdaUpdateWrapper<ShopUserCoupon> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ShopUserCoupon::getId, userCouponId)
.eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_UNUSED)
.set(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_USED)
.set(ShopUserCoupon::getUseTime, LocalDateTime.now())
.set(ShopUserCoupon::getOrderId, orderId)
.set(ShopUserCoupon::getOrderNo, orderNo);
boolean updated = update(updateWrapper);
if (updated) {
log.info("用户优惠券{}已使用,订单: {}", userCouponId, orderNo);
}
return updated;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean returnCoupon(Long orderId) {
// 查找使用该订单的优惠券
LambdaQueryWrapper<ShopUserCoupon> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShopUserCoupon::getOrderId, orderId)
.eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_USED);
List<ShopUserCoupon> usedCoupons = list(queryWrapper);
if (usedCoupons.isEmpty()) {
return true; // 没有使用优惠券,直接返回成功
}
// 退还优惠券
for (ShopUserCoupon userCoupon : usedCoupons) {
// 检查是否已过期
if (userCoupon.isExpired()) {
// 已过期的券设为过期状态
userCoupon.setStatus(ShopUserCoupon.STATUS_EXPIRED);
} else {
// 未过期的券恢复为未使用状态
userCoupon.setStatus(ShopUserCoupon.STATUS_UNUSED);
}
userCoupon.setUseTime(null);
userCoupon.setOrderId(null);
userCoupon.setOrderNo(null);
updateById(userCoupon);
log.info("退还用户优惠券{},订单: {}", userCoupon.getId(), orderId);
}
return true;
}
/**
* 从优惠券模板创建用户优惠券
*/
private ShopUserCoupon createUserCouponFromTemplate(ShopCoupon coupon, Integer userId) {
ShopUserCoupon userCoupon = new ShopUserCoupon();
userCoupon.setCouponId(coupon.getId());
userCoupon.setUserId(userId);
userCoupon.setName(coupon.getName());
userCoupon.setDescription(coupon.getDescription());
userCoupon.setType(coupon.getType());
userCoupon.setReducePrice(coupon.getReducePrice());
userCoupon.setDiscount(coupon.getDiscount());
userCoupon.setMinPrice(coupon.getMinPrice());
userCoupon.setApplyRange(coupon.getApplyRange());
userCoupon.setApplyRangeConfig(coupon.getApplyRangeConfig());
userCoupon.setStatus(ShopUserCoupon.STATUS_UNUSED);
userCoupon.setTenantId(coupon.getTenantId());
// 设置有效期
LocalDateTime now = LocalDateTime.now();
if (coupon.getExpireType() == 10) {
// 领取后生效
userCoupon.setStartTime(now);
if (coupon.getExpireDay() != null && coupon.getExpireDay() > 0) {
userCoupon.setEndTime(now.plusDays(coupon.getExpireDay()));
}
} else if (coupon.getExpireType() == 20) {
// 固定时间
userCoupon.setStartTime(coupon.getStartTime() != null ?
coupon.getStartTime().atStartOfDay() : now);
userCoupon.setEndTime(coupon.getEndTime() != null ?
coupon.getEndTime().atTime(23, 59, 59) : null);
}
return userCoupon;
}
@Override
public List<ShopUserCoupon> getAvailableCoupons(Integer userId, Integer goodsId,
Integer categoryId, BigDecimal orderAmount) {
ShopUserCouponParam param = new ShopUserCouponParam();
param.setUserId(userId);
param.setStatus(ShopUserCoupon.STATUS_UNUSED);
param.setOnlyAvailable(true);
param.setGoodsId(goodsId);
param.setCategoryId(categoryId);
param.setOrderAmount(orderAmount);
return baseMapper.selectAvailableCoupons(param);
}
@Override
public BigDecimal calculateDiscountAmount(ShopUserCoupon userCoupon, BigDecimal orderAmount) {
if (userCoupon == null || orderAmount == null || orderAmount.compareTo(BigDecimal.ZERO) <= 0) {
return BigDecimal.ZERO;
}
// 检查最低消费金额
if (userCoupon.getMinPrice() != null &&
orderAmount.compareTo(userCoupon.getMinPrice()) < 0) {
return BigDecimal.ZERO;
}
BigDecimal discountAmount = BigDecimal.ZERO;
if (userCoupon.getType() == ShopUserCoupon.TYPE_REDUCE) {
// 满减券
discountAmount = userCoupon.getReducePrice() != null ?
userCoupon.getReducePrice() : BigDecimal.ZERO;
} else if (userCoupon.getType() == ShopUserCoupon.TYPE_DISCOUNT) {
// 折扣券
if (userCoupon.getDiscount() != null && userCoupon.getDiscount() > 0 && userCoupon.getDiscount() < 100) {
BigDecimal discountRate = BigDecimal.valueOf(100 - userCoupon.getDiscount())
.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
discountAmount = orderAmount.multiply(discountRate);
}
} else if (userCoupon.getType() == ShopUserCoupon.TYPE_FREE) {
// 免费券
discountAmount = orderAmount;
}
// 优惠金额不能超过订单金额
return discountAmount.compareTo(orderAmount) > 0 ? orderAmount : discountAmount;
}
@Override
public boolean validateCouponForGoods(ShopUserCoupon userCoupon, Integer goodsId, Integer categoryId) {
if (userCoupon == null || userCoupon.getApplyRange() == null) {
return false;
}
if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_ALL) {
// 全部商品可用
return true;
} else if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_GOODS) {
// 指定商品可用
if (goodsId == null || userCoupon.getApplyRangeConfig() == null) {
return false;
}
// 解析商品ID列表(假设是逗号分隔的字符串)
String[] goodsIds = userCoupon.getApplyRangeConfig().split(",");
return Arrays.asList(goodsIds).contains(goodsId.toString());
} else if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_CATEGORY) {
// 指定分类可用
if (categoryId == null || userCoupon.getApplyRangeConfig() == null) {
return false;
}
// 解析分类ID列表(假设是逗号分隔的字符串)
String[] categoryIds = userCoupon.getApplyRangeConfig().split(",");
return Arrays.asList(categoryIds).contains(categoryId.toString());
}
return false;
}
@Override
public Map<String, Object> countUserCoupons(Integer userId) {
return baseMapper.countUserCoupons(userId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int updateExpiredCoupons() {
return baseMapper.updateExpiredStatus();
}
@Override
public List<ShopUserCoupon> getExpiringSoonCoupons(Integer days) {
return baseMapper.selectExpiringSoon(days != null ? days : 3);
}
@Override
public Map<String, Object> checkCanReceiveCoupon(Integer userId, Integer couponId) {
Map<String, Object> result = new HashMap<>();
// 获取优惠券模板
ShopCoupon coupon = shopCouponService.getById(couponId);
if (coupon == null) {
result.put("canReceive", false);
result.put("reason", "优惠券不存在");
return result;
}
if (coupon.getEnabled() != 1) {
result.put("canReceive", false);
result.put("reason", "优惠券已禁用");
return result;
}
// 检查发放数量限制
if (coupon.getTotalCount() != null && coupon.getTotalCount() > 0) {
int issuedCount = coupon.getIssuedCount() != null ? coupon.getIssuedCount() : 0;
if (issuedCount >= coupon.getTotalCount()) {
result.put("canReceive", false);
result.put("reason", "优惠券已领完");
return result;
}
}
// 检查每人限领数量
if (coupon.getLimitPerUser() != null && coupon.getLimitPerUser() > 0) {
int receivedCount = baseMapper.countUserReceivedCoupon(userId, couponId);
if (receivedCount >= coupon.getLimitPerUser()) {
result.put("canReceive", false);
result.put("reason", "已达到个人领取上限");
return result;
}
}
result.put("canReceive", true);
result.put("reason", "可以领取");
return result;
}
/**
* 更新优惠券模板的已发放数量
*/
private void updateCouponIssuedCount(Integer couponId, int increment) {
LambdaUpdateWrapper<ShopCoupon> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ShopCoupon::getId, couponId)
.setSql("issued_count = IFNULL(issued_count, 0) + " + increment);
shopCouponService.update(updateWrapper);
}
}

8
src/test/java/com/gxwebsoft/generator/ShopGenerator.java

@ -27,9 +27,9 @@ public class ShopGenerator {
// 输出目录 // 输出目录
private static final String OUTPUT_DIR = "/src/main/java"; private static final String OUTPUT_DIR = "/src/main/java";
// Vue文件输出位置 // Vue文件输出位置
private static final String OUTPUT_LOCATION_VUE = "/Users/gxwebsoft/VUE/shop";
private static final String OUTPUT_LOCATION_VUE = "/Users/gxwebsoft/VUE/mp-vue";
// Vue文件输出目录 // Vue文件输出目录
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/APP/shop";
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/VUE/template-10550";
// Vue文件输出目录 // Vue文件输出目录
private static final String OUTPUT_DIR_VUE = "/src"; private static final String OUTPUT_DIR_VUE = "/src";
// 作者名称 // 作者名称
@ -37,7 +37,7 @@ public class ShopGenerator {
// 是否在xml中添加二级缓存配置 // 是否在xml中添加二级缓存配置
private static final boolean ENABLE_CACHE = false; private static final boolean ENABLE_CACHE = false;
// 数据库连接配置 // 数据库连接配置
private static final String DB_URL = "jdbc:mysql://47.119.165.234:3308/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
private static final String DB_URL = "jdbc:mysql://8.134.169.209:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DB_USERNAME = "modules"; private static final String DB_USERNAME = "modules";
private static final String DB_PASSWORD = "8YdLnk7KsPAyDXGA"; private static final String DB_PASSWORD = "8YdLnk7KsPAyDXGA";
@ -55,7 +55,7 @@ public class ShopGenerator {
// "shop_goods_sku", // "shop_goods_sku",
// "shop_goods_category", // "shop_goods_category",
"shop_coupon", "shop_coupon",
// "shop_goods_coupon",
"shop_goods_coupon",
// "shop_goods_description", // "shop_goods_description",
// "shop_goods_log", // "shop_goods_log",
// "shop_goods_relation", // "shop_goods_relation",

24
src/test/java/com/gxwebsoft/generator/templates/controller.java.btl

@ -23,8 +23,8 @@ import ${cfg.packageName!}.common.core.web.PageParam;
import ${cfg.packageName!}.common.core.web.BatchParam; import ${cfg.packageName!}.common.core.web.BatchParam;
import ${cfg.packageName!}.common.core.annotation.OperationLog; import ${cfg.packageName!}.common.core.annotation.OperationLog;
import ${cfg.packageName!}.common.system.entity.User; import ${cfg.packageName!}.common.system.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ -41,7 +41,7 @@ import java.util.List;
* @since ${date(), 'yyyy-MM-dd HH:mm:ss'} * @since ${date(), 'yyyy-MM-dd HH:mm:ss'}
*/ */
<% if(swagger2) { %> <% if(swagger2) { %>
@Api(tags = "${table.comment!}管理")
@Tag(name = "${table.comment!}管理")
<% } %> <% } %>
<% if(restControllerStyle) { %> <% if(restControllerStyle) { %>
@RestController @RestController
@ -68,7 +68,7 @@ public class ${table.controllerName} {
@PreAuthorize("hasAuthority('${authPre}:list')") @PreAuthorize("hasAuthority('${authPre}:list')")
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("分页查询${table.comment!}")
@Operation(summary = "分页查询${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -88,7 +88,7 @@ public class ${table.controllerName} {
@PreAuthorize("hasAuthority('${authPre}:list')") @PreAuthorize("hasAuthority('${authPre}:list')")
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("查询全部${table.comment!}")
@Operation(summary = "查询全部${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -105,7 +105,7 @@ public class ${table.controllerName} {
*/ */
<% } %> <% } %>
@PreAuthorize("hasAuthority('${authPre}:list')") @PreAuthorize("hasAuthority('${authPre}:list')")
@ApiOperation("根据id查询${table.comment!}")
@Operation(summary = "根据id查询${table.comment!}")
@GetMapping("/{id}") @GetMapping("/{id}")
public ApiResult<${entity}> get(@PathVariable("id") Integer id) { public ApiResult<${entity}> get(@PathVariable("id") Integer id) {
// 使用关联查询 // 使用关联查询
@ -124,7 +124,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("添加${table.comment!}")
@Operation(summary = "添加${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -154,7 +154,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("修改${table.comment!}")
@Operation(summary = "修改${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -179,7 +179,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("删除${table.comment!}")
@Operation(summary = "删除${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -204,7 +204,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("批量添加${table.comment!}")
@Operation(summary = "批量添加${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -229,7 +229,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("批量修改${table.comment!}")
@Operation(summary = "批量修改${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody
@ -254,7 +254,7 @@ public class ${table.controllerName} {
@OperationLog @OperationLog
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiOperation("批量删除${table.comment!}")
@Operation(summary = "批量删除${table.comment!}")
<% } %> <% } %>
<% if(!restControllerStyle) { %> <% if(!restControllerStyle) { %>
@ResponseBody @ResponseBody

7
src/test/java/com/gxwebsoft/generator/templates/entity.java.btl

@ -4,8 +4,7 @@ package ${package.Entity};
import ${pkg}; import ${pkg};
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
<% } %> <% } %>
<% if(entityLombokModel) { %> <% if(entityLombokModel) { %>
import lombok.Data; import lombok.Data;
@ -33,7 +32,7 @@ import lombok.experimental.Accessors;
<% } %> <% } %>
<% } %> <% } %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiModel(value = "${entity}对象", description = "${table.comment!''}")
@Schema(name = "${entity}对象", description = "${table.comment!''}")
<% } %> <% } %>
<% if(table.convert) { %> <% if(table.convert) { %>
@TableName("${table.name}") @TableName("${table.name}")
@ -59,7 +58,7 @@ public class ${entity} implements Serializable {
<% if(isNotEmpty(field.comment)) { %> <% if(isNotEmpty(field.comment)) { %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiModelProperty(value = "${field.comment}")
@Schema(description = "${field.comment}")
<% }else{ %> <% }else{ %>
/** /**
* ${field.comment} * ${field.comment}

2
src/test/java/com/gxwebsoft/generator/templates/index.ts.btl

@ -1,5 +1,5 @@
import request from '@/utils/request'; import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ApiResult, PageResult } from '@/api/index';
import type { ${entity}, ${entity}Param } from './model'; import type { ${entity}, ${entity}Param } from './model';
import { MODULES_API_URL } from '@/config/setting'; import { MODULES_API_URL } from '@/config/setting';

2
src/test/java/com/gxwebsoft/generator/templates/model.ts.btl

@ -1,4 +1,4 @@
import type { PageParam } from '@/api';
import type { PageParam } from '@/api/index';
/** /**
* ${table.comment!} * ${table.comment!}

7
src/test/java/com/gxwebsoft/generator/templates/param.java.btl

@ -6,8 +6,7 @@ import ${cfg.packageName!}.common.core.annotation.QueryType;
import ${cfg.packageName!}.common.core.web.BaseParam; import ${cfg.packageName!}.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
<% if(swagger2) { %> <% if(swagger2) { %>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
<% } %> <% } %>
<% if(entityLombokModel) { %> <% if(entityLombokModel) { %>
import lombok.Data; import lombok.Data;
@ -36,7 +35,7 @@ import lombok.experimental.Accessors;
<% } %> <% } %>
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiModel(value = "${entity}Param对象", description = "${table.comment!''}查询参数")
@Schema(name = "${entity}Param对象", description = "${table.comment!''}查询参数")
<% } %> <% } %>
public class ${entity}Param extends BaseParam { public class ${entity}Param extends BaseParam {
<% if(entitySerialVersionUID) { %> <% if(entitySerialVersionUID) { %>
@ -57,7 +56,7 @@ public class ${entity}Param extends BaseParam {
<% if(isNotEmpty(field.comment)) { %> <% if(isNotEmpty(field.comment)) { %>
<% if(swagger2) { %> <% if(swagger2) { %>
@ApiModelProperty(value = "${field.comment}")
@Schema(description = "${field.comment}")
<% }else{ %> <% }else{ %>
/** /**
* ${field.comment} * ${field.comment}

199
src/test/java/com/gxwebsoft/shop/service/OrderBusinessServiceTest.java

@ -1,199 +0,0 @@
package com.gxwebsoft.shop.service;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopOrder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.*;
/**
* 订单业务服务测试类
*/
@ExtendWith(MockitoExtension.class)
class OrderBusinessServiceTest {
@Mock
private ShopOrderService shopOrderService;
@Mock
private ShopGoodsService shopGoodsService;
@InjectMocks
private OrderBusinessService orderBusinessService;
private User testUser;
private ShopGoods testGoods;
private OrderCreateRequest testRequest;
@BeforeEach
void setUp() {
// 准备测试用户
testUser = new User();
testUser.setUserId(1);
testUser.setOpenid("test_openid");
testUser.setPhone("13800138000");
// 准备测试商品
testGoods = new ShopGoods();
testGoods.setGoodsId(10021);
testGoods.setName("扎尔伯特五谷礼盒");
testGoods.setPrice(new BigDecimal("99.00"));
testGoods.setStock(100);
testGoods.setStatus(0);
testGoods.setIsShow(true);
testGoods.setDeleted(0);
// 准备测试请求(模拟前端发送的数据格式)
testRequest = new OrderCreateRequest();
testRequest.setGoodsId(10021); // 使用goodsId字段
testRequest.setQuantity(1); // 使用quantity字段
testRequest.setTotalPrice(new BigDecimal("99.00"));
testRequest.setTenantId(10832);
testRequest.setPayType(1);
testRequest.setComments("扎尔伯特五谷礼盒");
testRequest.setDeliveryType(0);
testRequest.setType(0);
}
@Test
void testCreateOrder_Success() {
// 模拟商品查询
when(shopGoodsService.getById(10021)).thenReturn(testGoods);
// 模拟订单保存
when(shopOrderService.save(any(ShopOrder.class))).thenReturn(true);
// 模拟微信支付订单创建
Map<String, String> wxOrderInfo = new HashMap<>();
wxOrderInfo.put("prepay_id", "test_prepay_id");
when(shopOrderService.createWxOrder(any(ShopOrder.class))).thenReturn((HashMap<String, String>) wxOrderInfo);
// 执行测试
Map<String, String> result = orderBusinessService.createOrder(testRequest, testUser);
// 验证结果
assertNotNull(result);
assertEquals("test_prepay_id", result.get("prepay_id"));
// 验证方法调用
verify(shopGoodsService).getById(10021);
verify(shopOrderService).save(any(ShopOrder.class));
verify(shopOrderService).createWxOrder(any(ShopOrder.class));
}
@Test
void testCreateOrder_GoodsNotFound() {
// 模拟商品不存在
when(shopGoodsService.getById(10021)).thenReturn(null);
// 执行测试并验证异常
Exception exception = assertThrows(Exception.class, () -> {
orderBusinessService.createOrder(testRequest, testUser);
});
assertTrue(exception.getMessage().contains("商品不存在"));
}
@Test
void testCreateOrder_InsufficientStock() {
// 设置库存不足
testGoods.setStock(0);
testRequest.setQuantity(1);
when(shopGoodsService.getById(10021)).thenReturn(testGoods);
// 执行测试并验证异常
Exception exception = assertThrows(Exception.class, () -> {
orderBusinessService.createOrder(testRequest, testUser);
});
assertTrue(exception.getMessage().contains("商品库存不足"));
}
@Test
void testCreateOrder_PriceValidation() {
// 设置错误的价格
testRequest.setTotalPrice(new BigDecimal("50.00")); // 商品价格是99.00,但请求价格是50.00
when(shopGoodsService.getById(10021)).thenReturn(testGoods);
// 执行测试并验证异常
Exception exception = assertThrows(Exception.class, () -> {
orderBusinessService.createOrder(testRequest, testUser);
});
assertTrue(exception.getMessage().contains("商品价格异常"));
}
@Test
void testCreateOrder_CompatibilityFields() {
// 测试兼容性字段
OrderCreateRequest compatRequest = new OrderCreateRequest();
compatRequest.setFormId(10021); // 使用formId字段
compatRequest.setTotalNum(1); // 使用totalNum字段
compatRequest.setTotalPrice(new BigDecimal("99.00"));
compatRequest.setTenantId(10832);
compatRequest.setPayType(1);
compatRequest.setType(0);
when(shopGoodsService.getById(10021)).thenReturn(testGoods);
when(shopOrderService.save(any(ShopOrder.class))).thenReturn(true);
Map<String, String> wxOrderInfo = new HashMap<>();
wxOrderInfo.put("prepay_id", "test_prepay_id");
when(shopOrderService.createWxOrder(any(ShopOrder.class))).thenReturn((HashMap<String, String>) wxOrderInfo);
// 执行测试
Map<String, String> result = orderBusinessService.createOrder(compatRequest, testUser);
// 验证结果
assertNotNull(result);
assertEquals("test_prepay_id", result.get("prepay_id"));
}
@Test
void testGetActualFormId() {
// 测试goodsId字段
OrderCreateRequest request1 = new OrderCreateRequest();
request1.setGoodsId(123);
assertEquals(123, request1.getActualFormId());
// 测试formId字段优先级
OrderCreateRequest request2 = new OrderCreateRequest();
request2.setFormId(456);
request2.setGoodsId(123);
assertEquals(456, request2.getActualFormId());
}
@Test
void testGetActualTotalNum() {
// 测试quantity字段
OrderCreateRequest request1 = new OrderCreateRequest();
request1.setQuantity(5);
assertEquals(5, request1.getActualTotalNum());
// 测试totalNum字段优先级
OrderCreateRequest request2 = new OrderCreateRequest();
request2.setTotalNum(10);
request2.setQuantity(5);
assertEquals(10, request2.getActualTotalNum());
// 测试默认值
OrderCreateRequest request3 = new OrderCreateRequest();
assertEquals(1, request3.getActualTotalNum());
}
}
Loading…
Cancel
Save