refactor: 微服务模块结构优化

This commit is contained in:
Ray.Hao 2024-09-02 00:29:27 +08:00
parent 42ef021811
commit a7f2332881
38 changed files with 1606 additions and 0 deletions

View File

@ -0,0 +1,24 @@
package com.youlai.mall.sale;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 营销服务启动类
*
* @author ray
* @since 0.0.1
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableScheduling
public class SaleApplication {
public static void main(String[] args) {
SpringApplication.run(SaleApplication.class, args);
}
}

View File

@ -0,0 +1,80 @@
package com.youlai.mall.sale.controller.admin;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.common.result.PageResult;
import com.youlai.common.result.Result;
import com.youlai.mall.sale.model.entity.Advert;
import com.youlai.mall.sale.model.query.AdvertPageQuery;
import com.youlai.mall.sale.service.AdvertService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@Tag(name = "Admin-营销广告")
@RestController
@RequestMapping("/api/v1/adverts")
@RequiredArgsConstructor
public class AdvertController {
private final AdvertService advertService;
@Operation(summary= "广告分页列表")
@GetMapping("/page")
public PageResult<Advert> getAdvertPage(AdvertPageQuery queryParams) {
// 查询参数
int pageNum = queryParams.getPageNum();
int pageSize = queryParams.getPageSize();
String keywords = queryParams.getKeywords();
// 分页查询
Page<Advert> result = advertService.page(
new Page<>(pageNum, pageSize),
new LambdaQueryWrapper<Advert>()
.like(StrUtil.isNotBlank(keywords), Advert::getTitle, keywords)
.orderByAsc(Advert::getSort)
);
return PageResult.success(result);
}
@Operation(summary= "广告详情")
@GetMapping("/{id}")
public Result getAdvertDetail(
@Parameter(description = "广告ID") @PathVariable Long id
) {
Advert advert = advertService.getById(id);
return Result.success(advert);
}
@Operation(summary= "新增广告")
@PostMapping
public Result addAvert(@RequestBody Advert advert) {
boolean status = advertService.save(advert);
return Result.judge(status);
}
@Operation(summary= "修改广告")
@PutMapping(value = "/{id}")
public Result updateAdvert(
@Parameter(description = "广告ID") @PathVariable Long id,
@RequestBody Advert advert) {
boolean status = advertService.updateById(advert);
return Result.judge(status);
}
@Operation(summary= "删除广告")
@DeleteMapping("/{ids}")
public Result deleteAdverts(@Parameter(description = "广告ID多个以英文逗号(,)分割") @PathVariable("ids") String ids) {
boolean status = advertService.removeByIds(Arrays.asList(ids.split(",")));
return Result.judge(status);
}
}

View File

@ -0,0 +1,63 @@
package com.youlai.mall.sale.controller.admin;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.common.result.PageResult;
import com.youlai.common.result.Result;
import com.youlai.mall.sale.model.form.CouponForm;
import com.youlai.mall.sale.model.query.CouponPageQuery;
import com.youlai.mall.sale.model.vo.CouponPageVO;
import com.youlai.mall.sale.service.CouponService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
@Tag(name = "Admin-优惠券管理")
@RestController
@RequestMapping("/api/v1/coupons")
@RequiredArgsConstructor
public class CouponController {
private final CouponService couponService;
@Operation(summary= "优惠券分页列表")
@GetMapping("/pages")
public PageResult getCouponPage(CouponPageQuery queryParams) {
Page<CouponPageVO> result = couponService.getCouponPage(queryParams);
return PageResult.success(result);
}
@Operation(summary= "优惠券表单数据")
@GetMapping("/{couponId}/form_data")
public Result<CouponForm> getCouponFormData(@Parameter(description = "优惠券ID") @PathVariable Long couponId) {
CouponForm couponForm = couponService.getCouponFormData(couponId);
return Result.success(couponForm);
}
@Operation(summary ="新增优惠券")
@PostMapping
public Result saveCoupon(@RequestBody @Valid CouponForm couponForm) {
boolean result = couponService.saveCoupon(couponForm);
return Result.judge(result);
}
@Operation(summary ="修改优惠券")
@PutMapping("/{couponId}")
public Result updateCoupon(
@PathVariable Long couponId,
@RequestBody @Valid CouponForm couponForm
) {
boolean result = couponService.updateCoupon(couponId,couponForm);
return Result.judge(result);
}
@Operation(summary= "删除优惠券")
@DeleteMapping("/{ids}")
public Result deleteCoupons(@Parameter(description = "用户ID多个以英文逗号(,)分割") @PathVariable String ids) {
boolean result = couponService.deleteCoupons(ids);
return Result.judge(result);
}
}

