修复代码生成器
This commit is contained in:
@@ -195,7 +195,7 @@ public class BszxPayController extends BaseController {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
final LambdaQueryWrapper<BszxPay> wrapper = new LambdaQueryWrapper<>();
|
||||
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("totalMoney", bigDecimal);
|
||||
return success(map);
|
||||
|
||||
@@ -85,7 +85,7 @@ public class BszxPayRankingController extends BaseController {
|
||||
wrapper.eq(BszxPay::getFormId, item.getArticleId());
|
||||
ranking.setFormId(item.getArticleId());
|
||||
ranking.setFormName(item.getTitle());
|
||||
ranking.setNumber(bszxPayService.count(wrapper));
|
||||
ranking.setNumber((long) bszxPayService.count(wrapper));
|
||||
ranking.setTotalPrice(bszxPayService.sumMoney(wrapper));
|
||||
rankings.add(ranking);
|
||||
});
|
||||
|
||||
@@ -235,17 +235,17 @@ public class CmsArticleController extends BaseController {
|
||||
wrapper.eq(CmsArticle::getMerchantId, param.getMerchantId());
|
||||
}
|
||||
|
||||
Long totalNum = cmsArticleService.count(
|
||||
long totalNum = cmsArticleService.count(
|
||||
wrapper.eq(CmsArticle::getDeleted, 0).eq(CmsArticle::getStatus, 0)
|
||||
);
|
||||
data.put("totalNum", Math.toIntExact(totalNum));
|
||||
|
||||
Long totalNum2 = cmsArticleService.count(
|
||||
long totalNum2 = cmsArticleService.count(
|
||||
wrapper.eq(CmsArticle::getStatus, 1)
|
||||
);
|
||||
data.put("totalNum2", Math.toIntExact(totalNum2));
|
||||
|
||||
Long totalNum3 = cmsArticleService.count(
|
||||
long totalNum3 = cmsArticleService.count(
|
||||
wrapper.gt(CmsArticle::getStatus, 1)
|
||||
);
|
||||
data.put("totalNum3", Math.toIntExact(totalNum3));
|
||||
|
||||
@@ -201,31 +201,31 @@ public class OaAppController extends BaseController {
|
||||
@GetMapping("/data")
|
||||
public ApiResult<Map<String, Integer>> data() {
|
||||
Map<String, Integer> data = new HashMap<>();
|
||||
Long totalNum = oaAppService.count(
|
||||
long totalNum = oaAppService.count(
|
||||
new LambdaQueryWrapper<>()
|
||||
);
|
||||
Long totalNum2 = oaAppService.count(
|
||||
long totalNum2 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getAppStatus, "开发中")
|
||||
);
|
||||
Long totalNum3 = oaAppService.count(
|
||||
long totalNum3 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getAppStatus, "已上架")
|
||||
);
|
||||
Long totalNum4 = oaAppService.count(
|
||||
long totalNum4 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getAppStatus, "已上架")
|
||||
.eq(OaApp::getShowExpiration,false)
|
||||
);
|
||||
Long totalNum5 = oaAppService.count(
|
||||
long totalNum5 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getAppStatus, "已下架")
|
||||
);
|
||||
Long totalNum6 = oaAppService.count(
|
||||
long totalNum6 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getShowCase,true)
|
||||
);
|
||||
Long totalNum7 = oaAppService.count(
|
||||
long totalNum7 = oaAppService.count(
|
||||
new LambdaQueryWrapper<OaApp>()
|
||||
.eq(OaApp::getShowIndex, true)
|
||||
);
|
||||
|
||||
@@ -258,7 +258,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
|
||||
// 剩余天数
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
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.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.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.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -21,7 +22,7 @@ import java.util.List;
|
||||
* 优惠券控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Tag(name = "优惠券管理")
|
||||
@RestController
|
||||
@@ -31,7 +32,7 @@ public class ShopCouponController extends BaseController {
|
||||
private ShopCouponService shopCouponService;
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopCoupon:list')")
|
||||
@Operation(summary = "批量修改优惠券")
|
||||
@Operation(summary = "分页查询优惠券")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ShopCoupon>> page(ShopCouponParam param) {
|
||||
// 使用关联查询
|
||||
@@ -104,6 +105,7 @@ public class ShopCouponController extends BaseController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopCoupon:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改优惠券")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopCoupon> batchParam) {
|
||||
@@ -114,6 +116,7 @@ public class ShopCouponController extends BaseController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopCoupon:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除优惠券")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
|
||||
@@ -136,19 +136,19 @@ public class ShopGoodsController extends BaseController {
|
||||
wrapper.eq(ShopGoods::getMerchantId,param.getMerchantId());
|
||||
}
|
||||
|
||||
Long totalNum = shopGoodsService.count(
|
||||
long totalNum = shopGoodsService.count(
|
||||
wrapper.eq(ShopGoods::getStatus,0).gt(ShopGoods::getStock,0)
|
||||
);
|
||||
data.put("totalNum", Math.toIntExact(totalNum));
|
||||
wrapper.clear();
|
||||
|
||||
Long totalNum2 = shopGoodsService.count(
|
||||
long totalNum2 = shopGoodsService.count(
|
||||
wrapper.gt(ShopGoods::getStatus,0)
|
||||
);
|
||||
data.put("totalNum2", Math.toIntExact(totalNum2));
|
||||
wrapper.clear();
|
||||
|
||||
Long totalNum3 = shopGoodsService.count(
|
||||
long totalNum3 = shopGoodsService.count(
|
||||
wrapper.eq(ShopGoods::getStock,0)
|
||||
);
|
||||
data.put("totalNum3", Math.toIntExact(totalNum3));
|
||||
|
||||
@@ -10,8 +10,8 @@ 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.tags.Tag;
|
||||
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.web.bind.annotation.*;
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.List;
|
||||
* 商品优惠券表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Tag(name = "商品优惠券表管理")
|
||||
@RestController
|
||||
@@ -31,6 +31,7 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
@Resource
|
||||
private ShopGoodsCouponService shopGoodsCouponService;
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:list')")
|
||||
@Operation(summary = "分页查询商品优惠券表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ShopGoodsCoupon>> page(ShopGoodsCouponParam param) {
|
||||
@@ -38,6 +39,7 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return success(shopGoodsCouponService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:list')")
|
||||
@Operation(summary = "查询全部商品优惠券表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ShopGoodsCoupon>> list(ShopGoodsCouponParam param) {
|
||||
@@ -53,6 +55,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return success(shopGoodsCouponService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加商品优惠券表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ShopGoodsCoupon shopGoodsCoupon) {
|
||||
@@ -67,6 +71,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改商品优惠券表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ShopGoodsCoupon shopGoodsCoupon) {
|
||||
@@ -76,6 +82,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除商品优惠券表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
@@ -85,6 +93,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加商品优惠券表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ShopGoodsCoupon> list) {
|
||||
@@ -94,6 +104,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改商品优惠券表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopGoodsCoupon> batchParam) {
|
||||
@@ -103,6 +115,8 @@ public class ShopGoodsCouponController extends BaseController {
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('shop:shopGoodsCoupon:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除商品优惠券表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
package com.gxwebsoft.shop.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDate;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
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 lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 优惠券模板
|
||||
* 优惠券
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("shop_coupon")
|
||||
@Schema(name = "ShopCoupon对象", description = "优惠券模板")
|
||||
@Schema(name = "ShopCoupon对象", description = "优惠券")
|
||||
public class ShopCoupon implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -48,15 +45,6 @@ public class ShopCoupon implements Serializable {
|
||||
@Schema(description = "最低消费金额")
|
||||
private BigDecimal minPrice;
|
||||
|
||||
@Schema(description = "发放总数量(-1表示无限制)")
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "已发放数量")
|
||||
private Integer issuedCount;
|
||||
|
||||
@Schema(description = "每人限领数量(-1表示无限制)")
|
||||
private Integer limitPerUser;
|
||||
|
||||
@Schema(description = "到期类型(10领取后生效 20固定时间)")
|
||||
private Integer expireType;
|
||||
|
||||
@@ -75,8 +63,8 @@ public class ShopCoupon implements Serializable {
|
||||
@Schema(description = "适用范围配置(json格式)")
|
||||
private String applyRangeConfig;
|
||||
|
||||
@Schema(description = "是否启用(0禁用 1启用)")
|
||||
private Integer enabled;
|
||||
@Schema(description = "是否过期(0未过期 1已过期)")
|
||||
private Integer isExpire;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
@@ -95,9 +83,21 @@ public class ShopCoupon implements Serializable {
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@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;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package com.gxwebsoft.shop.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
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.EqualsAndHashCode;
|
||||
|
||||
@@ -14,7 +13,7 @@ import lombok.EqualsAndHashCode;
|
||||
* 商品优惠券表
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@@ -48,9 +47,9 @@ public class ShopGoodsCoupon implements Serializable {
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "注册时间")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date updateTime;
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
* 优惠券Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
public interface ShopCouponMapper extends BaseMapper<ShopCoupon> {
|
||||
|
||||
@@ -34,13 +34,4 @@ public interface ShopCouponMapper extends BaseMapper<ShopCoupon> {
|
||||
*/
|
||||
List<ShopCoupon> selectListRel(@Param("param") ShopCouponParam param);
|
||||
|
||||
/**
|
||||
* 检查用户是否已领取指定优惠券
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param couponId 优惠券模板ID
|
||||
* @return 已领取数量
|
||||
*/
|
||||
int countUserReceivedCoupon(@Param("userId") Integer userId, @Param("couponId") Integer couponId);
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
* 商品优惠券表Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
public interface ShopGoodsCouponMapper extends BaseMapper<ShopGoodsCoupon> {
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<if test="param.name != null">
|
||||
AND a.name LIKE CONCAT('%', #{param.name}, '%')
|
||||
</if>
|
||||
<if test="param.description != null">
|
||||
AND a.description LIKE CONCAT('%', #{param.description}, '%')
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
@@ -67,6 +70,18 @@
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</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">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
@@ -84,13 +99,4 @@
|
||||
<include refid="selectSql"></include>
|
||||
</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>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
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.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 优惠券查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@@ -30,6 +29,9 @@ public class ShopCouponParam extends BaseParam {
|
||||
@Schema(description = "优惠券名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "优惠券描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
@@ -60,7 +62,7 @@ public class ShopCouponParam extends BaseParam {
|
||||
@Schema(description = "有效期结束时间")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "适用范围(10全部商品 20指定商品)")
|
||||
@Schema(description = "适用范围(10全部商品 20指定商品 30指定分类)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer applyRange;
|
||||
|
||||
@@ -75,7 +77,7 @@ public class ShopCouponParam extends BaseParam {
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0待使用, 1已使用, 2已失效")
|
||||
@Schema(description = "状态, 0正常, 1禁用")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer status;
|
||||
|
||||
@@ -83,8 +85,24 @@ public class ShopCouponParam extends BaseParam {
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
@Schema(description = "创建用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
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.EqualsAndHashCode;
|
||||
|
||||
@@ -14,7 +13,7 @@ import lombok.EqualsAndHashCode;
|
||||
* 商品优惠券表查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
* 优惠券Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
public interface ShopCouponService extends IService<ShopCoupon> {
|
||||
|
||||
@@ -39,29 +39,4 @@ public interface ShopCouponService extends IService<ShopCoupon> {
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
* 商品优惠券表Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
public interface ShopGoodsCouponService extends IService<ShopGoodsCoupon> {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,25 @@
|
||||
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.shop.mapper.ShopCouponMapper;
|
||||
import com.gxwebsoft.shop.service.ShopCouponService;
|
||||
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 com.gxwebsoft.shop.entity.ShopCoupon;
|
||||
import com.gxwebsoft.shop.mapper.ShopCouponMapper;
|
||||
import com.gxwebsoft.shop.param.ShopCouponParam;
|
||||
import com.gxwebsoft.shop.service.ShopCouponService;
|
||||
import com.gxwebsoft.shop.service.ShopUserCouponService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠券Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-08-08 21:10:55
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCoupon> implements ShopCouponService {
|
||||
|
||||
@Resource
|
||||
private ShopUserCouponService shopUserCouponService;
|
||||
|
||||
@Override
|
||||
public PageResult<ShopCoupon> pageRel(ShopCouponParam 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));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
* 商品优惠券表Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-01-11 10:45:12
|
||||
* @since 2025-08-09 15:26:02
|
||||
*/
|
||||
@Service
|
||||
public class ShopGoodsCouponServiceImpl extends ServiceImpl<ShopGoodsCouponMapper, ShopGoodsCoupon> implements ShopGoodsCouponService {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,9 @@ public class ShopGenerator {
|
||||
// 输出目录
|
||||
private static final String OUTPUT_DIR = "/src/main/java";
|
||||
// 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文件输出目录
|
||||
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/APP/shop";
|
||||
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/VUE/template-10550";
|
||||
// Vue文件输出目录
|
||||
private static final String OUTPUT_DIR_VUE = "/src";
|
||||
// 作者名称
|
||||
@@ -37,7 +37,7 @@ public class ShopGenerator {
|
||||
// 是否在xml中添加二级缓存配置
|
||||
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_USERNAME = "modules";
|
||||
private static final String DB_PASSWORD = "8YdLnk7KsPAyDXGA";
|
||||
@@ -55,7 +55,7 @@ public class ShopGenerator {
|
||||
// "shop_goods_sku",
|
||||
// "shop_goods_category",
|
||||
"shop_coupon",
|
||||
// "shop_goods_coupon",
|
||||
"shop_goods_coupon",
|
||||
// "shop_goods_description",
|
||||
// "shop_goods_log",
|
||||
// "shop_goods_relation",
|
||||
|
||||
@@ -23,8 +23,8 @@ import ${cfg.packageName!}.common.core.web.PageParam;
|
||||
import ${cfg.packageName!}.common.core.web.BatchParam;
|
||||
import ${cfg.packageName!}.common.core.annotation.OperationLog;
|
||||
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.web.bind.annotation.*;
|
||||
<% if(!restControllerStyle) { %>
|
||||
@@ -41,7 +41,7 @@ import java.util.List;
|
||||
* @since ${date(), 'yyyy-MM-dd HH:mm:ss'}
|
||||
*/
|
||||
<% if(swagger2) { %>
|
||||
@Api(tags = "${table.comment!}管理")
|
||||
@Tag(name = "${table.comment!}管理")
|
||||
<% } %>
|
||||
<% if(restControllerStyle) { %>
|
||||
@RestController
|
||||
@@ -68,7 +68,7 @@ public class ${table.controllerName} {
|
||||
@PreAuthorize("hasAuthority('${authPre}:list')")
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("分页查询${table.comment!}")
|
||||
@Operation(summary = "分页查询${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -88,7 +88,7 @@ public class ${table.controllerName} {
|
||||
@PreAuthorize("hasAuthority('${authPre}:list')")
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("查询全部${table.comment!}")
|
||||
@Operation(summary = "查询全部${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -105,7 +105,7 @@ public class ${table.controllerName} {
|
||||
*/
|
||||
<% } %>
|
||||
@PreAuthorize("hasAuthority('${authPre}:list')")
|
||||
@ApiOperation("根据id查询${table.comment!}")
|
||||
@Operation(summary = "根据id查询${table.comment!}")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<${entity}> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
@@ -124,7 +124,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("添加${table.comment!}")
|
||||
@Operation(summary = "添加${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -154,7 +154,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("修改${table.comment!}")
|
||||
@Operation(summary = "修改${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -179,7 +179,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("删除${table.comment!}")
|
||||
@Operation(summary = "删除${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -204,7 +204,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("批量添加${table.comment!}")
|
||||
@Operation(summary = "批量添加${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -229,7 +229,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("批量修改${table.comment!}")
|
||||
@Operation(summary = "批量修改${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
@@ -254,7 +254,7 @@ public class ${table.controllerName} {
|
||||
@OperationLog
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiOperation("批量删除${table.comment!}")
|
||||
@Operation(summary = "批量删除${table.comment!}")
|
||||
<% } %>
|
||||
<% if(!restControllerStyle) { %>
|
||||
@ResponseBody
|
||||
|
||||
@@ -4,8 +4,7 @@ package ${package.Entity};
|
||||
import ${pkg};
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
<% } %>
|
||||
<% if(entityLombokModel) { %>
|
||||
import lombok.Data;
|
||||
@@ -33,7 +32,7 @@ import lombok.experimental.Accessors;
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiModel(value = "${entity}对象", description = "${table.comment!''}")
|
||||
@Schema(name = "${entity}对象", description = "${table.comment!''}")
|
||||
<% } %>
|
||||
<% if(table.convert) { %>
|
||||
@TableName("${table.name}")
|
||||
@@ -59,7 +58,7 @@ public class ${entity} implements Serializable {
|
||||
|
||||
<% if(isNotEmpty(field.comment)) { %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
@Schema(description = "${field.comment}")
|
||||
<% }else{ %>
|
||||
/**
|
||||
* ${field.comment}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { MODULES_API_URL } from '@/config/setting';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PageParam } from '@/api';
|
||||
import type { PageParam } from '@/api/index';
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
|
||||
@@ -6,8 +6,7 @@ import ${cfg.packageName!}.common.core.annotation.QueryType;
|
||||
import ${cfg.packageName!}.common.core.web.BaseParam;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
<% if(swagger2) { %>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
<% } %>
|
||||
<% if(entityLombokModel) { %>
|
||||
import lombok.Data;
|
||||
@@ -36,7 +35,7 @@ import lombok.experimental.Accessors;
|
||||
<% } %>
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
<% if(swagger2) { %>
|
||||
@ApiModel(value = "${entity}Param对象", description = "${table.comment!''}查询参数")
|
||||
@Schema(name = "${entity}Param对象", description = "${table.comment!''}查询参数")
|
||||
<% } %>
|
||||
public class ${entity}Param extends BaseParam {
|
||||
<% if(entitySerialVersionUID) { %>
|
||||
@@ -57,7 +56,7 @@ public class ${entity}Param extends BaseParam {
|
||||
|
||||
<% if(isNotEmpty(field.comment)) { %>
|
||||
<% if(swagger2) { %>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
@Schema(description = "${field.comment}")
|
||||
<% }else{ %>
|
||||
/**
|
||||
* ${field.comment}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user