diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java index 2081e7da8..ac9713423 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java @@ -1,14 +1,57 @@ package cn.iocoder.yudao.module.product.controller.admin.sku; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + @Api(tags = "管理后台 - 商品 sku") @RestController @RequestMapping("/product/sku") @Validated public class ProductSkuController { + @Resource + private ProductSkuService productSkuService; + @Resource + private ProductSpuService productSpuService; + + @GetMapping("/get-option-list") + @ApiOperation("获得商品 SKU 选项的列表") +// @PreAuthorize("@ss.hasPermission('product:sku:query')") + public CommonResult> getSkuOptionList() { + // 获得 SKU 列表 + List skus = productSkuService.getSkuList(); + if (CollUtil.isEmpty(skus)) { + return success(Collections.emptyList()); + } + + // 获得对应的 SPU 映射 + Map spuMap = productSpuService.getSpuMap(convertSet(skus, ProductSkuDO::getSpuId)); + // 转换为返回结果 + List skuVOs = ProductSkuConvert.INSTANCE.convertList05(skus); + skuVOs.forEach(sku -> MapUtils.findAndThen(spuMap, sku.getSpuId(), + spu -> sku.setSpuId(spu.getId()).setSpuName(spu.getName()))); + return success(skuVOs); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuOptionRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuOptionRespVO.java new file mode 100644 index 000000000..0324bdc8d --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuOptionRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.product.controller.admin.sku.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel(value = "管理后台 - 商品 SKU 选项 Response VO", description = "用于前端 SELECT 选项") +@Data +public class ProductSkuOptionRespVO { + + @ApiModelProperty(value = "主键", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "商品 SKU 名字", example = "红色") + private String name; + + @ApiModelProperty(value = "销售价格", required = true, example = "100", notes = "单位:分") + private String price; + + @ApiModelProperty(value = "库存", required = true, example = "100") + private Integer stock; + + // ========== 商品 SPU 信息 ========== + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long spuId; + + @ApiModelProperty(value = "商品 SPU 名字", required = true, example = "iPhone 11") + private String spuName; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java index 46e76cc63..f46c3d3bc 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java @@ -9,7 +9,7 @@ import lombok.ToString; import java.util.Date; import java.util.List; -@ApiModel("管理后台 - 商品sku Response VO") +@ApiModel("管理后台 - 商品 SKU Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java index 4b8bb45f0..c96cd41db 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.convert.sku; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuDetailRespVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; @@ -11,7 +12,7 @@ import org.mapstruct.factory.Mappers; import java.util.List; /** - * 商品sku Convert + * 商品 SKU Convert * * @author 芋道源码 */ @@ -36,4 +37,6 @@ public interface ProductSkuConvert { List convertList04(List list); + List convertList05(List skus); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java index 25b91525c..f953534ed 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java @@ -97,6 +97,7 @@ public class ProductSkuDO extends BaseDO { * 商品属性 */ @Data + @NoArgsConstructor @AllArgsConstructor public static class Property { @@ -130,19 +131,5 @@ public class ProductSkuDO extends BaseDO { } - // TODO ========== 待定字段:yv ========= - // TODO brokerage:一级返佣 - // TODO brokerage_two:二级返佣 - // TODO pink_price:拼团价 - // TODO pink_stock:拼团库存 - // TODO seckill_price:秒杀价 - // TODO seckill_stock:秒杀库存 - // TODO integral:需要积分 - - // TODO ========== 待定字段:cf ========= - // TODO type 活动显示排序 0=默认 1=秒 2=砍价 3=拼团 - // TODO quota 活动限购数量 - // TODO quota_show 活动限购数量显示 - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index acde66a4a..8bdfe49d9 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -14,22 +14,29 @@ import java.util.List; public interface ProductSkuService { /** - * 删除商品sku + * 删除商品 SKU * * @param id 编号 */ void deleteSku(Long id); /** - * 获得商品sku + * 获得商品 SKU 信息 * * @param id 编号 - * @return 商品sku + * @return 商品 SKU 信息 */ ProductSkuDO getSku(Long id); /** - * 获得商品sku列表 + * 获得商品 SKU 列表 + * + * @return 商品sku列表 + */ + List getSkuList(); + + /** + * 获得商品 SKU 列表 * * @param ids 编号 * @return 商品sku列表 diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index 952fbeb74..d9b90b0f3 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -61,6 +61,11 @@ public class ProductSkuServiceImpl implements ProductSkuService { return productSkuMapper.selectById(id); } + @Override + public List getSkuList() { + return productSkuMapper.selectList(); + } + @Override public List getSkuList(Collection ids) { return productSkuMapper.selectBatchIds(ids); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java index e32c1f700..6ae7e8996 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java @@ -9,6 +9,9 @@ import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import javax.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商品 SPU Service 接口 @@ -63,6 +66,16 @@ public interface ProductSpuService { */ List getSpuList(Collection ids); + /** + * 获得商品 SPU 映射 + * + * @param ids 编号数组 + * @return 商品 SPU 映射 + */ + default Map getSpuMap(Collection ids) { + return convertMap(getSpuList(ids), ProductSpuDO::getId); + } + /** * 获得所有商品 SPU 列表 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java index fab744b80..0c50db779 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java @@ -130,11 +130,11 @@ public class CouponTemplateBaseVO { || fixedEndTerm != null; } - @AssertTrue(message = "折扣百分比需要大于等于 1") + @AssertTrue(message = "折扣百分比需要大于等于 1,小于等于 99") @JsonIgnore public boolean isDiscountPercentValid() { return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType()) - || (discountPercent != null && discountPercent >= 1); + || (discountPercent != null && discountPercent >= 1 && discountPercent<= 99); } @AssertTrue(message = "优惠金额不能为空") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java index 370a22848..e1eafcca9 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java @@ -1,10 +1,15 @@ package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import java.util.Date; @@ -47,10 +52,31 @@ public class DiscountActivityBaseVO { @NotNull(message = "商品 SKU 编号不能为空") private Long skuId; - @ApiModelProperty(value = "折扣价格,单位:分", required = true, example = "1000") - @NotNull(message = "折扣价格不能为空") - @Min(value = 1, message = "折扣价格必须大于 0") + @ApiModelProperty(value = "优惠类型", required = true, example = "1", notes = "参见 PromotionDiscountTypeEnum 枚举") + @NotNull(message = "优惠类型不能为空") + @InEnum(PromotionDiscountTypeEnum.class) + private Integer discountType; + + @ApiModelProperty(value = "折扣百分比", example = "80", notes = "例如说,80% 为 80") + private Integer discountPercent; + + @ApiModelProperty(value = "优惠金额", example = "10", notes = "单位:分") + @Min(value = 0, message = "优惠金额需要大于等于 0") private Integer discountPrice; + @AssertTrue(message = "折扣百分比需要大于等于 1,小于等于 99") + @JsonIgnore + public boolean isDiscountPercentValid() { + return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType()) + || (discountPercent != null && discountPercent >= 1 && discountPercent<= 99); + } + + @AssertTrue(message = "优惠金额不能为空") + @JsonIgnore + public boolean isDiscountPriceValid() { + return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PRICE.getType()) + || discountPrice != null; + } + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java index 6bf08ab97..35de6faf2 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java @@ -5,7 +5,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import javax.validation.constraints.NotNull; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import java.util.List; @ApiModel("管理后台 - 限时折扣活动创建 Request VO") @@ -17,7 +18,8 @@ public class DiscountActivityCreateReqVO extends DiscountActivityBaseVO { /** * 商品列表 */ - @NotNull(message = "商品列表不能为空") + @NotEmpty(message = "商品列表不能为空") + @Valid private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java index 675dfb529..0f3b6e435 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java @@ -6,6 +6,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -22,7 +24,8 @@ public class DiscountActivityUpdateReqVO extends DiscountActivityBaseVO { /** * 商品列表 */ - @NotNull(message = "商品列表不能为空") + @NotEmpty(message = "商品列表不能为空") + @Valid private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java index 7f5323515..55c924e4f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.discount; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -41,8 +42,23 @@ public class DiscountProductDO extends BaseDO { * 关联 ProductSkuDO 的 id 编号 */ private Long skuId; + /** - * 优惠价格,单位:分 + * 折扣类型 + * + * 枚举 {@link PromotionDiscountTypeEnum} + */ + private Integer discountType; + /** + * 折扣百分比 + * + * 例如,80% 为 80 + */ + private Integer discountPercent; + /** + * 优惠金额,单位:分 + * + * 当 {@link #discountType} 为 {@link PromotionDiscountTypeEnum#PRICE} 生效 */ private Integer discountPrice; diff --git a/yudao-ui-admin/src/api/mall/product/sku.js b/yudao-ui-admin/src/api/mall/product/sku.js new file mode 100644 index 000000000..72b401074 --- /dev/null +++ b/yudao-ui-admin/src/api/mall/product/sku.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 获得商品 SKU 选项的列表 +export function getSkuOptionList() { + return request({ + url: '/product/sku/get-option-list', + method: 'get', + }) +} diff --git a/yudao-ui-admin/src/api/mall/product/spu.js b/yudao-ui-admin/src/api/mall/product/spu.js index 3e35a358a..7cce82f3b 100644 --- a/yudao-ui-admin/src/api/mall/product/spu.js +++ b/yudao-ui-admin/src/api/mall/product/spu.js @@ -1,6 +1,6 @@ import request from '@/utils/request' -// 创建商品spu +// 创建商品 SPU export function createSpu(data) { return request({ url: '/product/spu/create', @@ -9,7 +9,7 @@ export function createSpu(data) { }) } -// 更新商品spu +// 更新商品 SPU export function updateSpu(data) { return request({ url: '/product/spu/update', @@ -18,7 +18,7 @@ export function updateSpu(data) { }) } -// 删除商品spu +// 删除商品 SPU export function deleteSpu(id) { return request({ url: '/product/spu/delete?id=' + id, @@ -34,7 +34,7 @@ export function getSpu(id) { }) } -// 获得商品spu详情 +// 获得商品 SPU 详情 export function getSpuDetail(id) { return request({ url: '/product/spu/get/detail?id=' + id, @@ -42,7 +42,7 @@ export function getSpuDetail(id) { }) } -// 获得商品spu分页 +// 获得商品 SPU 分页 export function getSpuPage(query) { return request({ url: '/product/spu/page', diff --git a/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue b/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue index fa7f8ccf6..b0998ae9a 100755 --- a/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue +++ b/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue @@ -70,7 +70,7 @@ @pagination="getList"/> - + @@ -80,7 +80,54 @@ + value-format="timestamp" placeholder="选择开始时间" style="width: 880px" /> + + + + + {{ item.spuName }}   {{ item.name}} + ¥{{ (item.price / 100.0).toFixed(2) }} + + + + + + + + + + + + + + + + + + + +