View File

@ -0,0 +1,31 @@
package com.youlai.mall.sale.controller.app;
import com.youlai.common.result.Result;
import com.youlai.mall.sale.model.vo.BannerVO;
import com.youlai.mall.sale.service.AdvertService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "App-营销广告")
@RestController
@RequestMapping("/app-api/v1/adverts")
@Slf4j
@AllArgsConstructor
public class AdvertAppController {
private AdvertService advertService;
@Operation(summary= "APP首页广告横幅列表")
@GetMapping("/banners")
public Result<List<BannerVO>> getBannerList() {
List<BannerVO> list = advertService.getBannerList();
return Result.success(list);
}
}

View File

@ -0,0 +1,28 @@
package com.youlai.mall.sale.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.mall.sale.model.entity.Advert;
import com.youlai.mall.sale.model.vo.BannerVO;
import com.youlai.mall.sale.model.vo.AdvertPageVO;
import org.mapstruct.Mapper;
import java.util.List;
/**
* advert实体转换器
*
* @author Ray
* @since 2022/5/29
*/
@Mapper(componentModel = "spring")
public interface AdvertConverter {
AdvertPageVO entity2PageVo(Advert entity);
Page<AdvertPageVO> entity2PageVo(Page<Advert> po);
BannerVO entity2BannerVo(Advert entity);
List<BannerVO> entity2BannerVo(List<Advert> entities);
}

View File

@ -0,0 +1,48 @@
package com.youlai.mall.sale.converter;
import com.youlai.mall.sale.model.entity.Coupon;
import com.youlai.mall.sale.model.form.CouponForm;
import com.youlai.mall.sale.model.vo.CouponPageVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import java.util.List;
/**
* 优惠券对象转换器
*
* @author Ray
* @since 2022/5/29
*/
@Mapper(componentModel = "spring")
public interface CouponConverter {
@Mappings({
@Mapping(target = "platformLabel", expression = "java(com.youlai.common.base.IBaseEnum.getLabelByValue(entity.getPlatform(), com.youlai.mall.sale.enums.PlatformEnum.class))"),
@Mapping(target = "typeLabel", expression = "java(com.youlai.common.base.IBaseEnum.getLabelByValue(entity.getType(), com.youlai.mall.sale.enums.CouponTypeEnum.class))"),
@Mapping(target = "faceValueLabel", expression = "java(com.youlai.mall.sale.util.CouponUtils.getFaceValue(entity.getType(),entity.getFaceValue(),entity.getDiscount()))"),
@Mapping(
target = "validityPeriodLabel",
expression = "java(com.youlai.mall.sale.util.CouponUtils.getValidityPeriod(entity.getValidityPeriodType(),entity.getValidityDays(),entity.getValidityStartTime(),entity.getValidityEndTime()))"
),
@Mapping(target = "minPointLabel", expression = "java(cn.hutool.core.util.NumberUtil.toStr(cn.hutool.core.util.NumberUtil.div(entity.getMinPoint(),new java.math.BigDecimal(100)).setScale(2)))"),
})
CouponPageVO entity2PageVO(Coupon entity);
List<CouponPageVO> entity2PageVO(List<Coupon> entities);
@Mappings({
@Mapping(target = "discount",expression = "java(cn.hutool.core.util.NumberUtil.div(form.getDiscount(),10L))"),
})
Coupon toEntity(CouponForm form);
@Mappings({
@Mapping(target = "discount",expression = "java(cn.hutool.core.util.NumberUtil.mul(entity.getDiscount(),10L))"),
})
CouponForm convertToForm(Coupon entity);
}

View File

