新增提货券
This commit is contained in:
1 parent
b0d6e56c42
commit
87486b9ea0
44 files changed
+2583
-4
No files matched your search
+17
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherUseReqDTO;
|
||||
|
||||
/**
|
||||
* 优惠劵 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface GiftVoucherApi {
|
||||
|
||||
|
||||
GiftVoucherRespDTO getGiftVoucherById(Long giftVoucherId);
|
||||
|
||||
void useGiftVoucher(GiftVoucherUseReqDTO giftVoucherUseReqDTO);
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.giftvoucher.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提货劵 Response DTO
|
||||
*
|
||||
* @author 茂县源码
|
||||
*/
|
||||
@Data
|
||||
public class GiftVoucherRespDTO{
|
||||
|
||||
/**
|
||||
* 提货劵编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 提货劵模板编号
|
||||
*/
|
||||
private Long templateId;
|
||||
/**
|
||||
* 提货劵名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 提货劵状态
|
||||
*
|
||||
* 1-未使用
|
||||
* 2-已使用
|
||||
* 3-已失效
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 商品范围编号的数组
|
||||
*/
|
||||
private List<Long> productScopeValues;
|
||||
// private String productScopeValues;
|
||||
/**
|
||||
* 可购买商品数量
|
||||
*/
|
||||
private Integer productCount;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 领取类型
|
||||
*
|
||||
* 1 - 用户主动领取
|
||||
* 2 - 后台自动发放
|
||||
*/
|
||||
private Integer takeType;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private LocalDateTime validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private LocalDateTime validEndTime;
|
||||
/**
|
||||
* 使用订单号
|
||||
*/
|
||||
private Long useOrderId;
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private LocalDateTime useTime;
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.giftvoucher.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 提货劵使用 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class GiftVoucherUseReqDTO {
|
||||
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
@NotNull(message = "提货劵编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
@NotNull(message = "订单编号不能为空")
|
||||
private Long orderId;
|
||||
|
||||
}
|
||||
+11
@@ -138,4 +138,15 @@ public interface ErrorCodeConstants {
|
||||
// ========== 客服消息 1-013-020-000 ==========
|
||||
ErrorCode KEFU_MESSAGE_NOT_EXISTS = new ErrorCode(1_013_020_000, "客服消息不存在");
|
||||
|
||||
// ========== 提货券模板 1-013-021-000 ==========
|
||||
ErrorCode GIFT_VOUCHER_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_021_000, "提货券模板不存在");
|
||||
ErrorCode GIFT_VOUCHER_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1_013_021_001, "用户已领取过此提货券");
|
||||
ErrorCode GIFT_VOUCHER_STATUS_NOT_UNUSED = new ErrorCode(1_013_021_002, "提货劵不处于待使用状态");
|
||||
|
||||
// ========== 提货劵 1-013-022-000 ==========
|
||||
ErrorCode GIFT_VOUCHER_NOT_EXISTS = new ErrorCode(1_013_022_000, "提货劵不存在");
|
||||
ErrorCode GIFT_VOUCHER_TEMPLATE_CANNOT_TAKE = new ErrorCode(1_013_022_001, "领取方式不正确");
|
||||
ErrorCode GIFT_VOUCHER_TEMPLATE_EXPIRED = new ErrorCode(1_013_022_002, "提货券模板已过期");
|
||||
ErrorCode GIFT_VOUCHER_TEMPLATE_NOT_ENOUGH = new ErrorCode(1_013_022_003, "当前剩余数量不够领取");
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.promotion.enums.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import cn.iocoder.yudao.module.promotion.enums.diy.DiyPageEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 提货劵状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GiftVoucherStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
UNUSED(1, "未使用"),
|
||||
USED(2, "已使用"),
|
||||
EXPIRE(3, "已过期");
|
||||
|
||||
private static final Integer[] ARRAYS = Arrays.stream(values()).map(GiftVoucherStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.promotion.enums.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 优惠劵模板的有限期类型的枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GiftVoucherTemplateValidityTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
DATE(1, "固定日期"),
|
||||
TERM(2, "领取之后"),
|
||||
;
|
||||
|
||||
private static final Integer[] ARRAYS = Arrays.stream(values()).map(GiftVoucherTemplateValidityTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.promotion.enums.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 优惠劵领取方式
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GiftVoucherTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
USER(1, "扫码领取"), // 用户可扫码直接领取
|
||||
ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵
|
||||
;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(GiftVoucherTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static boolean isUser(Integer type) {
|
||||
return Objects.equals(USER.getType(), type);
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.giftvoucher;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 优惠劵 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class GiftVoucherApiImpl implements GiftVoucherApi {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherService giftVoucherService;
|
||||
|
||||
|
||||
@Override
|
||||
public GiftVoucherRespDTO getGiftVoucherById(Long giftVoucherId) {
|
||||
return BeanUtils.toBean(giftVoucherService.getGiftVoucher(giftVoucherId), GiftVoucherRespDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useGiftVoucher(GiftVoucherUseReqDTO giftVoucherUseReqDTO) {
|
||||
giftVoucherService.useGiftVoucher(giftVoucherUseReqDTO);
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherSendReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 提货劵")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/gift-voucher")
|
||||
@Validated
|
||||
public class GiftVoucherController {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherService giftVoucherService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建提货劵")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:create')")
|
||||
public CommonResult<Long> createGiftVoucher(@Valid @RequestBody GiftVoucherSaveReqVO createReqVO) {
|
||||
return success(giftVoucherService.createGiftVoucher(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新提货劵")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:update')")
|
||||
public CommonResult<Boolean> updateGiftVoucher(@Valid @RequestBody GiftVoucherSaveReqVO updateReqVO) {
|
||||
giftVoucherService.updateGiftVoucher(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除提货劵")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:delete')")
|
||||
public CommonResult<Boolean> deleteGiftVoucher(@RequestParam("id") Long id) {
|
||||
giftVoucherService.deleteGiftVoucher(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得提货劵")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:query')")
|
||||
public CommonResult<GiftVoucherRespVO> getGiftVoucher(@RequestParam("id") Long id) {
|
||||
GiftVoucherDO giftVoucher = giftVoucherService.getGiftVoucher(id);
|
||||
return success(BeanUtils.toBean(giftVoucher, GiftVoucherRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得提货劵分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:query')")
|
||||
public CommonResult<PageResult<GiftVoucherRespVO>> getGiftVoucherPage(@Valid GiftVoucherPageReqVO pageReqVO) {
|
||||
PageResult<GiftVoucherDO> pageResult = giftVoucherService.getGiftVoucherPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, GiftVoucherRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出提货劵 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportGiftVoucherExcel(@Valid GiftVoucherPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<GiftVoucherDO> list = giftVoucherService.getGiftVoucherPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "提货劵.xls", "数据", GiftVoucherRespVO.class,
|
||||
BeanUtils.toBean(list, GiftVoucherRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/send")
|
||||
@Operation(summary = "发送提货券")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon:send')")
|
||||
public CommonResult<Boolean> sendGiftVoucher(@Valid @RequestBody GiftVoucherSendReqVO reqVO) {
|
||||
giftVoucherService.takeGiftVoucherByAdmin(reqVO.getTemplateId(), reqVO.getUserIds());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplateSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherTemplateService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
|
||||
@Tag(name = "管理后台 - 提货券模板")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/gift-voucher-template")
|
||||
@Validated
|
||||
public class GiftVoucherTemplateController {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherTemplateService giftVoucherTemplateService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建提货券模板")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:create')")
|
||||
public CommonResult<Long> createGiftVoucherTemplate(@Valid @RequestBody GiftVoucherTemplateSaveReqVO createReqVO) {
|
||||
return success(giftVoucherTemplateService.createGiftVoucherTemplate(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新提货券模板")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:update')")
|
||||
public CommonResult<Boolean> updateGiftVoucherTemplate(@Valid @RequestBody GiftVoucherTemplateSaveReqVO updateReqVO) {
|
||||
giftVoucherTemplateService.updateGiftVoucherTemplate(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除提货券模板")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:delete')")
|
||||
public CommonResult<Boolean> deleteGiftVoucherTemplate(@RequestParam("id") Long id) {
|
||||
giftVoucherTemplateService.deleteGiftVoucherTemplate(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得提货券模板")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:query')")
|
||||
public CommonResult<GiftVoucherTemplateRespVO> getGiftVoucherTemplate(@RequestParam("id") Long id) {
|
||||
GiftVoucherTemplateDO giftVoucherTemplate = giftVoucherTemplateService.getGiftVoucherTemplate(id);
|
||||
return success(BeanUtils.toBean(giftVoucherTemplate, GiftVoucherTemplateRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得提货券模板分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:query')")
|
||||
public CommonResult<PageResult<GiftVoucherTemplateRespVO>> getGiftVoucherTemplatePage(@Valid GiftVoucherTemplatePageReqVO pageReqVO) {
|
||||
PageResult<GiftVoucherTemplateDO> pageResult = giftVoucherTemplateService.getGiftVoucherTemplatePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, GiftVoucherTemplateRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出提货券模板 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:gift-voucher-template:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportGiftVoucherTemplateExcel(@Valid GiftVoucherTemplatePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<GiftVoucherTemplateDO> list = giftVoucherTemplateService.getGiftVoucherTemplatePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "提货券模板.xls", "数据", GiftVoucherTemplateRespVO.class,
|
||||
BeanUtils.toBean(list, GiftVoucherTemplateRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 提货劵分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class GiftVoucherPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "提货劵模板编号", example = "7305")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "提货劵名", example = "王五")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货劵状态", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "用户编号", example = "17286")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "领取类型", example = "1")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] validStartTime;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] validEndTime;
|
||||
|
||||
@Schema(description = "使用订单号", example = "23301")
|
||||
private Long useOrderId;
|
||||
|
||||
@Schema(description = "使用时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] useTime;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "可购买商品数量", example = "18952")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 提货劵 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class GiftVoucherRespVO {
|
||||
|
||||
@Schema(description = "提货劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17673")
|
||||
@ExcelProperty("提货劵编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提货劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7305")
|
||||
@ExcelProperty("提货劵模板编号")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "提货劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@ExcelProperty("提货劵名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货劵状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("提货劵状态")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
@ExcelProperty("商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17286")
|
||||
@ExcelProperty("用户编号")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "领取类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("领取类型")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "生效开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("生效开始时间")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "生效结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("生效结束时间")
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "使用订单号", example = "23301")
|
||||
@ExcelProperty("使用订单号")
|
||||
private Long useOrderId;
|
||||
|
||||
@Schema(description = "使用时间")
|
||||
@ExcelProperty("使用时间")
|
||||
private LocalDateTime useTime;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "可购买商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "18952")
|
||||
@ExcelProperty("可购买商品数量")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 提货劵新增/修改 Request VO")
|
||||
@Data
|
||||
public class GiftVoucherSaveReqVO {
|
||||
|
||||
@Schema(description = "提货劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17673")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提货劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7305")
|
||||
@NotNull(message = "提货劵模板编号不能为空")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "提货劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@NotEmpty(message = "提货劵名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货劵状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "提货劵状态")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17286")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "领取类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "领取类型")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "生效开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "生效开始时间不能为空")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "生效结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "生效结束时间不能为空")
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "使用订单号", example = "23301")
|
||||
private Long useOrderId;
|
||||
|
||||
@Schema(description = "使用时间")
|
||||
private LocalDateTime useTime;
|
||||
|
||||
@Schema(description = "可购买商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "18952")
|
||||
@NotNull(message = "可购买商品数量不能为空")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Set;
|
||||
|
||||
@Schema(description = "管理后台 - 提货劵发放 Request VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GiftVoucherSendReqVO {
|
||||
|
||||
@Schema(description = "提货劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "提货劵模板编号不能为空")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "用户编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
|
||||
@NotEmpty(message = "用户编号列表不能为空")
|
||||
private Set<Long> userIds;
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 提货券模板分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class GiftVoucherTemplatePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "提货券名", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货券描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "状态", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放数量, -1 - 则表示不限制", example = "23927")
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "每人限领个数, -1 - 则表示不限制", example = "31760")
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "领取方式", example = "1")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "生效日期类型", example = "1")
|
||||
private Integer validityType;
|
||||
|
||||
@Schema(description = "固定日期-生效开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] validStartTime;
|
||||
|
||||
@Schema(description = "固定日期-生效结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] validEndTime;
|
||||
|
||||
@Schema(description = "领取日期-开始天数")
|
||||
private Integer fixedStartTerm;
|
||||
|
||||
@Schema(description = "领取日期-结束天数")
|
||||
private Integer fixedEndTerm;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "领取提货券的数量", example = "1818")
|
||||
private Integer takeCount;
|
||||
|
||||
@Schema(description = "使用提货券的次数", example = "25128")
|
||||
private Integer useCount;
|
||||
|
||||
@Schema(description = "可购买商品数量", example = "22134")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 提货券模板 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class GiftVoucherTemplateRespVO {
|
||||
|
||||
@Schema(description = "模板编号,自增唯一。", requiredMode = Schema.RequiredMode.REQUIRED, example = "13004")
|
||||
@ExcelProperty("模板编号,自增唯一。")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提货券名", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
@ExcelProperty("提货券名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货券描述", example = "你猜")
|
||||
@ExcelProperty("提货券描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("状态")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放数量, -1 - 则表示不限制", requiredMode = Schema.RequiredMode.REQUIRED, example = "23927")
|
||||
@ExcelProperty("发放数量, -1 - 则表示不限制")
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "每人限领个数, -1 - 则表示不限制", requiredMode = Schema.RequiredMode.REQUIRED, example = "31760")
|
||||
@ExcelProperty("每人限领个数, -1 - 则表示不限制")
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "领取方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("领取方式")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
@ExcelProperty("商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("生效日期类型")
|
||||
private Integer validityType;
|
||||
|
||||
@Schema(description = "固定日期-生效开始时间")
|
||||
@ExcelProperty("固定日期-生效开始时间")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "固定日期-生效结束时间")
|
||||
@ExcelProperty("固定日期-生效结束时间")
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "领取日期-开始天数")
|
||||
@ExcelProperty("领取日期-开始天数")
|
||||
private Integer fixedStartTerm;
|
||||
|
||||
@Schema(description = "领取日期-结束天数")
|
||||
@ExcelProperty("领取日期-结束天数")
|
||||
private Integer fixedEndTerm;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "领取提货券的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1818")
|
||||
@ExcelProperty("领取提货券的数量")
|
||||
private Integer takeCount;
|
||||
|
||||
@Schema(description = "使用提货券的次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25128")
|
||||
@ExcelProperty("使用提货券的次数")
|
||||
private Integer useCount;
|
||||
|
||||
@Schema(description = "可购买商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "22134")
|
||||
@ExcelProperty("可购买商品数量")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 提货券模板新增/修改 Request VO")
|
||||
@Data
|
||||
public class GiftVoucherTemplateSaveReqVO {
|
||||
|
||||
@Schema(description = "模板编号,自增唯一。", requiredMode = Schema.RequiredMode.REQUIRED, example = "13004")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提货券名", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
@NotEmpty(message = "提货券名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货券描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发放数量, -1 - 则表示不限制", requiredMode = Schema.RequiredMode.REQUIRED, example = "23927")
|
||||
@NotNull(message = "发放数量, -1 - 则表示不限制不能为空")
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "每人限领个数, -1 - 则表示不限制", requiredMode = Schema.RequiredMode.REQUIRED, example = "31760")
|
||||
@NotNull(message = "每人限领个数, -1 - 则表示不限制不能为空")
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "领取方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "领取方式不能为空")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "商品范围编号的数组")
|
||||
private String productScopeValues;
|
||||
|
||||
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "生效日期类型不能为空")
|
||||
private Integer validityType;
|
||||
|
||||
@Schema(description = "固定日期-生效开始时间")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "固定日期-生效结束时间")
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "领取日期-开始天数")
|
||||
private Integer fixedStartTerm;
|
||||
|
||||
@Schema(description = "领取日期-结束天数")
|
||||
private Integer fixedEndTerm;
|
||||
|
||||
@Schema(description = "领取提货券的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1818")
|
||||
@NotNull(message = "领取提货券的数量不能为空")
|
||||
private Integer takeCount;
|
||||
|
||||
@Schema(description = "使用提货券的次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25128")
|
||||
@NotNull(message = "使用提货券的次数不能为空")
|
||||
private Integer useCount;
|
||||
|
||||
@Schema(description = "可购买商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "22134")
|
||||
@NotNull(message = "可购买商品数量不能为空")
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.giftvoucher;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo.AppGiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo.AppGiftVoucherRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo.AppGiftVoucherTakeReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.giftvoucher.GiftVoucherConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherService;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherTemplateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collections;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "用户 App - 我的提货劵列表")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/gift-voucher")
|
||||
@Validated
|
||||
public class AppGiftVoucherController {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherService giftVoucherService;
|
||||
@Resource
|
||||
private GiftVoucherTemplateService giftVoucherTemplateService;
|
||||
|
||||
@PostMapping("/take")
|
||||
@Operation(summary = "领取提货劵")
|
||||
@Parameter(name = "templateId", description = "提货劵模板编号", required = true, example = "1024")
|
||||
public CommonResult<Boolean> takeGiftVoucher(@Valid @RequestBody AppGiftVoucherTakeReqVO reqVO) {
|
||||
// 1. 领取提货劵
|
||||
Long userId = getLoginUserId();
|
||||
giftVoucherService.takeGiftVoucher(reqVO.getTemplateId(), CollUtil.newHashSet(userId), GiftVoucherTypeEnum.USER);
|
||||
|
||||
// 2. 检查是否可以继续领取
|
||||
GiftVoucherTemplateDO giftVoucherTemplate = giftVoucherTemplateService.getGiftVoucherTemplate(reqVO.getTemplateId());
|
||||
boolean canTakeAgain = true;
|
||||
if (giftVoucherTemplate.getTakeLimitCount() != null && giftVoucherTemplate.getTakeLimitCount() > 0) {
|
||||
Integer takeCount = giftVoucherService.getTakeCount(reqVO.getTemplateId(), userId);
|
||||
canTakeAgain = takeCount < giftVoucherTemplate.getTakeLimitCount();
|
||||
}
|
||||
return success(canTakeAgain);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "我的提货劵列表")
|
||||
public CommonResult<PageResult<AppGiftVoucherRespVO>> getGiftVoucherPage(AppGiftVoucherPageReqVO pageReqVO) {
|
||||
PageResult<GiftVoucherDO> pageResult = giftVoucherService.getGiftVoucherPage(
|
||||
GiftVoucherConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId())));
|
||||
return success(BeanUtils.toBean(pageResult, AppGiftVoucherRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得提货劵")
|
||||
@Parameter(name = "id", description = "优惠劵编号", required = true, example = "1024")
|
||||
public CommonResult<AppGiftVoucherRespVO> getGiftVoucher(@RequestParam("id") Long id) {
|
||||
GiftVoucherDO giftVoucherDO = giftVoucherService.getGiftVoucherByUserId(getLoginUserId(), id);
|
||||
return success(BeanUtils.toBean(giftVoucherDO, AppGiftVoucherRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get-unused-count")
|
||||
@Operation(summary = "获得未使用的提货劵数量")
|
||||
public CommonResult<Long> getUnusedCouponCount() {
|
||||
return success(giftVoucherService.getUnusedCouponCount(getLoginUserId()));
|
||||
}
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "用户 App - 提货劵分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class AppGiftVoucherPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "提货劵状态", example = "1")
|
||||
@InEnum(value = CouponStatusEnum.class, message = "提货劵状态,必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 提货劵 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class AppGiftVoucherRespVO {
|
||||
|
||||
@Schema(description = "提货劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "16947")
|
||||
@ExcelProperty("提货劵编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提货劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@ExcelProperty("提货劵名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "提货劵状态 * * 1-未使用 * 2-已使用 * 3-已失效", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("提货劵状态 * * 1-未使用 * 2-已使用 * 3-已失效")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "商品 SPU 编号", example = "9673")
|
||||
@ExcelProperty("商品 SPU 编号")
|
||||
private Long spuId;
|
||||
|
||||
@Schema(description = "商品 SKU 编号", example = "28153")
|
||||
@ExcelProperty("商品 SKU 编号")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "可购买商品数量", example = "2")
|
||||
@ExcelProperty("可购买商品数量")
|
||||
private Integer productCount;
|
||||
|
||||
@Schema(description = "提货券流水号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("提货券流水号")
|
||||
private String no;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2975")
|
||||
@ExcelProperty("用户编号")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "领取类型 * * 1 - 用户主动领取 * 2 - 后台自动发放", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("领取类型 * * 1 - 用户主动领取 * 2 - 后台自动发放")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "生效开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("生效开始时间")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "生效结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("生效结束时间")
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "使用订单号", example = "27627")
|
||||
@ExcelProperty("使用订单号")
|
||||
private Long useOrderId;
|
||||
|
||||
@Schema(description = "使用时间")
|
||||
@ExcelProperty("使用时间")
|
||||
private LocalDateTime useTime;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "用户 App - 提货劵领取 Request VO")
|
||||
@Data
|
||||
public class AppGiftVoucherTakeReqVO {
|
||||
|
||||
@Schema(description = "提货劵模板编号", example = "1")
|
||||
@NotNull(message = "提货劵模板编号不能为空")
|
||||
private Long templateId;
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.giftvoucher;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.giftvoucher.vo.AppGiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherTemplateValidityTypeEnum;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 提货劵 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface GiftVoucherConvert {
|
||||
|
||||
GiftVoucherConvert INSTANCE = Mappers.getMapper(GiftVoucherConvert.class);
|
||||
|
||||
default GiftVoucherDO convert(GiftVoucherTemplateDO template, Long userId) {
|
||||
GiftVoucherDO giftVoucherDO = new GiftVoucherDO()
|
||||
.setTemplateId(template.getId())
|
||||
.setName(template.getName())
|
||||
.setTakeType(template.getTakeType())
|
||||
.setStatus(GiftVoucherStatusEnum.UNUSED.getStatus())
|
||||
.setProductScopeValues(template.getProductScopeValues())
|
||||
.setProductCount(template.getProductCount())
|
||||
.setUserId(userId);
|
||||
if (GiftVoucherTemplateValidityTypeEnum.DATE.getType().equals(template.getValidityType())) {
|
||||
giftVoucherDO.setValidStartTime(template.getValidStartTime());
|
||||
giftVoucherDO.setValidEndTime(template.getValidEndTime());
|
||||
} else if (GiftVoucherTemplateValidityTypeEnum.TERM.getType().equals(template.getValidityType())) {
|
||||
giftVoucherDO.setValidStartTime(LocalDateTime.now().plusDays(template.getFixedStartTerm()));
|
||||
giftVoucherDO.setValidEndTime(LocalDateTime.now().plusDays(template.getFixedEndTerm()));
|
||||
}
|
||||
return giftVoucherDO;
|
||||
}
|
||||
|
||||
GiftVoucherPageReqVO convert(AppGiftVoucherPageReqVO pageReqVO, Collection<Long> userIds);
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提货劵 DO
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@TableName("promotion_gift_voucher")
|
||||
@KeySequence("promotion_gift_voucher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GiftVoucherDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 提货劵编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 提货劵模板编号
|
||||
*/
|
||||
private Long templateId;
|
||||
/**
|
||||
* 提货劵名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 提货劵状态
|
||||
* <p>
|
||||
* 1-未使用
|
||||
* 2-已使用
|
||||
* 3-已失效
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 商品范围编号的数组
|
||||
*
|
||||
* 冗余 {@link GiftVoucherTemplateDO#getProductScopeValues()}
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> productScopeValues;
|
||||
/**
|
||||
* 可购买商品数量
|
||||
*/
|
||||
private Integer productCount;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 领取类型
|
||||
* <p>
|
||||
* 1 - 用户主动领取
|
||||
* 2 - 后台自动发放
|
||||
*/
|
||||
private Integer takeType;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private LocalDateTime validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private LocalDateTime validEndTime;
|
||||
/**
|
||||
* 使用订单号
|
||||
*/
|
||||
private Long useOrderId;
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private LocalDateTime useTime;
|
||||
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 提货券模板 DO
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@TableName("promotion_gift_voucher_template")
|
||||
@KeySequence("promotion_gift_voucher_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GiftVoucherTemplateDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 模板编号,自增唯一。
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 提货券名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 提货券描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 发放数量, -1 - 则表示不限制
|
||||
*/
|
||||
private Integer totalCount;
|
||||
/**
|
||||
* 每人限领个数, -1 - 则表示不限制
|
||||
*/
|
||||
private Integer takeLimitCount;
|
||||
/**
|
||||
* 领取方式
|
||||
*/
|
||||
private Integer takeType;
|
||||
/**
|
||||
* 商品范围编号的数组
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> productScopeValues;
|
||||
/**
|
||||
* 生效日期类型
|
||||
*/
|
||||
private Integer validityType;
|
||||
/**
|
||||
* 固定日期-生效开始时间
|
||||
*/
|
||||
private LocalDateTime validStartTime;
|
||||
/**
|
||||
* 固定日期-生效结束时间
|
||||
*/
|
||||
private LocalDateTime validEndTime;
|
||||
/**
|
||||
* 领取日期-开始天数
|
||||
*/
|
||||
private Integer fixedStartTerm;
|
||||
/**
|
||||
* 领取日期-结束天数
|
||||
*/
|
||||
private Integer fixedEndTerm;
|
||||
/**
|
||||
* 领取提货券的数量
|
||||
*/
|
||||
private Integer takeCount;
|
||||
/**
|
||||
* 使用提货券的次数
|
||||
*/
|
||||
private Integer useCount;
|
||||
/**
|
||||
* 可购买商品数量
|
||||
*/
|
||||
private Integer productCount;
|
||||
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.giftvoucher;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 提货劵 Mapper
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@Mapper
|
||||
public interface GiftVoucherMapper extends BaseMapperX<GiftVoucherDO> {
|
||||
|
||||
default PageResult<GiftVoucherDO> selectPage(GiftVoucherPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eqIfPresent(GiftVoucherDO::getTemplateId, reqVO.getTemplateId())
|
||||
.likeIfPresent(GiftVoucherDO::getName, reqVO.getName())
|
||||
.eqIfPresent(GiftVoucherDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(GiftVoucherDO::getProductScopeValues, reqVO.getProductScopeValues())
|
||||
.eqIfPresent(GiftVoucherDO::getUserId, reqVO.getUserId())
|
||||
.eqIfPresent(GiftVoucherDO::getTakeType, reqVO.getTakeType())
|
||||
.betweenIfPresent(GiftVoucherDO::getValidStartTime, reqVO.getValidStartTime())
|
||||
.betweenIfPresent(GiftVoucherDO::getValidEndTime, reqVO.getValidEndTime())
|
||||
.eqIfPresent(GiftVoucherDO::getUseOrderId, reqVO.getUseOrderId())
|
||||
.betweenIfPresent(GiftVoucherDO::getUseTime, reqVO.getUseTime())
|
||||
.betweenIfPresent(GiftVoucherDO::getCreateTime, reqVO.getCreateTime())
|
||||
.eqIfPresent(GiftVoucherDO::getProductCount, reqVO.getProductCount())
|
||||
.orderByDesc(GiftVoucherDO::getId));
|
||||
}
|
||||
|
||||
default List<GiftVoucherDO> selectListByTemplateIdAndUserIds(Long templateId, Set<Long> userIds){
|
||||
return selectList(new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getTemplateId, templateId)
|
||||
.in(GiftVoucherDO::getUserId, userIds)
|
||||
);
|
||||
}
|
||||
|
||||
default GiftVoucherDO getGiftVoucherByUserId(Long userId, Long id){
|
||||
return selectOne(new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getUserId, userId)
|
||||
.eq(GiftVoucherDO::getId, id));
|
||||
}
|
||||
|
||||
default Long selectCountByUserIdAndStatus(Long userId, Integer status){
|
||||
return selectCount(new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getUserId, userId)
|
||||
.eq(GiftVoucherDO::getStatus, status));
|
||||
}
|
||||
|
||||
default Map<Long, Integer> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) {
|
||||
String templateIdAlias = "templateId";
|
||||
String countAlias = "count";
|
||||
List<Map<String, Object>> list = selectMaps(MPJWrappers.lambdaJoin(GiftVoucherDO.class)
|
||||
.selectAs(GiftVoucherDO::getTemplateId, templateIdAlias)
|
||||
.selectCount(GiftVoucherDO::getId, countAlias)
|
||||
.eq(GiftVoucherDO::getUserId, userId)
|
||||
.in(GiftVoucherDO::getTemplateId, templateIds)
|
||||
.groupBy(GiftVoucherDO::getTemplateId));
|
||||
return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias));
|
||||
}
|
||||
|
||||
default GiftVoucherDO selectByTemplateIdAndUserId(Long id, Long userId){
|
||||
return selectOne(new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getId, id)
|
||||
.eq(GiftVoucherDO::getUserId, userId));
|
||||
}
|
||||
|
||||
default int updateByIdAndStatus(Long id, Integer status, GiftVoucherDO giftVoucherDO){
|
||||
return update(giftVoucherDO, new LambdaUpdateWrapper<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getId, id).eq(GiftVoucherDO::getStatus, status));
|
||||
}
|
||||
|
||||
default List<GiftVoucherDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime){
|
||||
return selectList(new LambdaQueryWrapperX<GiftVoucherDO>()
|
||||
.eq(GiftVoucherDO::getStatus, status)
|
||||
.le(GiftVoucherDO::getValidEndTime, validEndTime)
|
||||
);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 提货券模板 Mapper
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@Mapper
|
||||
public interface GiftVoucherTemplateMapper extends BaseMapperX<GiftVoucherTemplateDO> {
|
||||
|
||||
default PageResult<GiftVoucherTemplateDO> selectPage(GiftVoucherTemplatePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<GiftVoucherTemplateDO>()
|
||||
.likeIfPresent(GiftVoucherTemplateDO::getName, reqVO.getName())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getDescription, reqVO.getDescription())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getTotalCount, reqVO.getTotalCount())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getTakeLimitCount, reqVO.getTakeLimitCount())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getTakeType, reqVO.getTakeType())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getProductScopeValues, reqVO.getProductScopeValues())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getValidityType, reqVO.getValidityType())
|
||||
.betweenIfPresent(GiftVoucherTemplateDO::getValidStartTime, reqVO.getValidStartTime())
|
||||
.betweenIfPresent(GiftVoucherTemplateDO::getValidEndTime, reqVO.getValidEndTime())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getFixedStartTerm, reqVO.getFixedStartTerm())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getFixedEndTerm, reqVO.getFixedEndTerm())
|
||||
.betweenIfPresent(GiftVoucherTemplateDO::getCreateTime, reqVO.getCreateTime())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getTakeCount, reqVO.getTakeCount())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getUseCount, reqVO.getUseCount())
|
||||
.eqIfPresent(GiftVoucherTemplateDO::getProductCount, reqVO.getProductCount())
|
||||
.orderByDesc(GiftVoucherTemplateDO::getId));
|
||||
}
|
||||
|
||||
default void updateTakeCount(Long id, int incrCount){
|
||||
update(null, new LambdaUpdateWrapper<GiftVoucherTemplateDO>()
|
||||
.eq(GiftVoucherTemplateDO::getId, id)
|
||||
.setSql("take_count = take_count + " + incrCount));
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.promotion.job.giftvoucher;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.promotion.service.giftvoucher.GiftVoucherService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 提货券过期 Job
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Component
|
||||
public class GiftVoucherExpireJob implements JobHandler {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherService giftVoucherService;
|
||||
|
||||
@Override
|
||||
@TenantJob
|
||||
public String execute(String param) {
|
||||
int count = giftVoucherService.expireGiftVoucher();
|
||||
return StrUtil.format("过期提货券 {} 个", count);
|
||||
}
|
||||
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.giftvoucher;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherTypeEnum;
|
||||
|
||||
/**
|
||||
* 提货劵 Service 接口
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
public interface GiftVoucherService {
|
||||
|
||||
/**
|
||||
* 创建提货劵
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createGiftVoucher(@Valid GiftVoucherSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新提货劵
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateGiftVoucher(@Valid GiftVoucherSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除提货劵
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteGiftVoucher(Long id);
|
||||
|
||||
/**
|
||||
* 获得提货劵
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 提货劵
|
||||
*/
|
||||
GiftVoucherDO getGiftVoucher(Long id);
|
||||
|
||||
/**
|
||||
* 获得提货劵分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 提货劵分页
|
||||
*/
|
||||
PageResult<GiftVoucherDO> getGiftVoucherPage(GiftVoucherPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 领取优惠券
|
||||
*
|
||||
* @param templateId 提货券模板编号
|
||||
* @param userIds 用户编号列表
|
||||
* @param takeType 领取方式
|
||||
* @return key: userId, value: 优惠券编号列表
|
||||
*/
|
||||
Map<Long, List<Long>> takeGiftVoucher(Long templateId, Set<Long> userIds, GiftVoucherTypeEnum takeType);
|
||||
|
||||
default Map<Long, List<Long>> takeGiftVoucherByAdmin(Long templateId, Set<Long> userIds){
|
||||
return takeGiftVoucher(templateId, userIds, GiftVoucherTypeEnum.ADMIN);
|
||||
}
|
||||
|
||||
GiftVoucherDO getGiftVoucherByUserId(Long userId, Long id);
|
||||
|
||||
Long getUnusedCouponCount(Long userId);
|
||||
|
||||
/**
|
||||
* 获取会员领取指定提货券的数量
|
||||
*
|
||||
* @param templateId 提货券模板编号
|
||||
* @param userId 用户编号
|
||||
* @return 领取提货券的数量
|
||||
*/
|
||||
default Integer getTakeCount(Long templateId, Long userId) {
|
||||
Map<Long, Integer> map = getTakeCountMapByTemplateIds(Collections.singleton(templateId), userId);
|
||||
return MapUtil.getInt(map, templateId, 0);
|
||||
}
|
||||
|
||||
Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId);
|
||||
|
||||
void useGiftVoucher(GiftVoucherUseReqDTO giftVoucherUseReqDTO);
|
||||
|
||||
int expireGiftVoucher();
|
||||
}
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.giftvoucher;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.giftvoucher.GiftVoucherSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.giftvoucher.GiftVoucherConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherTemplateValidityTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.giftvoucher.GiftVoucherTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.giftvoucher.GiftVoucherMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 提货劵 Service 实现类
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class GiftVoucherServiceImpl implements GiftVoucherService {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherMapper giftVoucherMapper;
|
||||
|
||||
@Resource
|
||||
private GiftVoucherTemplateService giftVoucherTemplateService;
|
||||
|
||||
@Override
|
||||
public Long createGiftVoucher(GiftVoucherSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
GiftVoucherDO giftVoucher = BeanUtils.toBean(createReqVO, GiftVoucherDO.class);
|
||||
giftVoucherMapper.insert(giftVoucher);
|
||||
// 返回
|
||||
return giftVoucher.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGiftVoucher(GiftVoucherSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateGiftVoucherExists(updateReqVO.getId());
|
||||
// 更新
|
||||
GiftVoucherDO updateObj = BeanUtils.toBean(updateReqVO, GiftVoucherDO.class);
|
||||
giftVoucherMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteGiftVoucher(Long id) {
|
||||
// 校验存在
|
||||
validateGiftVoucherExists(id);
|
||||
// 删除
|
||||
giftVoucherMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateGiftVoucherExists(Long id) {
|
||||
if (giftVoucherMapper.selectById(id) == null) {
|
||||
throw exception(GIFT_VOUCHER_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiftVoucherDO getGiftVoucher(Long id) {
|
||||
return giftVoucherMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<GiftVoucherDO> getGiftVoucherPage(GiftVoucherPageReqVO pageReqVO) {
|
||||
return giftVoucherMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<Long, List<Long>> takeGiftVoucher(Long templateId, Set<Long> userIds, GiftVoucherTypeEnum takeType) {
|
||||
GiftVoucherTemplateDO template = giftVoucherTemplateService.getGiftVoucherTemplate(templateId);
|
||||
// 1. 过滤掉达到领取限制的用户
|
||||
removeTakeLimitUser(userIds, template);
|
||||
// 2. 校验提货劵是否可以领取
|
||||
validateGiftVoucherTemplateCanTake(template, userIds, takeType);
|
||||
|
||||
// 3. 批量保存优惠劵
|
||||
List<GiftVoucherDO> giftVoucherList = convertList(userIds, userId -> GiftVoucherConvert.INSTANCE.convert(template, userId));
|
||||
giftVoucherMapper.insertBatch(giftVoucherList);
|
||||
|
||||
// 4. 增加优惠劵模板的领取数量
|
||||
giftVoucherTemplateService.updateGiftVoucherTemplateTakeCount(templateId, userIds.size());
|
||||
|
||||
return convertMultiMap(giftVoucherList, GiftVoucherDO::getUserId, GiftVoucherDO::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiftVoucherDO getGiftVoucherByUserId(Long userId, Long id) {
|
||||
return giftVoucherMapper.getGiftVoucherByUserId(userId, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getUnusedCouponCount(Long userId) {
|
||||
return giftVoucherMapper.selectCountByUserIdAndStatus(userId, GiftVoucherStatusEnum.UNUSED.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) {
|
||||
if (CollUtil.isEmpty(templateIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return giftVoucherMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useGiftVoucher(GiftVoucherUseReqDTO giftVoucherUseReqDTO) {
|
||||
// 校验状态
|
||||
GiftVoucherDO giftVoucher = giftVoucherMapper.selectByTemplateIdAndUserId(giftVoucherUseReqDTO.getId(), giftVoucherUseReqDTO.getUserId());
|
||||
if (ObjectUtil.notEqual(giftVoucher.getStatus(), GiftVoucherStatusEnum.UNUSED.getStatus())) {
|
||||
throw exception(GIFT_VOUCHER_STATUS_NOT_UNUSED);
|
||||
}
|
||||
// 校验有效期;为避免定时器没跑,实际优惠劵已经过期
|
||||
if (!LocalDateTimeUtils.isBetween(giftVoucher.getValidStartTime(), giftVoucher.getValidEndTime())) {
|
||||
throw exception(COUPON_VALID_TIME_NOT_NOW);
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
int updateCount = giftVoucherMapper.updateByIdAndStatus(giftVoucherUseReqDTO.getId(), GiftVoucherStatusEnum.UNUSED.getStatus(),
|
||||
new GiftVoucherDO().setStatus(GiftVoucherStatusEnum.USED.getStatus())
|
||||
.setUseOrderId(giftVoucherUseReqDTO.getOrderId()).setUseTime(LocalDateTime.now()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(GIFT_VOUCHER_STATUS_NOT_UNUSED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expireGiftVoucher() {
|
||||
// 1. 查询待过期的优惠券
|
||||
List<GiftVoucherDO> list = giftVoucherMapper.selectListByStatusAndValidEndTimeLe(
|
||||
GiftVoucherStatusEnum.UNUSED.getStatus(), LocalDateTime.now());
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. 遍历执行
|
||||
int count = 0;
|
||||
for (GiftVoucherDO giftVoucher : list) {
|
||||
try {
|
||||
boolean success = expireGiftVoucherOne(giftVoucher);
|
||||
if (success) {
|
||||
count++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[expireCoupon][giftVoucher({}) 更新为已过期失败]", giftVoucher.getId(), e);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期单个提货劵
|
||||
*
|
||||
* @param giftVoucher 提货劵
|
||||
* @return 是否过期成功
|
||||
*/
|
||||
private boolean expireGiftVoucherOne(GiftVoucherDO giftVoucher) {
|
||||
// 更新记录状态
|
||||
int updateRows = giftVoucherMapper.updateByIdAndStatus(giftVoucher.getId(), GiftVoucherStatusEnum.UNUSED.getStatus(),
|
||||
new GiftVoucherDO().setStatus(GiftVoucherStatusEnum.EXPIRE.getStatus()));
|
||||
if (updateRows == 0) {
|
||||
log.error("[expireCoupon][coupon({}) 更新为已过期失败]", giftVoucher.getId());
|
||||
return false;
|
||||
}
|
||||
log.info("[expireCoupon][coupon({}) 更新为已过期成功]", giftVoucher.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉达到领取限制的用户
|
||||
*
|
||||
* @param userIds
|
||||
* @param template
|
||||
*/
|
||||
private void removeTakeLimitUser(Set<Long> userIds, GiftVoucherTemplateDO template) {
|
||||
if (template.getTakeLimitCount() <= 0) {
|
||||
return;
|
||||
}
|
||||
// 查询已领过券的用户
|
||||
List<GiftVoucherDO> alreadyTakeCoupons = giftVoucherMapper.selectListByTemplateIdAndUserIds(template.getId(), userIds);
|
||||
if (CollUtil.isEmpty(alreadyTakeCoupons)) {
|
||||
return;
|
||||
}
|
||||
// 移除达到领取限制的用户
|
||||
Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, GiftVoucherDO::getUserId, Collectors.summingInt(c -> 1));
|
||||
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= template.getTakeLimitCount());
|
||||
}
|
||||
|
||||
private void validateGiftVoucherTemplateCanTake(GiftVoucherTemplateDO template, Set<Long> userIds, GiftVoucherTypeEnum takeType) {
|
||||
// 如果所有用户都领取过,则抛出异常
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_USER_ALREADY_TAKE);
|
||||
}
|
||||
|
||||
// 校验模板
|
||||
if (template == null) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_NOT_EXISTS);
|
||||
}
|
||||
// 校验剩余数量
|
||||
if (template.getTotalCount()>=0) {
|
||||
if (template.getTakeCount() + userIds.size() > template.getTotalCount()) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_NOT_ENOUGH);
|
||||
}
|
||||
}
|
||||
// 校验"固定日期"的有效期类型是否过期
|
||||
if (GiftVoucherTemplateValidityTypeEnum.DATE.getType().equals(template.getValidityType())) {
|
||||
if (LocalDateTimeUtils.beforeNow(template.getValidEndTime())) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_EXPIRED);
|
||||
}
|
||||
}
|
||||
// 校验领取方式
|
||||
if (ObjectUtil.notEqual(template.getTakeType(), takeType.getType())) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_CANNOT_TAKE);
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplateSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 提货券模板 Service 接口
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
public interface GiftVoucherTemplateService {
|
||||
|
||||
/**
|
||||
* 创建提货券模板
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createGiftVoucherTemplate(@Valid GiftVoucherTemplateSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新提货券模板
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateGiftVoucherTemplate(@Valid GiftVoucherTemplateSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除提货券模板
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteGiftVoucherTemplate(Long id);
|
||||
|
||||
/**
|
||||
* 获得提货券模板
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 提货券模板
|
||||
*/
|
||||
GiftVoucherTemplateDO getGiftVoucherTemplate(Long id);
|
||||
|
||||
/**
|
||||
* 获得提货券模板分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 提货券模板分页
|
||||
*/
|
||||
PageResult<GiftVoucherTemplateDO> getGiftVoucherTemplatePage(GiftVoucherTemplatePageReqVO pageReqVO);
|
||||
|
||||
void updateGiftVoucherTemplateTakeCount(Long id, int incrCount);
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.giftvoucher;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.giftvoucher.vo.template.GiftVoucherTemplateSaveReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.giftvoucher.GiftVoucherTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.giftvoucher.GiftVoucherTemplateMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.GIFT_VOUCHER_TEMPLATE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 提货券模板 Service 实现类
|
||||
*
|
||||
* @author 小如之家
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class GiftVoucherTemplateServiceImpl implements GiftVoucherTemplateService {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherTemplateMapper giftVoucherTemplateMapper;
|
||||
|
||||
@Override
|
||||
public Long createGiftVoucherTemplate(GiftVoucherTemplateSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
GiftVoucherTemplateDO giftVoucherTemplate = BeanUtils.toBean(createReqVO, GiftVoucherTemplateDO.class);
|
||||
giftVoucherTemplateMapper.insert(giftVoucherTemplate);
|
||||
// 返回
|
||||
return giftVoucherTemplate.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGiftVoucherTemplate(GiftVoucherTemplateSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateGiftVoucherTemplateExists(updateReqVO.getId());
|
||||
// 更新
|
||||
GiftVoucherTemplateDO updateObj = BeanUtils.toBean(updateReqVO, GiftVoucherTemplateDO.class);
|
||||
giftVoucherTemplateMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteGiftVoucherTemplate(Long id) {
|
||||
// 校验存在
|
||||
validateGiftVoucherTemplateExists(id);
|
||||
// 删除
|
||||
giftVoucherTemplateMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateGiftVoucherTemplateExists(Long id) {
|
||||
if (giftVoucherTemplateMapper.selectById(id) == null) {
|
||||
throw exception(GIFT_VOUCHER_TEMPLATE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiftVoucherTemplateDO getGiftVoucherTemplate(Long id) {
|
||||
return giftVoucherTemplateMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<GiftVoucherTemplateDO> getGiftVoucherTemplatePage(GiftVoucherTemplatePageReqVO pageReqVO) {
|
||||
return giftVoucherTemplateMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGiftVoucherTemplateTakeCount(Long id, int incrCount) {
|
||||
giftVoucherTemplateMapper.updateTakeCount(id, incrCount);
|
||||
}
|
||||
}
|
||||
+7
@@ -104,4 +104,11 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1_011_008_002, "提现金额不能低于 {} 元");
|
||||
ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1_011_008_003, "您当前最多可提现 {} 元");
|
||||
|
||||
|
||||
// ========== 提货券 模块 1-011-009-000 ==========
|
||||
ErrorCode BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE = new ErrorCode(1_011_009_000, "该提货劵无法使用,原因:{}」");
|
||||
ErrorCode BUILD_ORDER_GIFT_VOUCHER_SKU_NOT_EXISTS = new ErrorCode(1_011_009_001, "商品 SKU 不存在");
|
||||
ErrorCode BUILD_ORDER_GIFT_VOUCHER_STOCK_NOT_ENOUGH = new ErrorCode(1_011_009_002, "商品 SKU 库存不足");
|
||||
ErrorCode BUILD_ORDER_GIFT_VOUCHER_SPU_NOT_EXISTS = new ErrorCode(1_011_009_003, "商品 SPU 不存在");
|
||||
ErrorCode BUILD_ORDER_GIFT_VOUCHER_SPU_NOT_ENABLE = new ErrorCode(1_011_009_004, "商品 SPU【{}】不处于上架状态");
|
||||
}
|
||||
+1
@@ -21,6 +21,7 @@ public enum TradeOrderTypeEnum implements ArrayValuable<Integer> {
|
||||
BARGAIN(2, "砍价订单"),
|
||||
COMBINATION(3, "拼团订单"),
|
||||
POINT(4, "积分商城"),
|
||||
GIFTVOUCHER(5, "提货券订单"),
|
||||
;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(TradeOrderTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
+7
@@ -87,6 +87,13 @@ public class AppTradeOrderController {
|
||||
return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId()));
|
||||
}
|
||||
|
||||
@PostMapping("/create-giftvoucher")
|
||||
@Operation(summary = "创建提货码订单")
|
||||
public CommonResult<Long> createGiftVoucherOrder(@Valid @RequestBody AppGiftVoucherOrderSettlementReqVO createReqVO) {
|
||||
TradeOrderDO order = tradeOrderUpdateService.createGiftVoucherOrder(getLoginUserId(), createReqVO);
|
||||
return success(order.getId());
|
||||
}
|
||||
|
||||
@PostMapping("/update-paid")
|
||||
@Operation(summary = "更新订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 交易订单结算 Request VO")
|
||||
@Data
|
||||
@Valid
|
||||
public class AppGiftVoucherOrderSettlementReqVO {
|
||||
|
||||
@Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "商品不能为空")
|
||||
private List<Item> items;
|
||||
|
||||
@Schema(description = "提货劵编号", example = "1024")
|
||||
private Long giftVoucherId;
|
||||
|
||||
// ========== 配送相关相关字段 ==========
|
||||
@Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确")
|
||||
private Integer deliveryType;
|
||||
|
||||
@Schema(description = "收件地址编号", example = "1")
|
||||
private Long addressId;
|
||||
|
||||
@Schema(description = "自提门店编号", example = "1088")
|
||||
private Long pickUpStoreId;
|
||||
@Schema(description = "收件人名称", example = "芋艿") // 选择门店自提时,该字段为联系人名
|
||||
private String receiverName;
|
||||
@Schema(description = "收件人手机", example = "15601691300") // 选择门店自提时,该字段为联系人手机
|
||||
@Mobile(message = "收件人手机格式不正确")
|
||||
private String receiverMobile;
|
||||
|
||||
@Schema(description = "备注", example = "这个是我的订单哟")
|
||||
private String remark;
|
||||
|
||||
@AssertTrue(message = "配送方式不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isDeliveryTypeNotNull() {
|
||||
return deliveryType != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "提货商品每次只能购买一种规格")
|
||||
@JsonIgnore
|
||||
public boolean isValidActivityItems() {
|
||||
// 校验订单项是否超出
|
||||
return items.size() == 1;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Schema(description = "用户 App - 商品项")
|
||||
@Valid
|
||||
public static class Item {
|
||||
|
||||
@Schema(description = "商品 SKU 编号", example = "2048")
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "购买数量", example = "1")
|
||||
@Min(value = 1, message = "购买数量最小值为 {value}")
|
||||
private Integer count;
|
||||
|
||||
@AssertTrue(message = "商品不正确")
|
||||
@JsonIgnore
|
||||
public boolean isValid() {
|
||||
// 组合一:skuId + count 使用商品 SKU
|
||||
return skuId != null && count != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -34,6 +34,7 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn
|
||||
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
|
||||
import cn.iocoder.yudao.module.trade.service.order.bo.GiftVoucherCalculateRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
||||
import org.mapstruct.Mapper;
|
||||
@@ -286,4 +287,18 @@ public interface TradeOrderConvert {
|
||||
})
|
||||
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO item);
|
||||
|
||||
default List<TradeOrderItemDO> convertGiftVoucherOrderList(TradeOrderDO order, GiftVoucherCalculateRespBO calculateRespBO){
|
||||
return CollectionUtils.convertList(calculateRespBO.getItems(), item -> {
|
||||
TradeOrderItemDO orderItem = convert(item);
|
||||
orderItem.setUserId(order.getUserId());
|
||||
orderItem.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
|
||||
orderItem.setCommentStatus(false);
|
||||
return orderItem;
|
||||
});
|
||||
}
|
||||
|
||||
TradeOrderItemDO convert(GiftVoucherCalculateRespBO.OrderItem item);
|
||||
|
||||
TradeOrderDO convert(Long userId, GiftVoucherCalculateRespBO calculateRespBO);
|
||||
|
||||
}
|
||||
+6
@@ -360,4 +360,10 @@ public class TradeOrderDO extends BaseDO {
|
||||
*/
|
||||
private Long pointActivityId;
|
||||
|
||||
/**
|
||||
* 提货劵编号
|
||||
*/
|
||||
private Long giftVoucherId;
|
||||
|
||||
|
||||
}
|
||||
+2
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliver
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppGiftVoucherOrderSettlementReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
|
||||
@@ -220,4 +221,5 @@ public interface TradeOrderUpdateService {
|
||||
*/
|
||||
void updateOrderGiveCouponIds(Long userId, Long orderId, List<Long> giveCouponIds);
|
||||
|
||||
TradeOrderDO createGiftVoucherOrder(Long userId, AppGiftVoucherOrderSettlementReqVO createReqVO);
|
||||
}
|
||||
+137
@@ -12,6 +12,7 @@ import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
@@ -27,13 +28,18 @@ import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
|
||||
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.enums.sku.ProductSkuPurchaseBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.GiftVoucherApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppGiftVoucherOrderSettlementReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
|
||||
@@ -57,6 +63,7 @@ import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
||||
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService;
|
||||
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
|
||||
import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
|
||||
import cn.iocoder.yudao.module.trade.service.order.bo.GiftVoucherCalculateRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
|
||||
import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
|
||||
@@ -84,6 +91,7 @@ import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.min
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getTerminal;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BUILD_ORDER_GIFT_VOUCHER_SPU_NOT_ENABLE;
|
||||
import static cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants.WXA_ORDER_DELIVERY;
|
||||
|
||||
/**
|
||||
@@ -129,10 +137,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
public PayRefundApi payRefundApi;
|
||||
@Resource
|
||||
public ProductSkuApi productSkuApi;
|
||||
@Resource
|
||||
public ProductSpuApi productSpuApi;
|
||||
|
||||
@Resource
|
||||
private TradeOrderProperties tradeOrderProperties;
|
||||
|
||||
@Resource
|
||||
private GiftVoucherApi giftVoucherApi;
|
||||
|
||||
// =================== Order ===================
|
||||
|
||||
public List<TradeOrderItemDO> findUserSuccessOrderItem(Long payUserId, List<Long> skuIdList, ProductSkuPurchaseBizTypeEnum status) {
|
||||
@@ -987,6 +1000,130 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
tradeOrderMapper.updateById(new TradeOrderDO().setId(orderId).setGiveCouponIds(giveCouponIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeOrderDO createGiftVoucherOrder(Long userId, AppGiftVoucherOrderSettlementReqVO createReqVO) {
|
||||
|
||||
// 1 构建订单
|
||||
GiftVoucherCalculateRespBO giftVoucherCalculateRespBO=giftVoucherCalculate(userId, createReqVO);
|
||||
TradeOrderDO order = buildGiftVoucherOrder(userId, giftVoucherCalculateRespBO);
|
||||
List<TradeOrderItemDO> orderItems = buildGiftVoucherOrderItems(order,giftVoucherCalculateRespBO);
|
||||
|
||||
// 2. 订单创建前的逻辑
|
||||
tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));
|
||||
|
||||
// 3. 保存订单
|
||||
tradeOrderMapper.insert(order);
|
||||
orderItems.forEach(orderItem -> orderItem.setOrderId(order.getId()));
|
||||
tradeOrderItemMapper.insertBatch(orderItems);
|
||||
|
||||
// 4. 订单创建后的逻辑
|
||||
tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems));
|
||||
// 5. 插入订单日志
|
||||
TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus());
|
||||
return order;
|
||||
}
|
||||
|
||||
private TradeOrderDO buildGiftVoucherOrder(Long userId, GiftVoucherCalculateRespBO calculateRespBO) {
|
||||
return TradeOrderConvert.INSTANCE.convert(userId,calculateRespBO);
|
||||
}
|
||||
|
||||
private List<TradeOrderItemDO> buildGiftVoucherOrderItems(TradeOrderDO order, GiftVoucherCalculateRespBO calculateRespBO) {
|
||||
|
||||
return TradeOrderConvert.INSTANCE.convertGiftVoucherOrderList(order,calculateRespBO);
|
||||
}
|
||||
|
||||
private GiftVoucherCalculateRespBO giftVoucherCalculate(Long userId, AppGiftVoucherOrderSettlementReqVO createReqVO) {
|
||||
//看提货券是否可用
|
||||
GiftVoucherRespDTO giftVoucher=giftVoucherApi.getGiftVoucherById(createReqVO.getGiftVoucherId());
|
||||
if (null == giftVoucher) {
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE, "提货劵不存在");
|
||||
}
|
||||
if (giftVoucher.getStatus()!=1){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE, "提货劵已使用或已失效");
|
||||
}
|
||||
if (LocalDateTimeUtils.beforeNow(giftVoucher.getValidEndTime())) {
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"提货券已过期");
|
||||
}
|
||||
if (LocalDateTimeUtils.afterNow(giftVoucher.getValidStartTime())) {
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"提货券未生效");
|
||||
}
|
||||
|
||||
if (!Objects.equals(createReqVO.getItems().get(0).getCount(), giftVoucher.getProductCount())){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"购买商品数量与提货券可购买数量不一致");
|
||||
}
|
||||
if (!Objects.equals(userId, giftVoucher.getUserId())){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"当前用户与提货券用户不一致");
|
||||
}
|
||||
|
||||
if (createReqVO.getItems().size()>1){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"提货券只允许购买一种商品");
|
||||
}
|
||||
//看商品是否可用
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(createReqVO.getItems().get(0).getSkuId());
|
||||
if (null == sku) {
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_SKU_NOT_EXISTS);
|
||||
}
|
||||
if(sku.getStock()<createReqVO.getItems().get(0).getCount()){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_STOCK_NOT_ENOUGH);
|
||||
}
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(sku.getSpuId());
|
||||
if (null == spu) {
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_SPU_NOT_EXISTS);
|
||||
}
|
||||
//提货券的商品范围是否包含购买的商品
|
||||
if (!giftVoucher.getProductScopeValues().contains(createReqVO.getItems().get(0).getSkuId())){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_CAN_NOT_USE,"该提货券无法购买此商品");
|
||||
}
|
||||
if (spu.getStatus()!=1){
|
||||
throw exception(BUILD_ORDER_GIFT_VOUCHER_SPU_NOT_ENABLE,spu.getName());
|
||||
}
|
||||
GiftVoucherCalculateRespBO order = new GiftVoucherCalculateRespBO();
|
||||
order.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.TRADE_ORDER_NO_PREFIX));
|
||||
order.setType(TradeOrderTypeEnum.GIFTVOUCHER.getType());
|
||||
order.setUserIp(getClientIP()).setTerminal(getTerminal()).setUserId(userId);
|
||||
order.setUserRemark(createReqVO.getRemark());
|
||||
//待发货
|
||||
order.setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
||||
order.setProductCount(createReqVO.getItems().get(0).getCount());
|
||||
order.setPayStatus(true).setPayTime(LocalDateTime.now());
|
||||
order.setTotalPrice(sku.getPrice()*createReqVO.getItems().get(0).getCount());
|
||||
order.setDeliveryType(createReqVO.getDeliveryType());
|
||||
if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) {
|
||||
MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId);
|
||||
Assert.notNull(address, "地址({}) 不能为空", createReqVO.getAddressId()); // 价格计算时,已经计算
|
||||
order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile())
|
||||
.setReceiverAreaId(address.getAreaId()).setReceiverDetailAddress(address.getDetailAddress());
|
||||
} else if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.PICK_UP.getType())) {
|
||||
order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile());
|
||||
order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位
|
||||
}
|
||||
order.setPickUpStoreId(createReqVO.getPickUpStoreId());
|
||||
order.setGiftVoucherId(createReqVO.getGiftVoucherId());
|
||||
|
||||
//子项
|
||||
GiftVoucherCalculateRespBO.OrderItem orderItem = new GiftVoucherCalculateRespBO.OrderItem();
|
||||
orderItem.setSpuId(sku.getSpuId()).setSkuId(sku.getId())
|
||||
.setCount(createReqVO.getItems().get(0).getCount());
|
||||
// sku 价格
|
||||
orderItem.setPrice(sku.getPrice()).setPayPrice(0)
|
||||
.setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
|
||||
// sku 信息
|
||||
orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties())
|
||||
.setWeight(sku.getWeight()).setVolume(sku.getVolume());
|
||||
// spu 信息
|
||||
orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId())
|
||||
.setDeliveryTypes(spu.getDeliveryTypes()).setDeliveryTemplateId(spu.getDeliveryTemplateId())
|
||||
.setGivePoint(spu.getGiveIntegral()).setUsePoint(0);
|
||||
if (StrUtil.isBlank(orderItem.getPicUrl())) {
|
||||
orderItem.setPicUrl(spu.getPicUrl());
|
||||
}
|
||||
if(order.getItems()==null){
|
||||
order.setItems(new ArrayList<>()); // 初始化 items
|
||||
}
|
||||
order.getItems().add(orderItem);
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建单个订单的评论
|
||||
*
|
||||
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
package cn.iocoder.yudao.module.trade.service.order.bo;
|
||||
|
||||
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提货券构建订单 Response BO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class GiftVoucherCalculateRespBO extends TradeOrderDO {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 订单项数组
|
||||
*/
|
||||
private List<OrderItem> items;
|
||||
|
||||
/**
|
||||
* 订单商品 SKU
|
||||
*/
|
||||
@Data
|
||||
public static class OrderItem {
|
||||
|
||||
/**
|
||||
* SPU 编号
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* SKU 编号
|
||||
*/
|
||||
private Long skuId;
|
||||
/**
|
||||
* 购买数量
|
||||
*/
|
||||
private Integer count;
|
||||
/**
|
||||
* 购物车项的编号
|
||||
*/
|
||||
private Long cartId;
|
||||
/**
|
||||
* 是否选中
|
||||
*/
|
||||
private Boolean selected;
|
||||
|
||||
/**
|
||||
* 商品原价(单),单位:分
|
||||
*
|
||||
* 对应 ProductSkuDO 的 price 字段
|
||||
* 对应 taobao 的 order.price 字段
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 优惠金额(总),单位:分
|
||||
*
|
||||
* 对应 taobao 的 order.discount_fee 字段
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 运费金额(总),单位:分
|
||||
*/
|
||||
private Integer deliveryPrice;
|
||||
/**
|
||||
* 优惠劵减免金额,单位:分
|
||||
*
|
||||
* 对应 taobao 的 trade.coupon_fee 字段
|
||||
*/
|
||||
private Integer couponPrice;
|
||||
/**
|
||||
* 积分抵扣的金额,单位:分
|
||||
*
|
||||
* 对应 taobao 的 trade.point_fee 字段
|
||||
*/
|
||||
private Integer pointPrice;
|
||||
/**
|
||||
* 使用的积分
|
||||
*/
|
||||
private Integer usePoint;
|
||||
/**
|
||||
* VIP 减免金额,单位:分
|
||||
*/
|
||||
private Integer vipPrice;
|
||||
/**
|
||||
* 应付金额(总),单位:分
|
||||
*
|
||||
* = {@link #price} * {@link #count}
|
||||
* - {@link #couponPrice}
|
||||
* - {@link #pointPrice}
|
||||
* - {@link #discountPrice}
|
||||
* + {@link #deliveryPrice}
|
||||
* - {@link #vipPrice}
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
// ========== 商品 SPU 信息 ==========
|
||||
/**
|
||||
* 商品名
|
||||
*/
|
||||
private String spuName;
|
||||
/**
|
||||
* 商品图片
|
||||
*
|
||||
* 优先级:SKU.picUrl > SPU.picUrl
|
||||
*/
|
||||
private String picUrl;
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Long categoryId;
|
||||
|
||||
// ========== 物流相关字段 =========
|
||||
|
||||
/**
|
||||
* 配送方式数组
|
||||
*
|
||||
* 对应 DeliveryTypeEnum 枚举
|
||||
*/
|
||||
private List<Integer> deliveryTypes;
|
||||
|
||||
/**
|
||||
* 物流配置模板编号
|
||||
*
|
||||
* 对应 TradeDeliveryExpressTemplateDO 的 id 编号
|
||||
*/
|
||||
private Long deliveryTemplateId;
|
||||
|
||||
// ========== 商品 SKU 信息 ==========
|
||||
/**
|
||||
* 商品重量,单位:kg 千克
|
||||
*/
|
||||
private Double weight;
|
||||
/**
|
||||
* 商品体积,单位:m^3 平米
|
||||
*/
|
||||
private Double volume;
|
||||
|
||||
/**
|
||||
* 商品属性数组
|
||||
*/
|
||||
private List<ProductPropertyValueDetailRespDTO> properties;
|
||||
|
||||
/**
|
||||
* 赠送的积分
|
||||
*/
|
||||
private Integer givePoint;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+2
-1
@@ -32,7 +32,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_RECEIVE_FAIL_STATUS_NOT_OVERPAY;
|
||||
|
||||
/**
|
||||
* 优惠劵的 {@link TradeOrderHandler} 实现类
|
||||
* 贩卖机出货的 {@link TradeOrderHandler} 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@@ -182,6 +182,7 @@ public class TradeDeviceOrderHandler implements TradeOrderHandler {
|
||||
}
|
||||
}else {
|
||||
System.out.println("提货柜订单spu列表为空");
|
||||
log.error("订单:{},提货柜订单spu列表为空",order.getNo());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
package cn.iocoder.yudao.module.trade.service.order.handler;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTypesEnum;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.GiftVoucherApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.giftvoucher.dto.GiftVoucherUseReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.service.order.bo.DispenseRequestBo;
|
||||
import cn.iocoder.yudao.module.trade.service.order.bo.DispenseResponseBo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_RECEIVE_FAIL_STATUS_NOT_OVERPAY;
|
||||
|
||||
/**
|
||||
* 提货劵的 {@link TradeOrderHandler} 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TradeGiftVoucherOrderHandler implements TradeOrderHandler {
|
||||
|
||||
@Resource
|
||||
private GiftVoucherApi giftVoucherApi;
|
||||
|
||||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
|
||||
@Resource
|
||||
private ProductSkuApi productSkuApi;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Resource
|
||||
private TradeOrderMapper tradeOrderMapper;
|
||||
|
||||
// TOKEN
|
||||
@Value("${xr.cabinet.token}")
|
||||
private String token;
|
||||
|
||||
//API_URL
|
||||
@Value("${xr.cabinet.api_url}")
|
||||
private String api_url;
|
||||
|
||||
@Override
|
||||
public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
||||
if (order.getGiftVoucherId() == null || order.getGiftVoucherId() <= 0) {
|
||||
return;
|
||||
}
|
||||
//提货券商品的贩卖机出货
|
||||
//商品SPU ID列表
|
||||
List<Long> spuIds = orderItems.stream()
|
||||
.map(TradeOrderItemDO::getSpuId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
// if(null==spuIds && spuIds.size()<=0){
|
||||
// System.out.println("商品SPU ID列表 为空");
|
||||
// return;
|
||||
// }
|
||||
//查询spu表
|
||||
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
|
||||
//判断商品类型是否有不是提货柜商品的
|
||||
if (CollUtil.isNotEmpty(spuList)) {
|
||||
boolean hasNonDevice = spuList.stream()
|
||||
.anyMatch(spu -> !ProductSpuTypesEnum.ENABLE.getTypes().equals(spu.getTypes()));
|
||||
if (hasNonDevice) {
|
||||
//订单中包含非提货柜商品
|
||||
log.info("订单中包含非提货柜商品");
|
||||
}else {
|
||||
//判断是不是有不同机器的订单(一个创建人是一台机器)
|
||||
boolean isSingleCreator = spuList.stream()
|
||||
.map(ProductSpuRespDTO::getCreator) //获取每个商品的Creator
|
||||
.distinct() //去重Creator
|
||||
.count() == 1; // 判断是否只有一个唯一的创建人
|
||||
if (isSingleCreator) {
|
||||
// 只有一个Creator的逻辑处理
|
||||
System.out.println("订单明细中只有一个商品创建人");
|
||||
//查询商品创建人的设备IMEI
|
||||
AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(spuList.get(0).getCreator()));
|
||||
if (user == null|| user.getDeviceId() == null){
|
||||
return;
|
||||
}
|
||||
//获取商品通道
|
||||
List<Long> skuIds = orderItems.stream()
|
||||
.map(TradeOrderItemDO::getSkuId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if(CollUtil.isEmpty(skuIds)){
|
||||
return;
|
||||
}
|
||||
List<ProductSkuRespDTO> skuList = productSkuApi.getSkuList(skuIds);
|
||||
//判断是不是有不同通道类型的订单
|
||||
boolean isSingleCabinetType = skuList.stream()
|
||||
.map(ProductSkuRespDTO::getCabinetType) //获取每个商品的Creator
|
||||
.distinct() //去重Creator
|
||||
.count() == 1; // 判断是否只有一个唯一的创建人
|
||||
if (isSingleCabinetType) {
|
||||
DispenseRequestBo request = new DispenseRequestBo();
|
||||
request.setDeviceId(user.getDeviceId());
|
||||
StringBuilder message= new StringBuilder(skuList.get(0).getCabinetType() + ",");
|
||||
//遍历订单明细
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
TradeOrderItemDO orderItem = orderItems.get(i);
|
||||
ProductSkuRespDTO sku = productSkuApi.getSku(orderItem.getSkuId());
|
||||
message.append(sku.getCabinetChannel()).append("&").append(orderItem.getCount());
|
||||
if (i != orderItems.size() - 1) {
|
||||
message.append(",");
|
||||
}
|
||||
}
|
||||
request.setMessage(message.toString());
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", token);
|
||||
|
||||
// 创建请求实体
|
||||
HttpEntity<DispenseRequestBo> requestEntity = new HttpEntity<>(request, headers);
|
||||
|
||||
// 创建RestTemplate
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
try {
|
||||
// 发送请求并解析响应
|
||||
ResponseEntity<DispenseResponseBo> response = restTemplate.exchange(
|
||||
api_url,
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
DispenseResponseBo.class
|
||||
);
|
||||
|
||||
DispenseResponseBo body = response.getBody();
|
||||
if (body != null) {
|
||||
System.out.println("响应结果: " + body);
|
||||
if (body.getCode() == 0) {
|
||||
System.out.println("出货成功!详情: " + body.getData());
|
||||
} else {
|
||||
System.out.println("操作失败!原因: " + body.getMsg());
|
||||
log.error("订单--{}:[出货失败]:原因: {}",order.getNo(), body.getMsg());
|
||||
}
|
||||
}
|
||||
// 3. 更新 TradeOrderDO 状态为已完成
|
||||
TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(order.getId());
|
||||
int updateCount = tradeOrderMapper.updateByIdAndStatus(tradeOrderDO.getId(), tradeOrderDO.getStatus(),
|
||||
new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_OVERPAY);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("请求异常: " + e.getMessage());
|
||||
log.error("订单--{}:[出货异常]:原因: {}",order.getNo(), e.getMessage());
|
||||
}
|
||||
}else {
|
||||
System.out.println("订单明细中包含多个通道类型");
|
||||
log.error("订单:{},明细中包含多个通道类型",order.getNo());
|
||||
}
|
||||
} else {
|
||||
System.out.println("订单明细中包含多个商品创建人");
|
||||
log.error("订单:{},明细中包含多个商品创建人",order.getNo());
|
||||
}
|
||||
}
|
||||
}else {
|
||||
System.out.println("提货柜订单spu列表为空");
|
||||
log.error("订单:{},提货柜订单spu列表为空",order.getNo());
|
||||
}
|
||||
// 提货券更改为已使用
|
||||
giftVoucherApi.useGiftVoucher(new GiftVoucherUseReqDTO().setId(order.getGiftVoucherId()).setUserId(order.getUserId())
|
||||
.setOrderId(order.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,7 +80,7 @@ spring:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 10 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
password: 123456 # 密码,建议生产环境开启
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ spring:
|
||||
name: yudao-server
|
||||
|
||||
profiles:
|
||||
# active: prod
|
||||
active: local
|
||||
active: prod
|
||||
# active: local
|
||||
|
||||
main:
|
||||
allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。
|
||||
|
||||
Reference in new issue
Block a user