From 4ea49f82bba11c72c84ca4c5d8af12f6c14b30cd Mon Sep 17 00:00:00 2001 From: DB <2502523450@qq.com> Date: Mon, 6 Nov 2023 17:55:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=B4=AD=E7=89=A9=E8=BD=A6;?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=B4=AD=E4=B9=B0=E9=99=90=E5=88=B6=E7=AD=96?= =?UTF-8?q?=E7=95=A5;=E8=B0=83=E6=95=B4=E9=A2=84=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cpop/generator/CpopGenerator.java | 6 +- .../cpop/mall/business/bo/PlaceOrderBo.java | 3 +- .../cpop/mall/business/bo/ShoppingCartBo.java | 57 +++++++++ .../mall/business/bo/ShoppingCartPageBo.java | 25 ++++ .../controller/mini/MiniOrderController.java | 16 ++- .../mini/MiniProductController.java | 19 ++- .../mini/MiniShoppingCartController.java | 78 ++++++++++++ .../mall/business/entity/ShoppingCart.java | 68 +++++++++++ .../business/mapper/ShoppingCartMapper.java | 14 +++ .../mall/business/service/OrderService.java | 8 ++ .../mall/business/service/ProductService.java | 8 ++ .../business/service/ShoppingCartService.java | 35 ++++++ .../service/impl/OrderServiceImpl.java | 49 +++++++- .../service/impl/ProductServiceImpl.java | 12 ++ .../service/impl/ShoppingCartServiceImpl.java | 81 +++++++++++++ .../business/vo/MiniShoppingCartPageVo.java | 91 ++++++++++++++ .../cpop/mall/business/vo/OrderInfoVo.java | 1 + .../cpop/mall/business/vo/ProductInfoVo.java | 111 ++++++++++++++++++ .../framework/enums/BuyRestrictEnums.java | 75 ++++++++++++ .../buyRestrict/BuyRestrictStrategy.java | 19 +++ .../buyRestrict/MemberRestrictStrategy.java | 61 ++++++++++ .../NewCustomerRestrictStrategy.java | 45 +++++++ .../buyRestrict/UserRestrictStrategy.java | 66 +++++++++++ .../resources/mapper/ShoppingCartMapper.xml | 7 ++ 24 files changed, 944 insertions(+), 11 deletions(-) create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartBo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartPageBo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniShoppingCartController.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/entity/ShoppingCart.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/ShoppingCartMapper.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/service/ShoppingCartService.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ShoppingCartServiceImpl.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/vo/MiniShoppingCartPageVo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductInfoVo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/BuyRestrictEnums.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/BuyRestrictStrategy.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/MemberRestrictStrategy.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/NewCustomerRestrictStrategy.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/UserRestrictStrategy.java create mode 100644 Cpop-Mall/src/main/resources/mapper/ShoppingCartMapper.xml diff --git a/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java b/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java index f79a6c4..550d8b1 100644 --- a/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java +++ b/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java @@ -40,17 +40,17 @@ public class CpopGenerator { /** * 输出路径 */ - private static final String EXPORT_URL = "/Cpop-System"; + private static final String EXPORT_URL = "/Cpop-Mall"; /** * 模块 */ - private static final String EXPORT_ITEM = "system"; + private static final String EXPORT_ITEM = "mall"; /** * 表前缀 */ - private static final String TABLE_PREFIX = "cp_sys_"; + private static final String TABLE_PREFIX = "cp_mall_"; /** * 主入口 diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java index 75a5f17..5271fe9 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java @@ -26,7 +26,8 @@ public class PlaceOrderBo implements Serializable { /** * 主键 */ - @ApiModelProperty("主键") + @NotBlank(message = "主键不能为空") + @ApiModelProperty(value = "主键",required = true) private String id; /** diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartBo.java new file mode 100644 index 0000000..00c10b4 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartBo.java @@ -0,0 +1,57 @@ +package com.cpop.mall.business.bo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author DB + * @createTime 2023/11/06 14:12 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城购物车新增对象") +public class ShoppingCartBo implements Serializable { + + /** + * 商品记录id + */ + @NotBlank(message = "商品记录id不能为空") + @ApiModelProperty(value = "商品记录id",required = true) + private String productRecordId; + + /** + * 校区id + */ + @NotBlank(message = "校区id不能为空") + @ApiModelProperty(value = "校区id",required = true) + private String storeId; + + /** + * 金额 + */ + @NotNull(message = "金额不能为空") + @ApiModelProperty(value = "金额",required = true) + private BigDecimal amount; + + /** + * 积分 + */ + @NotNull(message = "积分不能为空") + @ApiModelProperty(value = "积分",required = true) + private Integer point; + + /** + * 数量 + */ + @NotNull(message = "数量不能为空") + @ApiModelProperty(value = "数量",required = true) + private Integer number; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartPageBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartPageBo.java new file mode 100644 index 0000000..2fc7083 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/ShoppingCartPageBo.java @@ -0,0 +1,25 @@ +package com.cpop.mall.business.bo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author DB + * @createTime 2023/11/06 13:52 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城购物车查询对象") +public class ShoppingCartPageBo implements Serializable { + + /** + * 商品名 + */ + @ApiModelProperty("商品名") + private String productName; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java index 862de55..a33566e 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java @@ -126,12 +126,24 @@ public class MiniOrderController { * @param orderId 订单id * @return: com.cpop.core.base.R> */ - @GetMapping("/rePayOrder/{orderId}") + @Deprecated + @PutMapping("/rePayOrder/{orderId}") @ApiOperation("小程序-重新支付订单") public R rePayOrder(@PathVariable @ApiParam(value = "订单id", required = true) String orderId) { return R.ok(orderService.rePayOrder(orderId)); } - + /** + * @descriptions 小程序-获取订单详情 + * @author DB + * @date 2023/11/06 14:25 + * @param orderId 订单id + * @return: com.cpop.core.base.R + */ + @GetMapping("/getOrderInfo/{orderId}") + @ApiOperation("小程序-获取订单详情") + public R getOrderInfo(@PathVariable @ApiParam(value = "订单id", required = true) String orderId) { + return R.ok(orderService.getOrderInfo(orderId)); + } } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java index 11c99af..4548a40 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java @@ -5,10 +5,7 @@ import com.cpop.core.base.R; import com.cpop.core.utils.SpringUtils; import com.cpop.mall.business.bo.ProductPageBo; import com.cpop.mall.business.service.ProductService; -import com.cpop.mall.business.vo.MiniProductPageVo; -import com.cpop.mall.business.vo.ProductEvaluateVo; -import com.cpop.mall.business.vo.ProductPageVo; -import com.cpop.mall.business.vo.StoreListVo; +import com.cpop.mall.business.vo.*; import com.cpop.system.business.entity.Store; import com.cpop.system.business.service.StoreService; import com.mybatisflex.core.paginate.Page; @@ -91,4 +88,18 @@ public class MiniProductController { return R.ok(list); } + /** + * @descriptions 获取商品详情 + * @author DB + * @date 2023/11/06 11:55 + * @param id 商品id + * @return: com.cpop.core.base.R + */ + @GetMapping("/getProductInfo/{id}") + @ApiOperation("获取商品详情") + public R getProductInfo(@PathVariable("id") @ApiParam(value = "商品id", required = true) String id) { + ProductInfoVo info = productService.getProductInfo(id); + return R.ok(info); + } + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniShoppingCartController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniShoppingCartController.java new file mode 100644 index 0000000..15d4c4d --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniShoppingCartController.java @@ -0,0 +1,78 @@ +package com.cpop.mall.business.controller.mini; + +import com.cpop.core.base.R; +import com.cpop.mall.business.bo.AdvanceOrderBo; +import com.cpop.mall.business.bo.ProductPageBo; +import com.cpop.mall.business.bo.ShoppingCartBo; +import com.cpop.mall.business.bo.ShoppingCartPageBo; +import com.cpop.mall.business.vo.MiniProductPageVo; +import com.cpop.mall.business.vo.MiniShoppingCartPageVo; +import com.mybatisflex.core.paginate.Page; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import com.cpop.mall.business.entity.ShoppingCart; +import com.cpop.mall.business.service.ShoppingCartService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + * 商城购物车表 控制层。 + * + * @author DB + * @since 2023-11-06 + */ +@RestController +@Api(tags = "小程序-商城购物车接口") +@RequestMapping("/mini/shoppingCart") +public class MiniShoppingCartController { + + @Autowired + private ShoppingCartService shoppingCartService; + + /** + * @descriptions 分页查询小程序-商城-购物车分页 + * @author DB + * @date 2023/11/06 14:10 + * @param bo 请求参数 + * @return: com.cpop.core.base.R> + */ + @GetMapping("/getMiniShoppingCartPage") + @ApiOperation("分页查询小程序-商城-购物车分页") + public R> getMiniShoppingCartPage(@ApiParam("分页参数") ShoppingCartPageBo bo) { + Page page = shoppingCartService.getMiniShoppingCartPage(bo); + return R.ok(page); + } + + /** + * @descriptions 小程序-商城-购物车添加商品 + * @author DB + * @date 2023/11/06 14:14 + * @param bo 请求参数 + * @return: com.cpop.core.base.R + */ + @PostMapping("/insertShoppingCart") + @ApiOperation("小程序-商城-购物车添加商品") + public R insertShoppingCart(@RequestBody @Validated @ApiParam("商城-购物车新增参数") ShoppingCartBo bo) { + shoppingCartService.insertShoppingCart(bo); + return R.ok(); + } + + /** + * @descriptions 小程序-商城-购物车删除商 + * @author DB + * @date 2023/11/06 14:14 + * @param ids 主键 + * @return: com.cpop.core.base.R + */ + @DeleteMapping("/removeShoppingCart") + @ApiOperation("小程序-商城-购物车删除商品") + public R removeShoppingCart(@RequestParam("ids") @ApiParam("商城-购物车新增参数") String[] ids) { + shoppingCartService.removeByIds(Arrays.asList(ids)); + return R.ok(); + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/ShoppingCart.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/ShoppingCart.java new file mode 100644 index 0000000..7c653d8 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/ShoppingCart.java @@ -0,0 +1,68 @@ +package com.cpop.mall.business.entity; + +import com.cpop.core.base.entity.BaseEntity; +import com.cpop.core.base.entity.BaseInsertListener; +import com.cpop.core.base.entity.BaseUpdateListener; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * 商城购物车表 实体类。 + * + * @author DB + * @since 2023-11-06 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@Table(value = "cp_mall_shopping_cart", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false) +public class ShoppingCart extends BaseEntity implements Serializable { + + /** + * 主键 + */ + @Id + private String id; + + /** + * 用户id + */ + private String userId; + + /** + * 商品记录id + */ + private String productRecordId; + + /** + * 店铺/校区id + */ + private byte[] storeId; + + /** + * 金额 + */ + private BigDecimal amount; + + /** + * 积分 + */ + private Integer point; + + /** + * 数量 + */ + private Integer number; + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/ShoppingCartMapper.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/ShoppingCartMapper.java new file mode 100644 index 0000000..3f28993 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/ShoppingCartMapper.java @@ -0,0 +1,14 @@ +package com.cpop.mall.business.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cpop.mall.business.entity.ShoppingCart; + +/** + * 商城购物车表 映射层。 + * + * @author DB + * @since 2023-11-06 + */ +public interface ShoppingCartMapper extends BaseMapper { + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java index 44ebc7b..fda5a0b 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java @@ -95,4 +95,12 @@ public interface OrderService extends IService { */ Object rePayOrder(String orderId); + /** + * @descriptions 小程序-获取订单详情 + * @author DB + * @date 2023/11/06 14:26 + * @param orderId 订单id + * @return: com.cpop.mall.business.vo.OrderInfoVo + */ + OrderInfoVo getOrderInfo(String orderId); } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ProductService.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ProductService.java index 335339b..1267466 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ProductService.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ProductService.java @@ -97,4 +97,12 @@ public interface ProductService extends IService { */ Page getOrderEvaluatePage(String productId); + /** + * @descriptions 获取商品详情 + * @author DB + * @date 2023/11/06 11:56 + * @param id 商品id + * @return: com.cpop.mall.business.vo.ProductInfoVo + */ + ProductInfoVo getProductInfo(String id); } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ShoppingCartService.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ShoppingCartService.java new file mode 100644 index 0000000..8d143a3 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/ShoppingCartService.java @@ -0,0 +1,35 @@ +package com.cpop.mall.business.service; + +import com.cpop.mall.business.bo.ShoppingCartBo; +import com.cpop.mall.business.bo.ShoppingCartPageBo; +import com.cpop.mall.business.vo.MiniShoppingCartPageVo; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.service.IService; +import com.cpop.mall.business.entity.ShoppingCart; + +/** + * 商城购物车表 服务层。 + * + * @author DB + * @since 2023-11-06 + */ +public interface ShoppingCartService extends IService { + + /** + * @descriptions 分页查询小程序-商城-购物车分页 + * @author DB + * @date 2023/11/06 14:02 + * @param bo 请求参数 + * @return: com.mybatisflex.core.paginate.Page + */ + Page getMiniShoppingCartPage(ShoppingCartPageBo bo); + + /** + * @descriptions 小程序-商城-购物车添加商品 + * @author DB + * @date 2023/11/06 14:17 + * @param bo 请求参数 + * @return: void + */ + void insertShoppingCart(ShoppingCartBo bo); +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderServiceImpl.java index bff6213..7ac81e7 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderServiceImpl.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderServiceImpl.java @@ -21,9 +21,11 @@ import com.cpop.mall.business.service.*; import com.cpop.mall.business.task.OrderOverTimeUnPayTask; import com.cpop.mall.business.task.ProductRecordSyncStockTask; import com.cpop.mall.business.task.WxPayAsyncTask; +import com.cpop.mall.business.vo.OrderDetailVo; import com.cpop.mall.business.vo.OrderInfoVo; import com.cpop.mall.business.vo.OrderPageVo; import com.cpop.mall.framework.constant.MallRedisConstant; +import com.cpop.mall.framework.enums.BuyRestrictEnums; import com.cpop.mall.framework.enums.QuartzEnums; import com.cpop.mall.framework.handler.WxPayHandler; import com.cpop.system.business.entity.Brand; @@ -54,6 +56,8 @@ import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_ import static com.cpop.mall.business.entity.table.ProductTableDef.PRODUCT; import static com.cpop.system.business.entity.table.ProfitSharingTableDef.PROFIT_SHARING; import static com.cpop.system.business.entity.table.StoreTableDef.STORE; +import static com.mybatisflex.core.query.QueryMethods.field; +import static com.mybatisflex.core.query.QueryMethods.select; /** @@ -152,7 +156,6 @@ public class OrderServiceImpl extends ServiceImpl implements try { Order order = BeanUtils.mapToClass(bo, Order.class); List orderDetails = BeanUtils.mapToList(bo.getOrderDetailList(), OrderDetail.class); - recordNumIsEnough= recordNumIsEnough(orderDetails); //规格记录ids Set recordIds = orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet()); //获取涉及到的商品 @@ -163,6 +166,10 @@ public class OrderServiceImpl extends ServiceImpl implements .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.PRODUCT_ID.eq(PRODUCT.ID)) .where(PRODUCT_RECORD.ID.in(recordIds)) .list(); + //检查库存 + recordNumIsEnough= recordNumIsEnough(orderDetails); + //购买限制 + buyRestrict(productList, recordNumIsEnough); //设置待付款 order.setOrderStatus(0) .setPreviousStatus(0) @@ -213,6 +220,17 @@ public class OrderServiceImpl extends ServiceImpl implements } } + private void buyRestrict(List productList, Map recordNumIsEnough) { + //过滤出存在购买限制的商品 + List filterProduct = productList.stream().filter(item -> item.getBuyRestrict() != null).collect(Collectors.toList()); + //过滤之后不为空,存在购买限制 + if (!filterProduct.isEmpty()){ + filterProduct.forEach(item->{ + BuyRestrictEnums.getByCode(item.getBuyRestrict()).getBuyRestrictStrategy().buyRestrict(item, recordNumIsEnough); + }); + } + } + /** * @descriptions 商城-订单-下单 * @author DB @@ -551,4 +569,33 @@ public class OrderServiceImpl extends ServiceImpl implements } } + /** + * @descriptions 小程序-获取订单详情 + * @author DB + * @date 2023/11/06 14:26 + * @param orderId 订单id + * @return: com.cpop.mall.business.vo.OrderInfoVo + */ + @Override + public OrderInfoVo getOrderInfo(String orderId) { + OrderInfoVo orderInfoVo = this.mapper.selectOneWithRelationsByIdAs(orderId, OrderInfoVo.class); + //获取订单详情 + List orderDetailVos = SpringUtils.getBean(OrderDetailService.class).listAs(QueryWrapper.create() + .select(PRODUCT.PRODUCT_NAME, PRODUCT.PIC_URL, PRODUCT.PIC_DETAIL_URL) + //订单详情 + .select(ORDER_DETAIL.ORDER_ID, ORDER_DETAIL.PRODUCT_RECORD_ID, ORDER_DETAIL.AMOUNT, ORDER_DETAIL.POINT, ORDER_DETAIL.STORE_ID) + //规格 + .select(PRODUCT_RECORD.RECORD_NAMES) + //校区 + .select(STORE.STORE_NAME) + .from(ORDER_DETAIL) + .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.ID.eq(ORDER_DETAIL.PRODUCT_RECORD_ID)) + .leftJoin(PRODUCT).on(PRODUCT.ID.eq(PRODUCT_RECORD.PRODUCT_ID)) + .leftJoin(STORE).on(STORE.ID.eq(ORDER_DETAIL.STORE_ID)) + .where(ORDER_DETAIL.ORDER_ID.eq(orderId)), + OrderDetailVo.class); + orderInfoVo.setDetailList(orderDetailVos); + return orderInfoVo; + } + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java index 5fd05bb..8df2307 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java @@ -380,4 +380,16 @@ public class ProductServiceImpl extends ServiceImpl impl .where(PRODUCT.ID.eq(productId)), ProductEvaluateVo.class); } + + /** + * @descriptions 获取商品详情 + * @author DB + * @date 2023/11/06 11:56 + * @param id 商品id + * @return: com.cpop.mall.business.vo.ProductInfoVo + */ + @Override + public ProductInfoVo getProductInfo(String id) { + return this.mapper.selectOneWithRelationsByIdAs(id, ProductInfoVo.class); + } } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ShoppingCartServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ShoppingCartServiceImpl.java new file mode 100644 index 0000000..7a4c418 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ShoppingCartServiceImpl.java @@ -0,0 +1,81 @@ +package com.cpop.mall.business.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.common.utils.StringUtils; +import com.cpop.common.utils.bean.BeanUtils; +import com.cpop.core.base.entity.PageDomain; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.sql.SqlUtils; +import com.cpop.mall.business.bo.ShoppingCartBo; +import com.cpop.mall.business.bo.ShoppingCartPageBo; +import com.cpop.mall.business.vo.MiniShoppingCartPageVo; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.cpop.mall.business.entity.ShoppingCart; +import com.cpop.mall.business.mapper.ShoppingCartMapper; +import com.cpop.mall.business.service.ShoppingCartService; +import org.springframework.stereotype.Service; + +import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD; +import static com.cpop.mall.business.entity.table.ProductTableDef.PRODUCT; +import static com.cpop.mall.business.entity.table.ShoppingCartTableDef.SHOPPING_CART; +import static com.cpop.system.business.entity.table.StoreTableDef.STORE; + +/** + * 商城购物车表 服务层实现。 + * + * @author DB + * @since 2023-11-06 + */ +@Service("shoppingCartService") +public class ShoppingCartServiceImpl extends ServiceImpl implements ShoppingCartService { + + /** + * @descriptions 分页查询小程序-商城-购物车分页 + * @author DB + * @date 2023/11/06 14:02 + * @param bo 请求参数 + * @return: com.mybatisflex.core.paginate.Page + */ + @Override + public Page getMiniShoppingCartPage(ShoppingCartPageBo bo) { + //获取当前用户信息 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); + QueryWrapper queryWrapper = QueryWrapper.create(); + if (StringUtils.isNotBlank(bo.getProductName())) { + queryWrapper.and(PRODUCT.PRODUCT_NAME.like(bo.getProductName())); + } + return this.mapper.paginateAs(pageDomain.getPageNum(), pageDomain.getPageSize(), + queryWrapper.select(SHOPPING_CART.ALL_COLUMNS) + //记录 + .select(PRODUCT_RECORD.RECORD_NAMES) + //商品 + .select(PRODUCT.PRODUCT_NAME) + //校区 + .select(STORE.STORE_NAME) + .from(SHOPPING_CART) + .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.ID.eq(SHOPPING_CART.PRODUCT_RECORD_ID)) + .leftJoin(PRODUCT).on(PRODUCT.ID.eq(PRODUCT_RECORD.PRODUCT_ID)) + .leftJoin(STORE).on(STORE.ID.eq(SHOPPING_CART.STORE_ID)) + .where(SHOPPING_CART.USER_ID.eq(loginUserInfo.getString("userId"))), + MiniShoppingCartPageVo.class); + } + + /** + * @descriptions 小程序-商城-购物车添加商品 + * @author DB + * @date 2023/11/06 14:17 + * @param bo 请求参数 + * @return: void + */ + @Override + public void insertShoppingCart(ShoppingCartBo bo) { + //获取当前用户信息 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + ShoppingCart shoppingCart = BeanUtils.mapToClass(bo, ShoppingCart.class); + shoppingCart.setUserId(loginUserInfo.getString("userId")); + this.save(shoppingCart); + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/MiniShoppingCartPageVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/MiniShoppingCartPageVo.java new file mode 100644 index 0000000..e113a6d --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/MiniShoppingCartPageVo.java @@ -0,0 +1,91 @@ +package com.cpop.mall.business.vo; + +import com.cpop.core.annontation.StringArrayConvert; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author DB + * @createTime 2023/11/06 13:53 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "小程序-商城-购物车分页返回对象") +public class MiniShoppingCartPageVo implements Serializable { + + /** + * 主键 + */ + @ApiModelProperty("主键") + private String id; + + /** + * 用户id + */ + @ApiModelProperty("用户id") + private String userId; + + /** + * 商品名 + */ + @ApiModelProperty("商品名") + private String productName; + + /** + * 规格名 + */ + @StringArrayConvert + @ApiModelProperty("规格名") + private String recordNames; + + /** + * 商品记录id + */ + @ApiModelProperty("商品记录id") + private String productRecordId; + + /** + * 店铺/校区id + */ + @ApiModelProperty("店铺/校区id") + private String storeId; + + /** + * 店铺/校区名 + */ + @ApiModelProperty("店铺/校区名") + private String storeName; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; + + /** + * 积分 + */ + @ApiModelProperty("积分") + private Integer point; + + /** + * 数量 + */ + @ApiModelProperty("数量") + private Integer number; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8") + @ApiModelProperty("创建时间") + private LocalDateTime createTime; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java index 1230b6c..23c304b 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java @@ -1,6 +1,7 @@ package com.cpop.mall.business.vo; import com.fasterxml.jackson.annotation.JsonFormat; +import com.mybatisflex.annotation.RelationOneToMany; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductInfoVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductInfoVo.java new file mode 100644 index 0000000..54eec84 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductInfoVo.java @@ -0,0 +1,111 @@ +package com.cpop.mall.business.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.mybatisflex.annotation.RelationOneToMany; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author DB + * @createTime 2023/11/06 11:55 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城商品详情返回对象") +public class ProductInfoVo implements Serializable { + + /** + * 主键 + */ + @ApiModelProperty("主键") + private String id; + + /** + * 商品名 + */ + @ApiModelProperty("商品名") + private String productName; + + /** + * 产品类型(0:课卡;1:周边;2:优惠卷:3:其他) + */ + @ApiModelProperty("产品类型(0:课卡;1:周边;2:优惠卷:3:其他)") + private Integer productType; + + /** + * 商店(校区)集合 + */ + @ApiModelProperty("商店(校区)集合") + private String storeIds; + + /** + * 描述 + */ + @ApiModelProperty("描述") + private String description; + + /** + * 商品图地址 + */ + @ApiModelProperty("商品图地址") + private String picUrl; + + /** + * 商品详情图地址 + */ + @ApiModelProperty("商品详情图地址") + private String picDetailUrl; + + /** + * 购买限制(0:会员限制;1:新客限定;2:用户限购) + */ + @ApiModelProperty("购买限制(0:会员限制;1:新客限定;2:用户限购)") + private Integer buyRestrict; + + /** + * 最高价 + */ + @ApiModelProperty("最高价") + private BigDecimal maxPrice; + + /** + * 最低价 + */ + @ApiModelProperty("最低价") + private BigDecimal minPrice; + + /** + * 支付方式(微信支付:0;积分支付:1) + */ + @ApiModelProperty("支付方式(微信支付:0;积分支付:1)") + private Integer payType; + + /** + * 产品规格 + */ + @RelationOneToMany(selfField = "id", targetField = "productId",targetTable = "cp_mall_product_specification") + @ApiModelProperty("产品规格") + private List productSpecificationVos; + + /** + * 产品规格记录 + */ + @RelationOneToMany(selfField = "id", targetField = "productId",targetTable = "cp_mall_product_record") + @ApiModelProperty("产品规格记录") + private List productRecordVos; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8") + @ApiModelProperty("创建时间") + private LocalDateTime createTime; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/BuyRestrictEnums.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/BuyRestrictEnums.java new file mode 100644 index 0000000..d5a4ac4 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/BuyRestrictEnums.java @@ -0,0 +1,75 @@ +package com.cpop.mall.framework.enums; + +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.framework.strategy.buyRestrict.BuyRestrictStrategy; +import com.cpop.mall.framework.strategy.buyRestrict.MemberRestrictStrategy; +import com.cpop.mall.framework.strategy.buyRestrict.NewCustomerRestrictStrategy; +import com.cpop.mall.framework.strategy.buyRestrict.UserRestrictStrategy; +import lombok.Getter; + +import javax.swing.*; +import java.util.HashMap; +import java.util.Map; + +/** + * @author DB + * @createTime 2023/11/06 15:21 + * @description 购买限制枚举 + */ +@Getter +public enum BuyRestrictEnums { + /** + * 会员限制 + */ + MEMBER_RESTRICT(0, "会员限制", SpringUtils.getBean(MemberRestrictStrategy.class)), + /** + * 新客限定 + */ + NEW_CUSTOMER_RESTRICT(1, "新客限定", SpringUtils.getBean(NewCustomerRestrictStrategy.class)), + /** + * 用户限购 + */ + USER_RESTRICT(2, "用户限购", SpringUtils.getBean(UserRestrictStrategy.class)) + ; + + private Integer code; + + private String name; + + private BuyRestrictStrategy buyRestrictStrategy; + + BuyRestrictEnums(Integer code, String name, BuyRestrictStrategy buyRestrictStrategy) { + this.code = code; + this.name = name; + this.buyRestrictStrategy = buyRestrictStrategy; + } + + public void setCode(Integer code) { + this.code = code; + } + + public void setName(String name) { + this.name = name; + } + + /** + * 放入map中,通过键取值 + */ + private static Map buyRestrictMap = new HashMap<>(); + + static { + for (BuyRestrictEnums value : BuyRestrictEnums.values()) { + buyRestrictMap.put(value.getCode(), value); + } + } + + /** + * 根据code获取枚举 + * @param code + * @return + */ + public static BuyRestrictEnums getByCode(Integer code) { + return buyRestrictMap.get(code); + } + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/BuyRestrictStrategy.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/BuyRestrictStrategy.java new file mode 100644 index 0000000..ed267d0 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/BuyRestrictStrategy.java @@ -0,0 +1,19 @@ +package com.cpop.mall.framework.strategy.buyRestrict; + +import com.cpop.mall.business.entity.Product; + +import java.util.Map; + +/** + * 购买策略接口 + */ +public interface BuyRestrictStrategy { + + /** + * @descriptions 购买限制 + * @author DB + * @date 2023/11/06 15:21 + * @return: void + */ + void buyRestrict(Product product, Map recordNumIsEnough); +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/MemberRestrictStrategy.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/MemberRestrictStrategy.java new file mode 100644 index 0000000..9bac773 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/MemberRestrictStrategy.java @@ -0,0 +1,61 @@ +package com.cpop.mall.framework.strategy.buyRestrict; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.jambox.business.entity.BrandExtend; +import com.cpop.jambox.business.service.BrandExtendService; +import com.cpop.mall.business.entity.Product; +import com.mybatisflex.core.datasource.DataSourceKey; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.row.Db; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.util.Map; + +import static com.cpop.jambox.business.entity.table.BrandExtendTableDef.BRAND_EXTEND; + +/** + * @author DB + * @createTime 2023/11/06 15:26 + * @description + */ +@Component +public class MemberRestrictStrategy implements BuyRestrictStrategy{ + + /** + * @descriptions 会员购买策略 + * @author DB + * @date 2023/11/06 15:47 + * @param product 商品 + * @return: void + */ + @Override + public void buyRestrict(Product product, Map recordNumIsEnough) { + // 获取当前用户信息 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + //获取品牌信息 + BrandExtend brandExtend = SpringUtils.getBean(BrandExtendService.class).queryChain() + .where(BRAND_EXTEND.BRAND_ID.eq(loginUserInfo.getString("brandId"))) + .one(); + //查询当前用户是否是会员 + DataSourceKey.use("jambox"); + long count = Db.selectCountByQuery("j_membership", QueryWrapper.create() + .select() + .leftJoin("t_brand_info").on("t_brand_info.brand_id = j_membership.brand_id") + //手机号 + .where("j_membership.phone = ?", loginUserInfo.getString("phoneNumber")) + //品牌id + .and("t_brand_info.brand_id = ?", brandExtend.getBrandCloudId()) + //会员时间未过期 + .and("j_membership.end_time >= ?", LocalDate.now()) + .and("j_membership.deleted = 1")); + DataSourceKey.clear(); + //没有会员 + if (count == 0) { + throw new ServiceException("你尚未成为会员,无法购买商品:" + product.getProductName()); + } + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/NewCustomerRestrictStrategy.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/NewCustomerRestrictStrategy.java new file mode 100644 index 0000000..6b38831 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/NewCustomerRestrictStrategy.java @@ -0,0 +1,45 @@ +package com.cpop.mall.framework.strategy.buyRestrict; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.business.entity.Product; +import com.cpop.mall.business.service.OrderService; +import com.mybatisflex.core.logicdelete.LogicDeleteManager; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static com.cpop.mall.business.entity.table.OrderTableDef.ORDER; + + +/** + * @author DB + * @createTime 2023/11/06 16:16 + * @description 新客限定策略 + */ +@Component +public class NewCustomerRestrictStrategy implements BuyRestrictStrategy{ + + /** + * 购买限制 + * @param product 产品 + */ + @Override + public void buyRestrict(Product product, Map recordNumIsEnough) { + //查询当前用户是否有购买记录 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + OrderService orderService = SpringUtils.getBean(OrderService.class); + //跳过逻辑删除 + LogicDeleteManager.execWithoutLogicDelete(() -> { + long count = orderService.queryChain() + .where(ORDER.PAY_USER_ID.eq(loginUserInfo.getString("userId"))) + .count(); + if (count > 0) { + //存在过购买记录 + throw new ServiceException("您已不是新客,无法购买商品" + product.getProductName()); + } + }); + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/UserRestrictStrategy.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/UserRestrictStrategy.java new file mode 100644 index 0000000..263f8d1 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/strategy/buyRestrict/UserRestrictStrategy.java @@ -0,0 +1,66 @@ +package com.cpop.mall.framework.strategy.buyRestrict; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.business.entity.Product; +import com.cpop.mall.business.entity.ProductRecord; +import com.cpop.mall.business.service.OrderDetailService; +import com.cpop.mall.business.service.ProductRecordService; +import com.mybatisflex.core.logicdelete.LogicDeleteManager; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.cpop.mall.business.entity.table.OrderDetailTableDef.ORDER_DETAIL; +import static com.cpop.mall.business.entity.table.OrderTableDef.ORDER; +import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD; +import static com.cpop.mall.business.entity.table.ProductTableDef.PRODUCT; + +/** + * @author DB + * @createTime 2023/11/06 16:42 + * @description 用户限购 + */ +@Component +public class UserRestrictStrategy implements BuyRestrictStrategy{ + + @Override + public void buyRestrict(Product product, Map recordNumIsEnough) { + //查询用户已购买的数量 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + OrderDetailService orderDetailService = SpringUtils.getBean(OrderDetailService.class); + ProductRecordService productRecordService = SpringUtils.getBean(ProductRecordService.class); + //产品记录 + List productRecordList = productRecordService.queryChain().where(PRODUCT_RECORD.PRODUCT_ID.eq(product.getId())).list(); + Set recordSet = productRecordList.stream().map(ProductRecord::getId).collect(Collectors.toSet()); + //跳过逻辑删除 + LogicDeleteManager.execWithoutLogicDelete(() -> { + //已存在订单数 + long count = orderDetailService.queryChain() + .leftJoin(ORDER).on(ORDER.ID.eq(ORDER_DETAIL.ORDER_ID)) + .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.ID.eq(ORDER_DETAIL.PRODUCT_RECORD_ID)) + .leftJoin(PRODUCT).on(PRODUCT.ID.eq(PRODUCT_RECORD.PRODUCT_ID)) + .where(ORDER.PAY_USER_ID.eq(loginUserInfo.getString("userId"))) + .and(PRODUCT.ID.eq(product.getId())) + .count(); + //产品购买数量 + AtomicInteger num = new AtomicInteger(); + recordNumIsEnough.forEach((key, value) -> { + if (recordSet.contains(key)) { + num.addAndGet(value); + } + }); + if (product.getLimitNum() - count > num.get()) { + //存在过购买记录 + throw new ServiceException("您购买的商品已超出限制,无法购买商品" + product.getProductName()); + } + }); + + } +} diff --git a/Cpop-Mall/src/main/resources/mapper/ShoppingCartMapper.xml b/Cpop-Mall/src/main/resources/mapper/ShoppingCartMapper.xml new file mode 100644 index 0000000..93899d8 --- /dev/null +++ b/Cpop-Mall/src/main/resources/mapper/ShoppingCartMapper.xml @@ -0,0 +1,7 @@ + + + + +