@ -0,0 +1,37 @@
package com.youlai.mall.sale.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import com.youlai.common.base.IBaseEnum;
import lombok.Getter;
/**
* 优惠券适用类型枚举
*
* @author Ray
* @since 2022/7/13
*/
@Getter
public enum CouponApplicationScopeEnum implements IBaseEnum<Integer> {
ALL(0, "全场通用"),
/**
* 指定商品分类
*/
SPU_CATEGORY(1, "指定商品分类"),
SPU(2, "指定商品"),
;
@Getter
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
private Integer value;
@Getter
@JsonValue // 表示对枚举序列化时返回此字段
private String label;
CouponApplicationScopeEnum(Integer value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -0,0 +1,27 @@
package com.youlai.mall.sale.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import com.youlai.common.base.IBaseEnum;
import lombok.Getter;
@Getter
public enum CouponFaceValueTypeEnum implements IBaseEnum<Integer> {
CASH(1, "现金"),
DISCOUNT(2, "折扣"),
;
@Getter
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
private Integer value;
@Getter
@JsonValue // 表示对枚举序列化时返回此字段
private String label;
CouponFaceValueTypeEnum(Integer value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -0,0 +1,29 @@
package com.youlai.mall.sale.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import com.youlai.common.base.IBaseEnum;
import lombok.Getter;
@Getter
public enum CouponTypeEnum implements IBaseEnum<Integer> {
WZ(0, null),
MJ(1, "满减券"),
ZJ(2, "直减券"),
ZK(3, "折扣券")
;
@Getter
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
private Integer value;
@Getter
@JsonValue // 表示对枚举序列化时返回此字段
private String label;
CouponTypeEnum(Integer value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -0,0 +1,28 @@
package com.youlai.mall.sale.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import com.youlai.common.base.IBaseEnum;
import lombok.Getter;
@Getter
public enum PlatformEnum implements IBaseEnum<Integer> {
ALL(0, "全平台"),
APP(1, "APP"),
PC(2, "PC"),
;
@Getter
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
private Integer value;
@Getter
@JsonValue // 表示对枚举序列化时返回此字段
private String label;
PlatformEnum(Integer value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -0,0 +1,27 @@
package com.youlai.mall.sale.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import com.youlai.common.base.IBaseEnum;
import lombok.Getter;
@Getter
public enum ValidityPeriodTypeEnum implements IBaseEnum<Integer> {
UNKNOWN(0, null),
DATE_RANGE(1, "日期范围"),
FIXED_DAYS(2, "固定天数"),
;
@Getter
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
private Integer value;
@Getter
@JsonValue // 表示对枚举序列化时返回此字段
private String label;
ValidityPeriodTypeEnum(Integer value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.mall.sale.model.entity.Advert;
import com.youlai.mall.sale.model.query.AdvertPageQuery;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AdvertMapper extends BaseMapper<Advert> {
/**
* 广告分页列表
*
* @param page
* @param queryParams
* @return
*/
Page<Advert> getAdvertPage(Page<Advert> page, AdvertPageQuery queryParams);
}

View File

@ -0,0 +1,15 @@
package com.youlai.mall.sale.mapper;
import com.youlai.mall.sale.model.entity.CouponHistory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CouponHistoryMapper extends BaseMapper<CouponHistory> {
}

View File

@ -0,0 +1,21 @@
package com.youlai.mall.sale.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.mall.sale.model.entity.Coupon;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.mall.sale.model.query.CouponPageQuery;
import com.youlai.mall.sale.model.vo.CouponPageVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CouponMapper extends BaseMapper<Coupon> {
List<Coupon> getCouponPage(Page<CouponPageVO> page, CouponPageQuery queryParams);
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.mapper;
import com.youlai.mall.sale.model.entity.CouponSpuCategory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 优惠券商品分类关联持久层
*
* @author Ray
* @since 2022/6/30
*/
@Mapper
public interface CouponSpuCategoryMapper extends BaseMapper<CouponSpuCategory> {
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.mapper;
import com.youlai.mall.sale.model.entity.CouponSpu;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 优惠券商品关联持久层
*
* @author Ray
* @since 2022/6/30
*/
@Mapper
public interface CouponSpuMapper extends BaseMapper<CouponSpu> {
}

View File

@ -0,0 +1,49 @@
package com.youlai.mall.sale.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.youlai.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 营销广告
*
* @author Ray Hao
* @since 2024/6/7
*/
@EqualsAndHashCode(callSuper = true)
@TableName("sms_advert")
@Data
public class Advert extends BaseEntity {
private String title;
private String imageUrl;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date endTime;
/**
* 状态
*/
private Integer status;
/**
* 排序
*/
private Integer sort;
/**
* 跳转URL
*/
private String redirectUrl;
private String remark;
}

View File

@ -0,0 +1,120 @@
package com.youlai.mall.sale.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
/**
* 优惠券表
*
* @author Ray Hao
* @since 2024/6/7
*/
@EqualsAndHashCode(callSuper = true)
@TableName("sms_coupon")
@Data
public class Coupon extends BaseEntity {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 优惠券类型(1:满减券;2:直减券;3:折扣券)
*/
private Integer type;
/**
* 优惠券名称
*/
private String name;
/**
* 优惠券码
*/
private String code;
/**
* 使用平台(0:全平台;1:移动端;2:PC端)
*/
private Integer platform;
/**
* 优惠券面值类型((1:金额;2:折扣)
*/
private Integer faceValueType;
/**
* 优惠券面值金额(单位:)
*/
private Long faceValue;
/**
* 优惠券折扣
*/
private BigDecimal discount;
/**
* 使用门槛(0:无门槛)
*/
private Long minPoint;
/**
* 每人限领张数(0:不限制)
*/
private Integer perLimit;
/**
* 有效期类型(1:自领取之起有效天数;2:有效起止时间)
*/
private Integer validityPeriodType;
/**
* 自领取之日起有效天数
*/
private Integer validityDays;
/**
* 有效期起始时间
*/
private Date validityStartTime;
/**
* 有效期截止时间
*/
private Date validityEndTime;
/**
* 使用类型(0-全场通用;1-指定商品分类;2-指定商品)
*/
private Integer applicationScope;
/**
* 发行量(-1:无限制)
*/
private Integer circulation;
/**
* 已领取的优惠券数量(统计)
*/
private Integer receivedCount;
/**
* 已使用的优惠券数量(统计)
*/
private Integer usedCount;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,79 @@
package com.youlai.mall.sale.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* 优惠券领取历史记录
*/
@TableName(value ="sms_coupon_history")
@Data
public class CouponHistory implements Serializable {
/**
*
*/
@TableId
private Long id;
/**
* 优惠券ID
*/
private Long couponId;
/**
* 会员ID
*/
private Long memberId;
/**
* 会员昵称
*/
private String memberNickname;
/**
* 优惠券码
*/
private String couponCode;
/**
* 获取类型(1后台增删2主动领取)
*/
private Integer getType;
/**
* 状态(0未使用1已使用2已过期)
*/
private Integer status;
/**
* 使用时间
*/
private Date useTime;
/**
* 订单ID
*/
private Long orderId;
/**
* 订单号
*/
private String orderSn;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,43 @@
package com.youlai.mall.sale.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 优惠券与产品关联表
*/
@TableName(value ="sms_coupon_spu")
@Data
@Accessors(chain = true)
public class CouponSpu implements Serializable {
/**
*
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 优惠券ID
*/
private Long couponId;
/**
* 商品ID
*/
private Long spuId;
/**
* 商品名称
*/
private String spuName;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,34 @@
package com.youlai.mall.sale.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@TableName(value ="sms_coupon_spu_category")
@Data
@Accessors(chain = true)
public class CouponSpuCategory implements Serializable {
/**
*
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 优惠券ID
*/
private Long couponId;
/**
* 商品分类ID
*/
private Long categoryId;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,76 @@
package com.youlai.mall.sale.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 优惠券表单对象
*
* @author Ray
* @since 2022/6/23
*/
@Schema(description = "优惠券表单对象")
@Data
public class CouponForm {
@Schema(description="ID")
private Long id;
@Schema(description="优惠券名称")
private String name;
@Schema(description="优惠券类型(1:满减券;2:直减券;3:折扣券)")
private Integer type;
@Schema(description="优惠券面值类型((1:金额;2:折扣)")
private Integer faceValueType;
@Schema(description="优惠券面值金额(单位:分)")
private Long faceValue;
@Schema(description="优惠券折扣")
private BigDecimal discount;
@Schema(description="优惠券码")
private String code;
@Schema(description="使用平台(0-全平台;1-移动端;2-PC;)")
private Integer platform;
@Schema(description="发行量(-1:无限制)")
private Integer circulation;
@Schema(description="使用门槛(0:无门槛)")
private Long minPoint;
@Schema(description="每人限领张数(-1:不限制)")
private Integer perLimit;
@Schema(description="有效期类型(1:日期范围;2:固定天数)")
private Integer validityPeriodType;
@Schema(description="自领取之日起有效天数")
private Integer validityDays;
@Schema(description="有效期开始时间")
private Date validityBeginTime;
@Schema(description="有效期截止时间")
private Date validityEndTime;
@Schema(description="应用范围(0:全场通用;1:指定商品分类;2:指定商品)")
private Integer applicationScope;
@Schema(description="备注")
private String remark;
@Schema(description="优惠券适用商品分类ID集合")
private List<Long> spuCategoryIds;
@Schema(description="优惠券适用商品列表")
private List<Long> spuIds;
}

View File

@ -0,0 +1,22 @@
package com.youlai.mall.sale.model.query;
import com.youlai.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 广告分页列表查询对象
*
* @author Ray
* @since 2021/7/11
*/
@EqualsAndHashCode(callSuper = true)
@Schema(description = "广告分页查询对象")
@Data
public class AdvertPageQuery extends BasePageQuery {
@Schema(description="关键字")
private String keywords;
}

View File

@ -0,0 +1,25 @@
package com.youlai.mall.sale.model.query;
import com.youlai.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xinyi
* @desc: 优惠券分页查询对象
* @since 2021/7/11
*/
@Schema(description = "优惠券分页查询对象")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CouponPageQuery extends BasePageQuery {
@Schema(description="状态")
private Integer status;
@Schema(description="优惠券码")
private String code;
}

View File

@ -0,0 +1,46 @@
package com.youlai.mall.sale.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
/**
* 广告分页视图对象
*
* @author Ray
* @since 2022/11/12
*/
@Schema(description = "广告分页视图对象")
@Data
public class AdvertPageVO {
@Schema(description="广告ID")
private Integer id;
@Schema(description="广告标题")
private String title;
@Schema(description="广告图片")
private String imgUrl;
@Schema(description="开始时间")
@JsonFormat( pattern = "yyyy-MM-dd")
private Date beginTime;
@Schema(description="截止时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endTime;
@Schema(description="状态")
private Integer status;
private Integer sort;
private String redirectUrl;
private String remark;
}

View File

@ -0,0 +1,19 @@
package com.youlai.mall.sale.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "横幅视图对象")
@Data
public class BannerVO {
@Schema(description="广告标题")
private String title;
@Schema(description="横幅图片URL")
private String imageUrl;
@Schema(description="跳转URL")
private String redirectUrl;
}

View File

@ -0,0 +1,44 @@
package com.youlai.mall.sale.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 优惠券分页视图对象
*
* @author Ray
* @since 2022/6/26
*/
@Schema(description = "优惠券分页视图对象")
@Data
public class CouponPageVO {
@Schema(description="ID")
private Long id;
@Schema(description="优惠券名称")
private String name;
@Schema(description="优惠券码")
private String code;
@Schema(description="使用平台")
private String platformLabel;
@Schema(description="优惠券类型标签")
private String typeLabel;
@Schema(description="优惠券面值")
private String faceValueLabel;
@Schema(description="使用门槛")
private String minPointLabel;
@Schema(description="优惠券有效期")
private String validityPeriodLabel;
@Schema(description="使用说明")
private String remark;
}

View File

@ -0,0 +1,23 @@
package com.youlai.mall.sale.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.mall.sale.model.entity.Advert;
import com.youlai.mall.sale.model.query.AdvertPageQuery;
import com.youlai.mall.sale.model.vo.BannerVO;
import com.youlai.mall.sale.model.vo.AdvertPageVO;
import java.util.List;
public interface AdvertService extends IService<Advert> {
/**
* 广告分页列表
*
* @param queryParams
* @return
*/
Page<AdvertPageVO> getAdvertPage(AdvertPageQuery queryParams);
List<BannerVO> getBannerList();
}

View File

@ -0,0 +1,11 @@
package com.youlai.mall.sale.service;
import com.youlai.mall.sale.model.entity.CouponHistory;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
*/
public interface CouponHistoryService extends IService<CouponHistory> {
}

View File

@ -0,0 +1,58 @@
package com.youlai.mall.sale.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.mall.sale.model.entity.Coupon;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.mall.sale.model.form.CouponForm;
import com.youlai.mall.sale.model.query.CouponPageQuery;
import com.youlai.mall.sale.model.vo.CouponPageVO;
/**
* 优惠券业务接口
*
* @author Ray
* @since 2022/5/29
*/
public interface CouponService extends IService<Coupon> {
/**
* 优惠券分页列表
*
* @param queryParams
* @return
*/
Page<CouponPageVO> getCouponPage(CouponPageQuery queryParams);
/**
* 新增优惠券
*
* @param couponForm
* @return
*/
boolean saveCoupon(CouponForm couponForm);
/**
* 修改优惠券
*
* @param couponId 优惠券ID
* @param couponForm 优惠券表单
* @return
*/
boolean updateCoupon(Long couponId, CouponForm couponForm);
/**
* 删除优惠券
*
* @param ids 优惠券ID多个以英文逗号(,)分割
* @return
*/
boolean deleteCoupons(String ids);
/**
* 优惠券表单数据
*
* @param couponId
* @return
*/
CouponForm getCouponFormData(Long couponId);
}

View File

@ -0,0 +1,11 @@
package com.youlai.mall.sale.service;
import com.youlai.mall.sale.model.entity.CouponSpuCategory;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
*/
public interface CouponSpuCategoryService extends IService<CouponSpuCategory> {
}

View File

@ -0,0 +1,11 @@
package com.youlai.mall.sale.service;
import com.youlai.mall.sale.model.entity.CouponSpu;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
*/
public interface CouponSpuService extends IService<CouponSpu> {
}

View File

@ -0,0 +1,57 @@
package com.youlai.mall.sale.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.common.enums.StatusEnum;
import com.youlai.mall.sale.converter.AdvertConverter;
import com.youlai.mall.sale.model.entity.Advert;
import com.youlai.mall.sale.mapper.AdvertMapper;
import com.youlai.mall.sale.model.query.AdvertPageQuery;
import com.youlai.mall.sale.model.vo.BannerVO;
import com.youlai.mall.sale.model.vo.AdvertPageVO;
import com.youlai.mall.sale.service.AdvertService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 广告业务实现类
*
* @author Ray Hao
* @since 2022/5/28
*/
@Service
@RequiredArgsConstructor
public class AdvertServiceImpl extends ServiceImpl<AdvertMapper, Advert> implements AdvertService {
private final AdvertConverter advertConverter;
/**
* 广告分页列表
*
* @param queryParams 查询参数
* @return 广告分页列表
*/
@Override
public Page<AdvertPageVO> getAdvertPage(AdvertPageQuery queryParams) {
Page<Advert> page = this.baseMapper.getAdvertPage(new Page<>(queryParams.getPageNum(),
queryParams.getPageSize()),
queryParams);
return advertConverter.entity2PageVo(page);
}
/**
* 获取广告横幅列表
*/
@Override
public List<BannerVO> getBannerList() {
List<Advert> entities = this.list(new LambdaQueryWrapper<Advert>().
eq(Advert::getStatus, StatusEnum.ENABLE.getValue())
.select(Advert::getTitle, Advert::getImageUrl, Advert::getRedirectUrl)
);
return advertConverter.entity2BannerVo(entities);
}
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.mall.sale.model.entity.CouponHistory;
import com.youlai.mall.sale.service.CouponHistoryService;
import com.youlai.mall.sale.mapper.CouponHistoryMapper;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class CouponHistoryServiceImpl extends ServiceImpl<CouponHistoryMapper, CouponHistory>
implements CouponHistoryService {
}

View File

@ -0,0 +1,231 @@
package com.youlai.mall.sale.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.common.base.IBaseEnum;
import com.youlai.mall.sale.enums.CouponApplicationScopeEnum;
import com.youlai.mall.sale.converter.CouponConverter;
import com.youlai.mall.sale.mapper.CouponMapper;
import com.youlai.mall.sale.model.entity.Coupon;
import com.youlai.mall.sale.model.entity.CouponSpu;
import com.youlai.mall.sale.model.entity.CouponSpuCategory;
import com.youlai.mall.sale.model.form.CouponForm;
import com.youlai.mall.sale.model.query.CouponPageQuery;
import com.youlai.mall.sale.model.vo.CouponPageVO;
import com.youlai.mall.sale.service.CouponService;
import com.youlai.mall.sale.service.CouponSpuCategoryService;
import com.youlai.mall.sale.service.CouponSpuService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 优惠券业务实现类
*
* @author Ray
* @since 2022/5/29
*/
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {
private final CouponConverter couponConverter;
private final CouponSpuCategoryService couponSpuCategoryService;
private final CouponSpuService couponSpuService;
/**
* 优惠券分页列表
*
* @param queryParams
* @return
*/
@Override
public Page<CouponPageVO> getCouponPage(CouponPageQuery queryParams) {
Page<CouponPageVO> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());
// 查询数据
List<Coupon> couponList = this.baseMapper.getCouponPage(page, queryParams);
// 实体转换
List<CouponPageVO> records = couponConverter.entity2PageVO(couponList);
page.setRecords(records);
return page;
}
/**
* 优惠券表单数据
*
* @param couponId
* @return
*/
@Override
public CouponForm getCouponFormData(Long couponId) {
Coupon entity = this.getById(couponId);
// 实体转换entity->form
CouponForm couponForm = couponConverter.convertToForm(entity);
Integer applicationScope = couponForm.getApplicationScope();
CouponApplicationScopeEnum applicationScopeEnum = IBaseEnum.getEnumByValue(applicationScope, CouponApplicationScopeEnum.class);
if (applicationScopeEnum != null) {
switch (applicationScopeEnum) {
case SPU_CATEGORY:
List<CouponSpuCategory> couponSpuCategoryList = couponSpuCategoryService.list(new LambdaQueryWrapper<CouponSpuCategory>()
.eq(CouponSpuCategory::getCouponId, couponId)
.select(CouponSpuCategory::getCategoryId)
);
List<Long> categoryIds = couponSpuCategoryList.stream().map(item -> item.getCategoryId()).collect(Collectors.toList());
couponForm.setSpuCategoryIds(categoryIds);
break;
case SPU:
List<CouponSpu> couponSpuList = couponSpuService.list(new LambdaQueryWrapper<CouponSpu>()
.eq(CouponSpu::getCouponId, couponId)
.select(CouponSpu::getSpuId)
);
List<Long> spuIds = couponSpuList.stream().map(item -> item.getSpuId()).collect(Collectors.toList());
couponForm.setSpuIds(spuIds);
break;
}
}
return couponForm;
}
/**
* 新增优惠券
*
* @param couponForm 优惠券表单
* @return
*/
@Override
public boolean saveCoupon(CouponForm couponForm) {
Coupon entity = couponConverter.toEntity(couponForm);
boolean result = this.save(entity);
if (result) {
// 根据优惠券适用商品范围保存对应的关联关系
// 指定商品分类 优惠券 <-> 商品分类
// 指定商品 优惠券 <-> 商品
Long couponId = entity.getId();
Integer applicationScope = couponForm.getApplicationScope();
CouponApplicationScopeEnum applicationScopeEnum = IBaseEnum.getEnumByValue(applicationScope, CouponApplicationScopeEnum.class);
Assert.isTrue(applicationScopeEnum != null, "请指定优惠券适用范围");
switch (applicationScopeEnum) {
case SPU_CATEGORY:
List<Long> spuCategoryIds = couponForm.getSpuCategoryIds();
if (CollectionUtil.isNotEmpty(spuCategoryIds)) {
List<CouponSpuCategory> smsCouponSpuCategories = spuCategoryIds.stream()
.map(spuCategoryId -> new CouponSpuCategory().setCouponId(couponId).setCategoryId(spuCategoryId))
.collect(Collectors.toList());
couponSpuCategoryService.saveBatch(smsCouponSpuCategories);
}
break;
case SPU:
List<Long> spuIds = couponForm.getSpuIds();
if (CollectionUtil.isNotEmpty(spuIds)) {
List<CouponSpu> couponSpuList = spuIds.stream()
.map(spuId -> new CouponSpu().setCouponId(couponId).setSpuId(spuId))
.collect(Collectors.toList());
couponSpuService.saveBatch(couponSpuList);
}
break;
}
}
return result;
}
/**
* 修改优惠券
*
* @param couponId 优惠券ID
* @param couponForm 优惠券表单
* @return
*/
@Override
public boolean updateCoupon(Long couponId, CouponForm couponForm) {
Coupon entity = couponConverter.toEntity(couponForm);
boolean result = this.updateById(entity);
if (result) {
// 根据优惠券适用商品范围保存对应的关联关系
// 全场通用 删除所有关联
// 指定商品分类 优惠券 <-> 商品分类
// 指定商品 优惠券 <-> 商品
Integer applicationScope = couponForm.getApplicationScope();
CouponApplicationScopeEnum applicationScopeEnum = IBaseEnum.getEnumByValue(applicationScope, CouponApplicationScopeEnum.class);
Assert.isTrue(applicationScopeEnum != null, "请指定优惠券适用范围");
switch (applicationScopeEnum) {
case ALL:
couponSpuCategoryService.remove(new LambdaQueryWrapper<CouponSpuCategory>()
.eq(CouponSpuCategory::getCouponId, couponId)
);
couponSpuService.remove(new LambdaQueryWrapper<CouponSpu>()
.eq(CouponSpu::getCouponId, couponId)
);
break;
case SPU_CATEGORY:
List<Long> spuCategoryIds = couponForm.getSpuCategoryIds();
if (CollectionUtil.isNotEmpty(spuCategoryIds)) {
couponSpuCategoryService.remove(new LambdaQueryWrapper<CouponSpuCategory>()
.eq(CouponSpuCategory::getCouponId, couponId)
);
List<CouponSpuCategory> smsCouponSpuCategories = spuCategoryIds.stream()
.map(spuCategoryId -> new CouponSpuCategory().setCouponId(couponId)
.setCategoryId(spuCategoryId))
.collect(Collectors.toList());
couponSpuCategoryService.saveBatch(smsCouponSpuCategories);
}
break;
case SPU:
List<Long> spuIds = couponForm.getSpuIds();
if (CollectionUtil.isNotEmpty(spuIds)) {
couponSpuService.remove(new LambdaQueryWrapper<CouponSpu>()
.eq(CouponSpu::getCouponId, couponId)
);
List<CouponSpu> couponSpuList = spuIds.stream()
.map(spuId -> new CouponSpu().setCouponId(couponId).setSpuId(spuId))
.collect(Collectors.toList());
couponSpuService.saveBatch(couponSpuList);
}
break;
}
}
return result;
}
/**
* 删除优惠券
*
* @param idsStr 优惠券ID多个以英文逗号(,)分割
* @return
*/
@Override
@Transactional
public boolean deleteCoupons(String idsStr) {
Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的优惠券数据为空");
// 逻辑删除
List<Long> ids = Arrays.stream(idsStr.split(","))
.map(Long::parseLong)
.collect(Collectors.toList());
return this.removeByIds(ids);
}
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.mall.sale.model.entity.CouponSpuCategory;
import com.youlai.mall.sale.service.CouponSpuCategoryService;
import com.youlai.mall.sale.mapper.CouponSpuCategoryMapper;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class CouponSpuCategoryServiceImpl extends ServiceImpl<CouponSpuCategoryMapper, CouponSpuCategory>
implements CouponSpuCategoryService {
}

View File

@ -0,0 +1,20 @@
package com.youlai.mall.sale.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.mall.sale.model.entity.CouponSpu;
import com.youlai.mall.sale.service.CouponSpuService;
import com.youlai.mall.sale.mapper.CouponSpuMapper;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class CouponSpuServiceImpl extends ServiceImpl<CouponSpuMapper, CouponSpu>
implements CouponSpuService {
}

View File

@ -0,0 +1,69 @@
package com.youlai.mall.sale.util;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.youlai.common.base.IBaseEnum;
import com.youlai.mall.sale.enums.CouponFaceValueTypeEnum;
import com.youlai.mall.sale.enums.ValidityPeriodTypeEnum;
import java.math.BigDecimal;
import java.util.Date;
public class CouponUtils {
/**
* 计算优惠券面值
*
* @param faceValueType 面值类型
* @param faceValue
* @param discount
* @return
*/
public static String getFaceValue(Integer faceValueType, Long faceValue, BigDecimal discount) {
String faceValueLabel = null;
if (faceValueType == null) {
return null;
}
CouponFaceValueTypeEnum couponFaceValueTypeEnum = IBaseEnum.getEnumByValue(faceValueType, CouponFaceValueTypeEnum.class);
switch (couponFaceValueTypeEnum) {
case CASH:
faceValueLabel = NumberUtil.toStr(NumberUtil.div(faceValue, new Float(100), 2)) + "";
break;
case DISCOUNT:
faceValueLabel = NumberUtil.mul(discount, 10) + "";
break;
}
return faceValueLabel;
}
/**
* 计算优惠券有效期
*
* @param validityPeriodType
* @param validityDays
* @param validityBeginTime
* @param validityEndTime
* @return
*/
public static String getValidityPeriod(Integer validityPeriodType, Integer validityDays, Date validityBeginTime, Date validityEndTime) {
String validityPeriodLabel = null;
if (validityPeriodType == null) {
return null;
}
ValidityPeriodTypeEnum validityPeriodTypeEnum = IBaseEnum.getEnumByValue(validityPeriodType, ValidityPeriodTypeEnum.class);
switch (validityPeriodTypeEnum) {
case DATE_RANGE:
validityPeriodLabel = DateUtil.format(validityBeginTime, "yyyy/MM/dd") + "~" + DateUtil.format(validityEndTime, "yyyy/MM/dd");
break;
case FIXED_DAYS:
validityPeriodLabel = "领取后" + validityDays + "天有效";
break;
}
return validityPeriodLabel;
}
}