mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
refactor:商品重构优化
This commit is contained in:
commit
7dd4903607
@ -1,6 +1,6 @@
|
||||
package com.youlai.mall.oms.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
@ -9,26 +9,33 @@ import lombok.Getter;
|
||||
* @email huawei_code@163.com
|
||||
* @date 2021/1/16
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public enum PayTypeEnum {
|
||||
public enum PayTypeEnum {
|
||||
|
||||
WEIXIN_JSAPI(1,"微信JSAPI支付"),
|
||||
ALIPAY(2,"支付宝支付"),
|
||||
BALANCE(3,"会员余额支付"),
|
||||
WEIXIN_APP(4,"微信APP支付");
|
||||
|
||||
PayTypeEnum(int code, String text) {
|
||||
this.code = code;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private Integer code;
|
||||
|
||||
@Getter
|
||||
private String text;
|
||||
|
||||
public static PayTypeEnum getByCode(Integer code){
|
||||
public static PayTypeEnum getByCode(Integer code) {
|
||||
PayTypeEnum payTypeEnum = null;
|
||||
|
||||
for (PayTypeEnum value : values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
payTypeEnum = value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return payTypeEnum;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
package com.youlai.mall.oms.pojo.dto;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 购物车商品传输层实体
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
@Builder
|
||||
@Data
|
||||
public class CartItemDTO implements Serializable {
|
||||
|
||||
|
||||
private Long skuId;
|
||||
|
||||
/**
|
||||
* 商品库存单元名称
|
||||
*/
|
||||
private String skuName;
|
||||
|
||||
/**
|
||||
* 商品库存单元编码
|
||||
*/
|
||||
private String skuSn;
|
||||
|
||||
/**
|
||||
* 商品库存单元图片
|
||||
*/
|
||||
private String picUrl;
|
||||
|
||||
private Integer count; // 商品数量
|
||||
|
||||
/**
|
||||
* 加入购物车价格,因会变动,不能作为订单计算因子,订单验价时需重新获取商品价格即可
|
||||
*/
|
||||
private Long price;
|
||||
|
||||
private Long coupon;
|
||||
|
||||
private Boolean checked;
|
||||
|
||||
/**
|
||||
* 商品库存数量,页面控制能选择最大数量
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String goodsName;
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package com.youlai.mall.oms.pojo.vo;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 购物车实体类
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
@Builder
|
||||
@Data
|
||||
public class CartVO implements Serializable {
|
||||
|
||||
private List<CartItem> items;
|
||||
|
||||
@Data
|
||||
public static class CartItem {
|
||||
|
||||
private Long skuId;
|
||||
|
||||
private String skuName; // 标题
|
||||
|
||||
private String skuCode;
|
||||
|
||||
private String pic;
|
||||
|
||||
private Integer count; // 商品数量
|
||||
|
||||
private Long price; // 加入购物车价格,因会变动,不能作为订单计算因子,订单验价时需重新获取商品价格即可
|
||||
|
||||
private Long coupon;
|
||||
|
||||
private Boolean checked;
|
||||
|
||||
private Integer stock;// 商品库存数量,页面控制能选择最大数量
|
||||
|
||||
private String spuName;
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package com.youlai.mall.oms;
|
||||
|
||||
|
||||
import com.youlai.mall.pms.api.SkuFeignClient;
|
||||
import com.youlai.mall.pms.api.GoodsFeignClient;
|
||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@ -12,7 +12,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients(basePackageClasses = { MemberFeignClient.class, SkuFeignClient.class})
|
||||
@EnableFeignClients(basePackageClasses = { MemberFeignClient.class, GoodsFeignClient.class})
|
||||
@EnableRabbit
|
||||
public class OmsApplication {
|
||||
|
||||
|
@ -17,10 +17,5 @@ public interface OmsConstants {
|
||||
*/
|
||||
String RELEASE_LOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
|
||||
|
||||
/**
|
||||
* 释放锁成功返回值
|
||||
*/
|
||||
Long RELEASE_LOCK_SUCCESS_RESULT = 1L;
|
||||
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ package com.youlai.mall.oms.controller.app;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.oms.pojo.vo.CartVO;
|
||||
import com.youlai.common.web.util.JwtUtils;
|
||||
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
||||
import com.youlai.mall.oms.service.ICartService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
@ -11,6 +12,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author huawei
|
||||
* @email huawei_code@163.com
|
||||
@ -30,8 +33,9 @@ public class CartController {
|
||||
@GetMapping
|
||||
@ApiOperationSupport(order = 1)
|
||||
public Result getCart() {
|
||||
CartVO cart = cartService.getCart();
|
||||
return Result.success(cart);
|
||||
Long memberId = JwtUtils.getUserId();
|
||||
List<CartItemDTO> result = cartService.listCartItemByMemberId(memberId);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除购物车")
|
||||
@ -54,7 +58,7 @@ public class CartController {
|
||||
@ApiOperation(value = "更新购物车商品")
|
||||
@PutMapping("/skuId/{skuId}")
|
||||
@ApiOperationSupport(order = 4)
|
||||
public Result updateCartItem(@PathVariable Long skuId,@RequestBody CartVO.CartItem cartItem) {
|
||||
public Result updateCartItem(@PathVariable Long skuId,@RequestBody CartItemDTO cartItem) {
|
||||
cartItem.setSkuId(skuId);
|
||||
boolean result = cartService.updateCartItem(cartItem);
|
||||
return Result.judge(result);
|
||||
|
@ -5,14 +5,17 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.web.util.JwtUtils;
|
||||
import com.youlai.mall.oms.enums.PayTypeEnum;
|
||||
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderConfirmDTO;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO;
|
||||
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
||||
import com.youlai.mall.oms.pojo.vo.OrderConfirmVO;
|
||||
import com.youlai.mall.oms.pojo.vo.OrderSubmitVO;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO;
|
||||
import com.youlai.mall.oms.service.IOrderService;
|
||||
import io.swagger.annotations.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -28,18 +31,13 @@ import javax.validation.Valid;
|
||||
@RestController
|
||||
@RequestMapping("/app-api/v1/orders")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class OrderController {
|
||||
|
||||
private IOrderService orderService;
|
||||
final IOrderService orderService;
|
||||
|
||||
@ApiOperation("订单列表")
|
||||
@GetMapping
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "page", defaultValue = "1", value = "页码", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", defaultValue = "10", value = "每页数量", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "status", value = "订单状态", paramType = "query", dataType = "Integer")
|
||||
})
|
||||
public Result list(
|
||||
@RequestParam(defaultValue = "1") Long page,
|
||||
@RequestParam(defaultValue = "10") Long limit,
|
||||
@ -53,7 +51,6 @@ public class OrderController {
|
||||
}
|
||||
|
||||
@ApiOperation("订单确认")
|
||||
@ApiImplicitParam(name = "orderConfirm", value = "确认订单信息", required = true, paramType = "body", dataType = "OrderConfirmDTO")
|
||||
@PostMapping("/_confirm")
|
||||
public Result<OrderConfirmVO> confirm(@RequestBody OrderConfirmDTO orderConfirm) {
|
||||
OrderConfirmVO result = orderService.confirm(orderConfirm);
|
||||
@ -61,7 +58,6 @@ public class OrderController {
|
||||
}
|
||||
|
||||
@ApiOperation("订单提交")
|
||||
@ApiImplicitParam(name = "orderSubmitDTO", value = "提交订单信息", required = true, paramType = "body", dataType = "orderSubmitDTO")
|
||||
@PostMapping("/_submit")
|
||||
public Result submit(@Valid @RequestBody OrderSubmitDTO orderSubmitDTO) {
|
||||
OrderSubmitVO result = orderService.submit(orderSubmitDTO);
|
||||
@ -76,6 +72,7 @@ public class OrderController {
|
||||
@ApiImplicitParam(name = "appId", value = "小程序appId", paramType = "query", dataType = "String")
|
||||
})
|
||||
public <T> Result<T> pay(@PathVariable Long orderId, Integer payType, String appId) {
|
||||
|
||||
PayTypeEnum payTypeEnum = PayTypeEnum.getByCode(payType);
|
||||
if (payTypeEnum == null) {
|
||||
return Result.failed("系统暂不支持该支付方式~");
|
||||
@ -85,7 +82,6 @@ public class OrderController {
|
||||
|
||||
@ApiOperation("订单删除")
|
||||
@PostMapping("/{orderId}")
|
||||
@ApiImplicitParam(name = "orderId", value = "订单ID", paramType = "path", dataType = "Long")
|
||||
public Result deleteOrder(@PathVariable Long orderId) {
|
||||
boolean result = orderService.deleteOrder(orderId);
|
||||
return Result.judge(result);
|
||||
|
@ -3,7 +3,7 @@ package com.youlai.mall.oms.listener;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.youlai.mall.oms.service.IOrderItemService;
|
||||
import com.youlai.mall.oms.service.IOrderService;
|
||||
import com.youlai.mall.pms.api.SkuFeignClient;
|
||||
import com.youlai.mall.pms.api.StockFeignClient;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
@ -24,7 +24,7 @@ public class OrderListener {
|
||||
|
||||
IOrderService orderService;
|
||||
IOrderItemService orderItemService;
|
||||
SkuFeignClient skuFeignService;
|
||||
StockFeignClient stockFeignClient;
|
||||
RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
@ -36,7 +36,7 @@ public class OrderListener {
|
||||
try {
|
||||
if (orderService.closeOrder(orderToken)) {
|
||||
log.info("=======================关闭订单成功,开始释放已锁定的库存=======================");
|
||||
skuFeignService.unlockStock(orderToken);
|
||||
stockFeignClient.unlockStock(orderToken);
|
||||
} else {
|
||||
log.info("=======================关单失败,订单状态已处理,手动确认消息处理完毕=======================");
|
||||
// basicAck(tag,multiple),multiple为true开启批量确认,小于tag值队列中未被消费的消息一次性确认
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.youlai.mall.oms.service;
|
||||
|
||||
import com.youlai.mall.oms.pojo.vo.CartVO;
|
||||
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -10,15 +10,14 @@ import java.util.List;
|
||||
public interface ICartService {
|
||||
|
||||
|
||||
CartVO getCart();
|
||||
|
||||
List<CartVO.CartItem> getCartItems(Long memberId);
|
||||
List<CartItemDTO> listCartItemByMemberId(Long memberId);
|
||||
|
||||
boolean deleteCart();
|
||||
|
||||
boolean addCartItem(Long skuId);
|
||||
|
||||
boolean updateCartItem(CartVO.CartItem cartItem);
|
||||
boolean updateCartItem(CartItemDTO cartItem);
|
||||
|
||||
boolean removeCartItem(Long skuId);
|
||||
|
||||
|
@ -2,10 +2,10 @@ package com.youlai.mall.oms.service.impl;
|
||||
|
||||
import com.youlai.common.web.util.JwtUtils;
|
||||
import com.youlai.mall.oms.constant.OmsConstants;
|
||||
import com.youlai.mall.oms.pojo.vo.CartVO;
|
||||
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
||||
import com.youlai.mall.oms.service.ICartService;
|
||||
import com.youlai.mall.pms.api.SkuFeignClient;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.api.GoodsFeignClient;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
@ -32,25 +32,12 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class CartServiceImpl implements ICartService {
|
||||
|
||||
private RedisTemplate redisTemplate;
|
||||
private SkuFeignClient skuFeignService;
|
||||
|
||||
/**
|
||||
* 获取用户购物车
|
||||
*/
|
||||
@Override
|
||||
public CartVO getCart() {
|
||||
CartVO cart = new CartVO();
|
||||
Long memberId= JwtUtils.getUserId();
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
List<CartVO.CartItem> cartItems = cartHashOperations.values();
|
||||
cart.setItems(cartItems);
|
||||
return cart;
|
||||
}
|
||||
private GoodsFeignClient skuFeignService;
|
||||
|
||||
@Override
|
||||
public List<CartVO.CartItem> getCartItems(Long memberId) {
|
||||
public List<CartItemDTO> listCartItemByMemberId(Long memberId) {
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
List<CartVO.CartItem> cartItems = cartHashOperations.values();
|
||||
List<CartItemDTO> cartItems = cartHashOperations.values();
|
||||
return cartItems;
|
||||
}
|
||||
|
||||
@ -73,28 +60,28 @@ public class CartServiceImpl implements ICartService {
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
String hKey = skuId + "";
|
||||
|
||||
CartVO.CartItem cartItem;
|
||||
CartItemDTO cartItem;
|
||||
// 购物车已存在该商品,更新商品数量
|
||||
if (cartHashOperations.get(hKey) != null) {
|
||||
cartItem = (CartVO.CartItem) cartHashOperations.get(hKey);
|
||||
cartItem = (CartItemDTO) cartHashOperations.get(hKey);
|
||||
cartItem.setCount(cartItem.getCount() + 1); // 点击一次“加入购物车”,数量+1
|
||||
cartItem.setChecked(true);
|
||||
cartHashOperations.put(hKey, cartItem);
|
||||
return true;
|
||||
}
|
||||
// 购物车不存在该商品,添加商品至购物车
|
||||
cartItem = new CartVO.CartItem();
|
||||
cartItem = new CartItemDTO();
|
||||
CompletableFuture<Void> cartItemCompletableFuture = CompletableFuture.runAsync(() -> {
|
||||
SkuDTO sku = skuFeignService.getSkuById(skuId).getData();
|
||||
if (sku != null) {
|
||||
cartItem.setSkuId(sku.getId());
|
||||
cartItem.setCount(1);
|
||||
cartItem.setPrice(sku.getPrice());
|
||||
cartItem.setPic(sku.getPic());
|
||||
cartItem.setPicUrl(sku.getPicUrl());
|
||||
cartItem.setSkuName(sku.getName());
|
||||
cartItem.setStock(sku.getStock());
|
||||
cartItem.setSkuCode(sku.getCode());
|
||||
cartItem.setSpuName(sku.getSpuName());
|
||||
cartItem.setSkuSn(sku.getSn());
|
||||
cartItem.setGoodsName(sku.getGoodsName());
|
||||
cartItem.setChecked(true);
|
||||
}
|
||||
});
|
||||
@ -107,12 +94,12 @@ public class CartServiceImpl implements ICartService {
|
||||
* 更新购物车总商品数量、选中状态
|
||||
*/
|
||||
@Override
|
||||
public boolean updateCartItem(CartVO.CartItem cartItem) {
|
||||
public boolean updateCartItem(CartItemDTO cartItem) {
|
||||
Long memberId= JwtUtils.getUserId();
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
String hKey = cartItem.getSkuId() + "";
|
||||
if (cartHashOperations.get(hKey) != null) {
|
||||
CartVO.CartItem cacheCartItem = (CartVO.CartItem) cartHashOperations.get(hKey);
|
||||
CartItemDTO cacheCartItem = (CartItemDTO) cartHashOperations.get(hKey);
|
||||
if(cartItem.getChecked()!=null){
|
||||
cacheCartItem.setChecked(cartItem.getChecked());
|
||||
}
|
||||
@ -145,7 +132,7 @@ public class CartServiceImpl implements ICartService {
|
||||
Long memberId= JwtUtils.getUserId();
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
for (Object value : cartHashOperations.values()) {
|
||||
CartVO.CartItem cartItem = (CartVO.CartItem) value;
|
||||
CartItemDTO cartItem = (CartItemDTO) value;
|
||||
cartItem.setChecked(checked);
|
||||
String hKey = cartItem.getSkuId() + "";
|
||||
cartHashOperations.put(hKey, cartItem);
|
||||
@ -163,7 +150,7 @@ public class CartServiceImpl implements ICartService {
|
||||
Long memberId= JwtUtils.getUserId();
|
||||
BoundHashOperations cartHashOperations = getCartHashOperations(memberId);
|
||||
for (Object value : cartHashOperations.values()) {
|
||||
CartVO.CartItem cartItem = (CartVO.CartItem) value;
|
||||
CartItemDTO cartItem = (CartItemDTO) value;
|
||||
if (cartItem.getChecked()) {
|
||||
cartHashOperations.delete(cartItem.getSkuId()+"");
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.youlai.mall.oms.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@ -31,24 +31,25 @@ import com.youlai.mall.oms.mapper.OrderMapper;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderConfirmDTO;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderItemDTO;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO;
|
||||
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
||||
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
||||
import com.youlai.mall.oms.pojo.entity.OmsOrderItem;
|
||||
import com.youlai.mall.oms.pojo.vo.CartVO;
|
||||
import com.youlai.mall.oms.pojo.vo.OrderConfirmVO;
|
||||
import com.youlai.mall.oms.pojo.vo.OrderSubmitVO;
|
||||
import com.youlai.mall.oms.service.ICartService;
|
||||
import com.youlai.mall.oms.service.IOrderItemService;
|
||||
import com.youlai.mall.oms.service.IOrderService;
|
||||
import com.youlai.mall.oms.tcc.service.SeataTccOrderService;
|
||||
import com.youlai.mall.pms.api.SkuFeignClient;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.api.GoodsFeignClient;
|
||||
import com.youlai.mall.pms.api.StockFeignClient;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.LockStockDTO;
|
||||
import com.youlai.mall.ums.api.MemberAddressFeignClient;
|
||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||
import com.youlai.mall.ums.pojo.entity.UmsAddress;
|
||||
import com.youlai.mall.ums.pojo.entity.UmsMember;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
@ -69,25 +70,25 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static com.youlai.mall.oms.constant.OmsConstants.*;
|
||||
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> implements IOrderService {
|
||||
|
||||
private final WxPayProperties wxPayProperties;
|
||||
private final ICartService cartService;
|
||||
private final SkuFeignClient skuFeignService;
|
||||
private final MemberAddressFeignClient addressFeignService;
|
||||
private final IOrderItemService orderItemService;
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
private final StringRedisTemplate redisTemplate;
|
||||
private final RedissonClient redissonClient;
|
||||
private final ThreadPoolExecutor threadPoolExecutor;
|
||||
private final MemberFeignClient memberFeignClient;
|
||||
|
||||
private final BusinessNoGenerator businessNoGenerator;
|
||||
private final SeataTccOrderService seataTccOrderService;
|
||||
private final WxPayService wxPayService;
|
||||
private final WxPayProperties wxPayProperties;
|
||||
private final ICartService cartService;
|
||||
private final MemberAddressFeignClient addressFeignService;
|
||||
private final IOrderItemService orderItemService;
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
private final StringRedisTemplate redisTemplate;
|
||||
private final ThreadPoolExecutor threadPoolExecutor;
|
||||
private final MemberFeignClient memberFeignClient;
|
||||
private final BusinessNoGenerator businessNoGenerator;
|
||||
private final GoodsFeignClient goodsFeignClient;
|
||||
private final StockFeignClient stockFeignClient;
|
||||
private final SeataTccOrderService seataTccOrderService;
|
||||
private final RedissonClient redissonClient;
|
||||
private final WxPayService wxPayService;
|
||||
|
||||
/**
|
||||
* 订单确认
|
||||
@ -105,25 +106,25 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
.skuId(orderConfirmDTO.getSkuId())
|
||||
.count(orderConfirmDTO.getCount())
|
||||
.build();
|
||||
SkuDTO sku = skuFeignService.getSkuById(orderConfirmDTO.getSkuId()).getData();
|
||||
SkuDTO sku = goodsFeignClient.getSkuById(orderConfirmDTO.getSkuId()).getData();
|
||||
orderItemDTO.setPrice(sku.getPrice());
|
||||
orderItemDTO.setPic(sku.getPic());
|
||||
orderItemDTO.setPic(sku.getPicUrl());
|
||||
orderItemDTO.setSkuName(sku.getName());
|
||||
orderItemDTO.setSkuCode(sku.getCode());
|
||||
orderItemDTO.setSpuName(sku.getSpuName());
|
||||
orderItemDTO.setSkuCode(sku.getSn());
|
||||
orderItemDTO.setSpuName(sku.getGoodsName());
|
||||
orderItems.add(orderItemDTO);
|
||||
} else { // 购物车中商品结算
|
||||
List<CartVO.CartItem> cartItems = cartService.getCartItems(memberId);
|
||||
List<CartItemDTO> cartItems = cartService.listCartItemByMemberId(memberId);
|
||||
List<OrderItemDTO> items = cartItems.stream()
|
||||
.filter(CartVO.CartItem::getChecked)
|
||||
.filter(CartItemDTO::getChecked)
|
||||
.map(cartItem -> OrderItemDTO.builder()
|
||||
.skuId(cartItem.getSkuId())
|
||||
.count(cartItem.getCount())
|
||||
.price(cartItem.getPrice())
|
||||
.skuName(cartItem.getSkuName())
|
||||
.skuCode(cartItem.getSkuCode())
|
||||
.spuName(cartItem.getSpuName())
|
||||
.pic(cartItem.getPic())
|
||||
.skuCode(cartItem.getSkuSn())
|
||||
.spuName(cartItem.getGoodsName())
|
||||
.pic(cartItem.getPicUrl())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
orderItems.addAll(items);
|
||||
@ -160,43 +161,36 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
// 订单重复提交校验
|
||||
String orderToken = submitDTO.getOrderToken();
|
||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA_SCRIPT, Long.class);
|
||||
Long result = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken);
|
||||
|
||||
if (!ObjectUtil.equals(result, RELEASE_LOCK_SUCCESS_RESULT)) {
|
||||
throw new BizException("订单不可重复提交");
|
||||
}
|
||||
Long execute = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken);
|
||||
Assert.isTrue(execute.equals(1l), "订单不可重复提交");
|
||||
|
||||
List<OrderItemDTO> orderItems = submitDTO.getOrderItems();
|
||||
if (CollectionUtil.isEmpty(orderItems)) {
|
||||
throw new BizException("订单没有商品,请选择商品后提交");
|
||||
}
|
||||
Assert.isTrue(CollectionUtil.isNotEmpty(orderItems), "订单商品为空");
|
||||
|
||||
// 订单验价
|
||||
Long currentTotalPrice = orderItems.stream().map(item -> {
|
||||
SkuDTO sku = skuFeignService.getSkuById(item.getSkuId()).getData();
|
||||
SkuDTO sku = goodsFeignClient.getSkuById(item.getSkuId()).getData();
|
||||
if (sku != null) {
|
||||
return sku.getPrice() * item.getCount();
|
||||
}
|
||||
return 0L;
|
||||
}).reduce(0L, Long::sum);
|
||||
|
||||
if (currentTotalPrice.compareTo(submitDTO.getTotalPrice()) != 0) {
|
||||
throw new BizException("页面已过期,请重新刷新页面再提交");
|
||||
}
|
||||
Assert.isTrue(currentTotalPrice.compareTo(submitDTO.getTotalPrice()) == 0, "当前页面已过期,请重新刷新页面再提交");
|
||||
|
||||
// 校验库存是否足够和锁库存
|
||||
List<SkuLockDTO> skuLockList = orderItems.stream()
|
||||
.map(item -> SkuLockDTO.builder().skuId(item.getSkuId())
|
||||
List<LockStockDTO> skuLockList = orderItems.stream()
|
||||
.map(item -> LockStockDTO.builder().skuId(item.getSkuId())
|
||||
.count(item.getCount())
|
||||
.orderToken(orderToken)
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Result<?> lockResult = skuFeignService.lockStock(skuLockList);
|
||||
Result<?> lockResult = stockFeignClient.lockStock(skuLockList);
|
||||
|
||||
|
||||
Assert.isTrue(Result.success().getCode().equals(lockResult.getCode()), "锁定商品库存失败:{}", lockResult.getMsg());
|
||||
|
||||
if (!Result.success().getCode().equals(lockResult.getCode())) {
|
||||
throw new BizException(Result.failed().getMsg());
|
||||
}
|
||||
// 创建订单(状态:待支付)
|
||||
OmsOrder order = new OmsOrder();
|
||||
order.setOrderSn(orderToken) // 把orderToken赋值给订单编号【!】
|
||||
@ -254,7 +248,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
|
||||
// 订单验价
|
||||
Long currentTotalPrice = orderItems.stream().map(item -> {
|
||||
SkuDTO sku = skuFeignService.getSkuById(item.getSkuId()).getData();
|
||||
SkuDTO sku = goodsFeignClient.getSkuById(item.getSkuId()).getData();
|
||||
if (sku != null) {
|
||||
return sku.getPrice() * item.getCount();
|
||||
}
|
||||
@ -266,14 +260,14 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
}
|
||||
|
||||
// 校验库存是否足够和锁库存
|
||||
List<SkuLockDTO> skuLockList = orderItems.stream()
|
||||
.map(item -> SkuLockDTO.builder().skuId(item.getSkuId())
|
||||
List<LockStockDTO> skuLockList = orderItems.stream()
|
||||
.map(item -> LockStockDTO.builder().skuId(item.getSkuId())
|
||||
.count(item.getCount())
|
||||
.orderToken(orderToken)
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Result<?> lockResult = skuFeignService.lockStock(skuLockList);
|
||||
Result<?> lockResult = stockFeignClient.lockStock(skuLockList);
|
||||
|
||||
if (!Result.success().getCode().equals(lockResult.getCode())) {
|
||||
throw new BizException(Result.failed().getMsg());
|
||||
@ -329,7 +323,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
}
|
||||
|
||||
// 扣减库存
|
||||
Result<?> deductStockResult = skuFeignService.deductStock(order.getOrderSn());
|
||||
Result<?> deductStockResult = stockFeignClient.deductStock(order.getOrderSn());
|
||||
|
||||
if (!Result.isSuccess(deductStockResult)) {
|
||||
throw new BizException("扣减商品库存失败");
|
||||
}
|
||||
@ -450,7 +445,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
boolean result = this.updateById(order);
|
||||
if (result) {
|
||||
// 释放被锁定的库存
|
||||
Result<?> unlockResult = skuFeignService.unlockStock(order.getOrderSn());
|
||||
Result<?> unlockResult = stockFeignClient.unlockStock(order.getOrderSn());
|
||||
if (!Result.isSuccess(unlockResult)) {
|
||||
throw new BizException(unlockResult.getMsg());
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.youlai.mall.pms.api;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
@FeignClient(value = "mall-pms",contextId = "goods")
|
||||
public interface GoodsFeignClient {
|
||||
|
||||
/**
|
||||
* 获取商品信息
|
||||
*/
|
||||
@GetMapping("/app-api/v1/stocks/{id}")
|
||||
Result<SkuDTO> getSkuById(@PathVariable Long id);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package com.youlai.mall.pms.api;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FeignClient(value = "mall-pms")
|
||||
public interface SkuFeignClient {
|
||||
|
||||
/**
|
||||
* 获取库存信息
|
||||
*/
|
||||
@GetMapping("/app-api/v1/skus/{id}")
|
||||
Result<SkuDTO> getSkuById(@PathVariable Long id);
|
||||
|
||||
/**
|
||||
* 锁定库存
|
||||
*/
|
||||
@PutMapping("/app-api/v1/skus/lock_stock")
|
||||
Result lockStock(@RequestBody List<SkuLockDTO> list);
|
||||
|
||||
/**
|
||||
* 解锁库存
|
||||
*/
|
||||
@PutMapping("/app-api/v1/skus/unlock_stock")
|
||||
Result<Boolean> unlockStock(@RequestParam String orderToken);
|
||||
|
||||
|
||||
@PutMapping("/app-api/v1/skus/deduct_stock")
|
||||
Result deductStock(@RequestParam String orderToken);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.youlai.mall.pms.api;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.app.LockStockDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
@FeignClient(value = "mall-pms",contextId = "stock")
|
||||
public interface StockFeignClient {
|
||||
|
||||
/**
|
||||
* 锁定库存
|
||||
*/
|
||||
@PutMapping("/app-api/v1/stocks/_lock")
|
||||
Result lockStock(@RequestBody List<LockStockDTO> list);
|
||||
|
||||
/**
|
||||
* 解锁库存
|
||||
*/
|
||||
@PutMapping("/app-api/v1/stocks/_unlock")
|
||||
Result<Boolean> unlockStock(@RequestParam String orderToken);
|
||||
|
||||
|
||||
/**
|
||||
* 扣减库存
|
||||
*/
|
||||
@PutMapping("/app-api/v1/stocks/_deduct")
|
||||
Result deductStock(@RequestParam String orderToken);
|
||||
|
||||
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.youlai.mall.pms.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SpuDTO {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long categoryId;
|
||||
private Long brandId;
|
||||
private Long originPrice;
|
||||
private Long price;
|
||||
private Integer sales;
|
||||
private String pic;
|
||||
private List<String> pics;
|
||||
private String unit;
|
||||
private String description;
|
||||
private String detail;
|
||||
private Integer status;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.youlai.mall.pms.pojo.dto.admin;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
@ApiModel("属性表单")
|
||||
public class AttributeFormDTO {
|
||||
|
||||
@ApiModelProperty("分类ID")
|
||||
@NotNull
|
||||
private Long categoryId;
|
||||
|
||||
|
||||
@ApiModelProperty("属性类型(1:规格;2:属性)")
|
||||
@NotNull
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty("属性集合")
|
||||
@NotEmpty
|
||||
private List<Attribute> attributes;
|
||||
|
||||
@Data
|
||||
public static class Attribute {
|
||||
|
||||
@ApiModelProperty("属性ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("属性名称")
|
||||
@NotBlank
|
||||
private String name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.youlai.mall.pms.pojo.dto.admin;
|
||||
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Data
|
||||
public class GoodsFormDTO {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long categoryId;
|
||||
private Long brandId;
|
||||
private Long originPrice;
|
||||
private Long price;
|
||||
private String picUrl;
|
||||
private List<String> subPicUrls;
|
||||
private String description;
|
||||
private String detail;
|
||||
|
||||
private List<AttributeValue> attrList;
|
||||
|
||||
private List<AttributeValue> specList;
|
||||
|
||||
private List<PmsSku> skuList;
|
||||
|
||||
@Data
|
||||
public static class AttributeValue{
|
||||
|
||||
private Long attributeId;
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String value;
|
||||
|
||||
private String picUrl;
|
||||
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.youlai.mall.pms.pojo.dto.admin;
|
||||
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuSpecValue;
|
||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ProductFormDTO {
|
||||
|
||||
private SpuDTO spu;
|
||||
|
||||
private List<PmsSpuAttributeValue> attrs;
|
||||
|
||||
private List<PmsSpuSpecValue> specs;
|
||||
|
||||
private List<PmsSku> skus;
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.youlai.mall.pms.pojo.dto;
|
||||
package com.youlai.mall.pms.pojo.dto.app;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SkuLockDTO {
|
||||
public class LockStockDTO {
|
||||
|
||||
private Long skuId;
|
||||
|
@ -2,8 +2,6 @@ package com.youlai.mall.pms.pojo.dto.app;
|
||||
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -15,12 +13,29 @@ import java.util.List;
|
||||
@NoArgsConstructor
|
||||
public class ProductFormDTO {
|
||||
|
||||
private SpuDTO spu;
|
||||
private SpuInfo spuInfo;
|
||||
|
||||
private List<PmsSpuAttributeValue> attrs;
|
||||
private List<PmsSpuAttributeValue> attrValueList;
|
||||
|
||||
private List<PmsSpec> specs;
|
||||
|
||||
private List<PmsSku> skus;
|
||||
private List<PmsSku> skuList;
|
||||
|
||||
|
||||
@Data
|
||||
public static class SpuInfo {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long categoryId;
|
||||
private Long brandId;
|
||||
private Long originPrice;
|
||||
private Long price;
|
||||
private Integer sales;
|
||||
private String picUrl;
|
||||
private List<String> album;
|
||||
private String unit;
|
||||
private String description;
|
||||
private String detail;
|
||||
private Integer status;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.youlai.mall.pms.pojo.dto;
|
||||
package com.youlai.mall.pms.pojo.dto.app;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -12,12 +12,12 @@ import lombok.Data;
|
||||
public class SkuDTO {
|
||||
|
||||
private Long id;
|
||||
private String code;
|
||||
private String sn;
|
||||
private String name;
|
||||
private String pic;
|
||||
private String picUrl;
|
||||
private Long price;
|
||||
|
||||
private Integer stock;
|
||||
private String spuName;
|
||||
private String goodsName;
|
||||
|
||||
}
|
@ -2,14 +2,27 @@ package com.youlai.mall.pms.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.youlai.common.base.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
public class PmsAttribute {
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PmsAttribute extends BaseEntity {
|
||||
|
||||
@TableId(type=IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long categoryId;
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 类型(1:规格;2:属性;)
|
||||
*/
|
||||
private Integer type;
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.youlai.common.base.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class PmsBrand extends BaseEntity {
|
||||
@ -12,13 +14,10 @@ public class PmsBrand extends BaseEntity {
|
||||
@TableId(type= IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
private String name;
|
||||
|
||||
private String logo;
|
||||
|
||||
private String firstLetter;
|
||||
private String logoUrl;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Integer status;
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ public class PmsCategory extends BaseEntity {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long parentId;
|
||||
private String icon;
|
||||
private String iconUrl;
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
private Integer level;
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
private Integer sort;
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
private Integer status;
|
||||
private Integer visible;
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.youlai.mall.pms.pojo.entity;
|
||||
|
||||
import com.youlai.common.base.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PmsCategoryBrand extends BaseEntity {
|
||||
|
||||
private Long categoryId;
|
||||
|
||||
private Long brandId;
|
||||
|
||||
}
|
@ -7,16 +7,14 @@ import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PmsSku extends BaseEntity {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private Long spuId;
|
||||
private String sn;
|
||||
private String name;
|
||||
private String code;
|
||||
private String pic;
|
||||
private Long originPrice;
|
||||
private Long spuId;
|
||||
private String specIds;
|
||||
private Long price;
|
||||
private Integer stock;
|
||||
private Integer lockedStock;
|
||||
private String specValueIds;
|
||||
private String picUrl;
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
package com.youlai.mall.pms.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.youlai.common.base.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PmsSpec extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 全面屏手机 颜色 版本
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private Long categoryId;
|
||||
private String name;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<PmsSpuSpecValue> values = new ArrayList<>();
|
||||
|
||||
}
|
@ -9,8 +9,7 @@ import lombok.experimental.Accessors;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ -24,8 +23,8 @@ public class PmsSpu extends BaseEntity {
|
||||
private Long originPrice;
|
||||
private Long price;
|
||||
private Integer sales;
|
||||
private String pic;
|
||||
private String pics;
|
||||
private String picUrl;
|
||||
private String album;
|
||||
private String unit;
|
||||
private String description;
|
||||
private String detail;
|
||||
@ -38,8 +37,5 @@ public class PmsSpu extends BaseEntity {
|
||||
private String brandName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<PmsSku> skus;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<String> picList;
|
||||
private List<PmsSku> skuList;
|
||||
}
|
||||
|
@ -18,5 +18,7 @@ public class PmsSpuAttributeValue extends BaseEntity {
|
||||
private Long attributeId;
|
||||
private String name;
|
||||
private String value;
|
||||
private Integer type;
|
||||
private String picUrl;
|
||||
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.youlai.mall.pms.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.youlai.common.base.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Data
|
||||
public class PmsSpuSpecValue extends BaseEntity {
|
||||
|
||||
@TableId(type = IdType.INPUT)
|
||||
private Long id;
|
||||
private Long spuId;
|
||||
private Long specId;
|
||||
private String value;
|
||||
}
|
@ -16,13 +16,11 @@ public class CategoryVO {
|
||||
|
||||
private Integer level;
|
||||
|
||||
private String icon;
|
||||
private String iconUrl;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private String unit;
|
||||
|
||||
private Integer status;
|
||||
private Integer visible;
|
||||
|
||||
private List<CategoryVO> children=new ArrayList<>();
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.youlai.mall.pms.pojo.vo.admin;
|
||||
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品详情视图层对象
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
public class GoodsDetailVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Long categoryId;
|
||||
|
||||
private Long brandId;
|
||||
|
||||
private Long originPrice;
|
||||
|
||||
private Long price;
|
||||
|
||||
private String picUrl;
|
||||
|
||||
private List<String> subPicUrls;
|
||||
|
||||
private String description;
|
||||
|
||||
private String detail;
|
||||
|
||||
|
||||
private List<PmsSpuAttributeValue> attrList;
|
||||
|
||||
private List<PmsSpuAttributeValue> specList;
|
||||
|
||||
private List<PmsSku> skuList;
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package com.youlai.mall.pms.pojo.vo.app;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品详情页-商品详细信息
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/8/8
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("商品详情")
|
||||
public class GoodsDetailVO {
|
||||
|
||||
@ApiModelProperty("商品基本信息")
|
||||
private GoodsInfo goodsInfo;
|
||||
|
||||
@ApiModelProperty("商品属性列表")
|
||||
private List<Attribute> attributeList;
|
||||
|
||||
@ApiModelProperty("商品规格列表")
|
||||
private List<Specification> specList;
|
||||
|
||||
@ApiModelProperty("商品库存单元列表")
|
||||
private List<Sku> skuList;
|
||||
|
||||
@Data
|
||||
@ApiModel("商品信息")
|
||||
public static class GoodsInfo {
|
||||
|
||||
@ApiModelProperty("商品ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("商品名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("商品原价(单位:分)")
|
||||
private Long originPrice;
|
||||
|
||||
@ApiModelProperty("商品零售价(单位:分)")
|
||||
private Long price;
|
||||
|
||||
@ApiModelProperty("销量")
|
||||
private Integer sales;
|
||||
|
||||
@ApiModelProperty("商品图册")
|
||||
private List<String> album;
|
||||
|
||||
@ApiModelProperty("商品详情")
|
||||
private String detail;
|
||||
}
|
||||
|
||||
|
||||
@Data
|
||||
@ApiModel("属性信息")
|
||||
public static class Attribute {
|
||||
@ApiModelProperty("属性ID")
|
||||
private Long id;
|
||||
@ApiModelProperty("属性名称")
|
||||
private String name;
|
||||
@ApiModelProperty("属性值")
|
||||
private String value;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ApiModel("规格信息")
|
||||
public static class Specification {
|
||||
|
||||
@ApiModelProperty(value = "规格名称", example = "颜色")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "规格项列表", example = "[黑,白]")
|
||||
private List<Value> values;
|
||||
|
||||
@Data
|
||||
@ApiModel("规格项")
|
||||
public static class Value {
|
||||
@ApiModelProperty("规格项ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("规格项值")
|
||||
private String value;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@ApiModel("商品库存单元")
|
||||
public static class Sku {
|
||||
@ApiModelProperty("库存单元ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("库存单元名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("库存单元规格值ID集合,以英文逗号拼接")
|
||||
private String specIds;
|
||||
|
||||
@ApiModelProperty("价格")
|
||||
private Long price;
|
||||
|
||||
@ApiModelProperty("库存")
|
||||
private Integer stock;
|
||||
|
||||
@ApiModelProperty("商品图片URL")
|
||||
private String picUrl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.youlai.mall.pms.pojo.vo.app;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商品列表页-商品基础信息
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/8/8
|
||||
*/
|
||||
@Data
|
||||
public class GoodsVO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long price;
|
||||
private Integer sales;
|
||||
private String picUrl;
|
||||
}
|
@ -8,6 +8,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
|
||||
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients(basePackageClasses = {MemberFeignClient.class})
|
||||
|
@ -15,4 +15,7 @@ public interface PmsConstants {
|
||||
String LOCK_PRODUCT_DETAIL = "lock:product:detail";
|
||||
|
||||
String PRODUCT_REDIS_BLOOM_FILTER = "product:redis:bloom:filter";
|
||||
|
||||
String TEMP_ID_PREFIX = "tid_";
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.youlai.mall.pms.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 商品属性类型枚举
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
public enum AttributeTypeEnum {
|
||||
|
||||
SPECIFICATION(1, "规格"),
|
||||
ATTRIBUTE(2, "属性");
|
||||
|
||||
AttributeTypeEnum(int value, String name) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private Integer value;
|
||||
|
||||
@Getter
|
||||
private String name;
|
||||
|
||||
public static AttributeTypeEnum getByValue(Integer value) {
|
||||
AttributeTypeEnum attributeTypeEnum = null;
|
||||
|
||||
for (AttributeTypeEnum item : values()) {
|
||||
if (item.getValue().equals(value)) {
|
||||
attributeTypeEnum = item;
|
||||
}
|
||||
}
|
||||
return attributeTypeEnum;
|
||||
}
|
||||
|
||||
}
|
@ -2,9 +2,10 @@ package com.youlai.mall.pms.config;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.hash.Funnel;
|
||||
import com.youlai.mall.pms.common.constant.PmsConstants;
|
||||
import com.youlai.mall.pms.component.BloomRedisService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.service.IProductService;
|
||||
import com.youlai.mall.pms.serviceapp.IGoodsService;
|
||||
import com.youlai.mall.pms.utils.BloomFilterUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -13,11 +14,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_REDIS_BLOOM_FILTER;
|
||||
|
||||
/**
|
||||
* @Author DaniR
|
||||
* @Description
|
||||
@ -28,7 +26,7 @@ import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_REDIS_BLO
|
||||
@AllArgsConstructor
|
||||
public class BloomFilterConfig implements InitializingBean {
|
||||
|
||||
private final IProductService iProductService;
|
||||
private final IGoodsService goodsService;
|
||||
private final RedisTemplate redisTemplate;
|
||||
|
||||
@Bean
|
||||
@ -48,11 +46,11 @@ public class BloomFilterConfig implements InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
List<PmsSpu> list = iProductService.list();
|
||||
List<PmsSpu> list = goodsService.list();
|
||||
log.info("加载产品到布隆过滤器当中,size:{}", list.size());
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
list.stream().filter(item -> item.getId() > 0).forEach(item -> {
|
||||
bloomRedisService().addByBloomFilter(PRODUCT_REDIS_BLOOM_FILTER, item.getId() + "");
|
||||
bloomRedisService().addByBloomFilter(PmsConstants.PRODUCT_REDIS_BLOOM_FILTER, item.getId() + "");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.AttributeFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsAttribute;
|
||||
import com.youlai.mall.pms.service.IPmsAttributeService;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -14,9 +14,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "【系统管理】商品属性")
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "系统管理端-属性信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/attributes")
|
||||
@Slf4j
|
||||
@ -27,45 +29,23 @@ public class AttributeController {
|
||||
|
||||
@ApiOperation(value = "属性列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "categoryId", value = "商品分类ID", paramType = "query", dataType = "Long")
|
||||
@ApiImplicitParam(name = "categoryId", value = "分类ID", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "type", value = "属性类型(1:规格;2:属性)", paramType = "query", dataType = "Integer"),
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(Long categoryId) {
|
||||
public Result list(Long categoryId, Integer type) {
|
||||
List<PmsAttribute> list = iPmsAttributeService.list(new LambdaQueryWrapper<PmsAttribute>()
|
||||
.eq(PmsAttribute::getCategoryId, categoryId));
|
||||
.eq(categoryId != null, PmsAttribute::getCategoryId, categoryId)
|
||||
.eq(type != null, PmsAttribute::getType, type)
|
||||
);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量新增")
|
||||
@ApiImplicitParam(name = "attributes", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsAttribute")
|
||||
@ApiOperation(value = "批量新增/修改")
|
||||
@ApiImplicitParam(name = "attributeForm", value = "实体JSON对象", required = true, paramType = "body", dataType = "AttributeFormDTO")
|
||||
@PostMapping("/batch")
|
||||
public Result saveBatch(@RequestBody List<PmsAttribute> attributes) {
|
||||
|
||||
if (CollectionUtil.isEmpty(attributes)) {
|
||||
return Result.failed("请至少提交一条属性");
|
||||
}
|
||||
|
||||
Long categoryId = attributes.get(0).getCategoryId();
|
||||
List<Long> formIds = attributes.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
List<Long> dbIds = iPmsAttributeService
|
||||
.list(new LambdaQueryWrapper<PmsAttribute>()
|
||||
.eq(PmsAttribute::getCategoryId, categoryId)
|
||||
.select(PmsAttribute::getId))
|
||||
.stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 提交删除
|
||||
if (CollectionUtil.isNotEmpty(dbIds)) {
|
||||
List<Long> removeIds = dbIds.stream()
|
||||
.filter(id -> CollectionUtil.isEmpty(formIds) || !formIds.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(removeIds)) {
|
||||
iPmsAttributeService.removeByIds(removeIds);
|
||||
}
|
||||
}
|
||||
|
||||
boolean result = iPmsAttributeService.saveOrUpdateBatch(attributes);
|
||||
public Result saveBatch(@RequestBody AttributeFormDTO attributeForm) {
|
||||
boolean result = iPmsAttributeService.saveBatch(attributeForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
}
|
||||
|
@ -2,60 +2,54 @@ package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.constant.GlobalConstants;
|
||||
import com.youlai.common.enums.QueryModeEnum;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsBrand;
|
||||
import com.youlai.mall.pms.service.IPmsBrandService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "【系统管理】品牌接口")
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "系统管理端-品牌信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/brands")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class BrandController {
|
||||
|
||||
private IPmsBrandService iPmsBrandService;
|
||||
private final IPmsBrandService iPmsBrandService;
|
||||
|
||||
@ApiOperation(value = "列表分页")
|
||||
@ApiOperation(value = "品牌列表分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "queryMode", paramType = "query", dataType = "QueryModeEnum"),
|
||||
@ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "name", value = "品牌名称", paramType = "query", dataType = "String")
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(String queryMode, Integer page, Integer limit, String name) {
|
||||
QueryModeEnum queryModeEnum = QueryModeEnum.getByCode(queryMode);
|
||||
LambdaQueryWrapper<PmsBrand> queryWrapper = new LambdaQueryWrapper<>();
|
||||
switch (queryModeEnum) {
|
||||
case PAGE:
|
||||
queryWrapper.like(StrUtil.isNotBlank(name), PmsBrand::getName, name);
|
||||
Page<PmsBrand> result = iPmsBrandService.page(new Page<>(page, limit), queryWrapper);
|
||||
return Result.success(result.getRecords(), result.getTotal());
|
||||
case LIST:
|
||||
queryWrapper.eq(PmsBrand::getStatus, GlobalConstants.STATUS_YES)
|
||||
.select(PmsBrand::getId, PmsBrand::getName);
|
||||
List<PmsBrand> list = iPmsBrandService.list(queryWrapper);
|
||||
return Result.success(list);
|
||||
default:
|
||||
return Result.failed(ResultCode.QUERY_MODE_IS_NULL);
|
||||
}
|
||||
@GetMapping("/page")
|
||||
public Result page(Integer page, Integer limit, String name) {
|
||||
LambdaQueryWrapper<PmsBrand> queryWrapper = new LambdaQueryWrapper<PmsBrand>().like(StrUtil.isNotBlank(name), PmsBrand::getName, name);
|
||||
Page<PmsBrand> result = iPmsBrandService.page(new Page<>(page, limit), queryWrapper);
|
||||
return Result.success(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "品牌列表")
|
||||
@GetMapping
|
||||
public Result list() {
|
||||
List<PmsBrand> list = iPmsBrandService.list(new LambdaQueryWrapper<PmsBrand>()
|
||||
.select(PmsBrand::getId, PmsBrand::getName));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "品牌详情")
|
||||
@ApiImplicitParam(name = "id", value = "品牌id", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
@ -92,17 +86,4 @@ public class BrandController {
|
||||
boolean status = iPmsBrandService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改品牌")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "brand", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsBrand")
|
||||
})
|
||||
@PatchMapping(value = "/{id}")
|
||||
public Result patch(@PathVariable Long id, @RequestBody PmsBrand brand) {
|
||||
LambdaUpdateWrapper<PmsBrand> updateWrapper = new LambdaUpdateWrapper<PmsBrand>().eq(PmsBrand::getId, id);
|
||||
updateWrapper.set(brand.getStatus()!=null,PmsBrand::getStatus, brand.getStatus());
|
||||
boolean result = iPmsBrandService.update(updateWrapper);
|
||||
return Result.success(result);
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,53 @@
|
||||
package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.youlai.common.enums.QueryModeEnum;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsAttribute;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategory;
|
||||
import com.youlai.mall.pms.pojo.vo.CategoryVO;
|
||||
import com.youlai.mall.pms.service.IPmsAttributeService;
|
||||
import com.youlai.mall.pms.service.IPmsCategoryService;
|
||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "【系统管理】商品分类")
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "系统管理端-分类信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/categories")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class CategoryController {
|
||||
|
||||
private IPmsCategoryService iPmsCategoryService;
|
||||
private IPmsAttributeService iPmsAttributeService;
|
||||
private IPmsSpecService iPmsSpecService;
|
||||
|
||||
|
||||
@ApiOperation(value = "分类列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "queryMode", paramType = "query", dataType = "String"),
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(String queryMode) {
|
||||
QueryModeEnum queryModeEnum = QueryModeEnum.getByCode(queryMode);
|
||||
PmsCategory category = new PmsCategory();
|
||||
List list;
|
||||
switch (queryModeEnum) {
|
||||
case CASCADER:
|
||||
list = iPmsCategoryService.listForCascader(category);
|
||||
return Result.success(list);
|
||||
default:
|
||||
list = iPmsCategoryService.listForTree(category);
|
||||
return Result.success(list);
|
||||
}
|
||||
public Result<List<CategoryVO>> list() {
|
||||
List<CategoryVO> list = iPmsCategoryService.listTreeCategory(null);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "分类级联列表")
|
||||
@GetMapping("/cascade")
|
||||
public Result cascadeCategoryList() {
|
||||
List list = iPmsCategoryService.listCascadeCategory();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "分类详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品分类id", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
@ -64,10 +60,8 @@ public class CategoryController {
|
||||
@ApiImplicitParam(name = "category", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsCategory")
|
||||
@PostMapping
|
||||
public Result add(@RequestBody PmsCategory category) {
|
||||
iPmsCategoryService.save(category);
|
||||
CategoryVO categoryVO = new CategoryVO();
|
||||
BeanUtil.copyProperties(category, categoryVO);
|
||||
return Result.success(categoryVO);
|
||||
boolean result = iPmsCategoryService.save(category);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改分类")
|
||||
@ -76,38 +70,33 @@ public class CategoryController {
|
||||
@ApiImplicitParam(name = "category", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsCategory")
|
||||
})
|
||||
@PutMapping(value = "/{id}")
|
||||
public Result update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody PmsCategory category) {
|
||||
iPmsCategoryService.updateById(category);
|
||||
return Result.success(category);
|
||||
public Result update(@RequestBody PmsCategory category) {
|
||||
boolean result = iPmsCategoryService.updateById(category);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除商品分类")
|
||||
@ApiOperation(value = "删除分类")
|
||||
@ApiImplicitParam(name = "ids", value = "id集合,以英文逗号','分隔", required = true, paramType = "query", dataType = "String")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result delete(@PathVariable String ids) {
|
||||
List<String> idList = Arrays.asList(ids.split(","));
|
||||
Optional.ofNullable(idList).ifPresent(list -> {
|
||||
list.forEach(id -> {
|
||||
iPmsAttributeService.removeById(id);
|
||||
iPmsSpecService.removeById(id);
|
||||
});
|
||||
iPmsCategoryService.removeByIds(idList.stream().map(id -> Long.parseLong(id)).collect(Collectors.toList()));
|
||||
List<String> categoryIds = Arrays.asList(ids.split(","));
|
||||
Optional.ofNullable(categoryIds).ifPresent(categoryIdList -> {
|
||||
categoryIdList.forEach(categoryId -> iPmsAttributeService.remove(new LambdaQueryWrapper<PmsAttribute>().eq(PmsAttribute::getCategoryId, categoryId)));
|
||||
});
|
||||
return Result.success();
|
||||
boolean result = iPmsCategoryService.removeByIds(categoryIds);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改分类")
|
||||
@ApiOperation(value = "选择性修改分类")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "category", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsCategory")
|
||||
})
|
||||
@PatchMapping(value = "/{id}")
|
||||
public Result patch(@PathVariable Long id, @RequestBody PmsCategory category) {
|
||||
LambdaUpdateWrapper<PmsCategory> updateWrapper = new LambdaUpdateWrapper<PmsCategory>().eq(PmsCategory::getId, id);
|
||||
updateWrapper.set(category.getStatus() != null, PmsCategory::getStatus, category.getStatus());
|
||||
boolean update = iPmsCategoryService.update(updateWrapper);
|
||||
return Result.success(update);
|
||||
updateWrapper.set(category.getVisible() != null, PmsCategory::getVisible, category.getVisible());
|
||||
boolean result = iPmsCategoryService.update(updateWrapper);
|
||||
return Result.judge(result);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.GoodsFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.vo.admin.GoodsDetailVO;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "系统管理端-商品信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/goods")
|
||||
@AllArgsConstructor
|
||||
public class GoodsController {
|
||||
|
||||
private IPmsSpuService iPmsSpuService;
|
||||
|
||||
@ApiOperation(value = "商品分页列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "categoryId", value = "分类ID", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "name", value = "商品名称", paramType = "query", dataType = "String")
|
||||
|
||||
})
|
||||
@GetMapping("/page")
|
||||
public Result list(Integer page, Integer limit, String name, Long categoryId) {
|
||||
IPage<PmsSpu> result = iPmsSpuService.list(new Page<>(page, limit), name, categoryId);
|
||||
return Result.success(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品id", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(@PathVariable Long id) {
|
||||
GoodsDetailVO goodsDetail = iPmsSpuService.getGoodsById(id);
|
||||
return Result.success(goodsDetail);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增商品")
|
||||
@ApiImplicitParam(name = "goodsForm", value = "实体JSON对象", required = true, paramType = "body", dataType = "GoodsFormDTO")
|
||||
@PostMapping
|
||||
public Result add(@RequestBody GoodsFormDTO goodsForm) {
|
||||
boolean result = iPmsSpuService.addGoods(goodsForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改商品")
|
||||
@ApiImplicitParam(name = "id", value = "商品id", required = true, paramType = "path", dataType = "Long")
|
||||
@PutMapping(value = "/{id}")
|
||||
public Result update(@PathVariable Long id, @RequestBody GoodsFormDTO goods) {
|
||||
boolean result = iPmsSpuService.updateGoods(goods);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除商品")
|
||||
@ApiImplicitParam(name = "ids", value = "id集合,以英文逗号','分隔", required = true, paramType = "query", dataType = "String")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result delete(@PathVariable String ids) {
|
||||
boolean result = iPmsSpuService.removeByGoodsIds(Arrays.asList(ids.split(",")).stream().map(id -> Long.parseLong(id)).collect(Collectors.toList()));
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "选择性修改商品")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "spu", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsSpu")
|
||||
})
|
||||
@PatchMapping(value = "/{id}")
|
||||
public Result patch(@PathVariable Integer id, @RequestBody PmsSpu spu) {
|
||||
LambdaUpdateWrapper<PmsSpu> updateWrapper = new LambdaUpdateWrapper<PmsSpu>().eq(PmsSpu::getId, id);
|
||||
updateWrapper.set(spu.getStatus() != null, PmsSpu::getStatus, spu.getStatus());
|
||||
boolean update = iPmsSpuService.update(updateWrapper);
|
||||
return Result.success(update);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "【系统管理】商品规格")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/specs")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class SpecController {
|
||||
|
||||
private IPmsSpecService iPmsSpecService;
|
||||
|
||||
@ApiOperation(value = "分类规格列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "categoryId", value = "分类ID", paramType = "query", dataType = "Long")
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(Long categoryId) {
|
||||
List<PmsSpec> list = iPmsSpecService
|
||||
.list(new LambdaQueryWrapper<PmsSpec>()
|
||||
.eq(PmsSpec::getCategoryId, categoryId));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增规格")
|
||||
@ApiImplicitParam(name = "specCategories", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsSpecCategory")
|
||||
@PostMapping
|
||||
public Result save(@RequestBody List<PmsSpec> specCategories) {
|
||||
|
||||
if (CollectionUtil.isEmpty(specCategories)) {
|
||||
return Result.failed("至少提交一条规格");
|
||||
}
|
||||
|
||||
Long categoryId = specCategories.get(0).getCategoryId();
|
||||
|
||||
|
||||
List<Long> formIds = specCategories.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
|
||||
List<Long> databaseIds = iPmsSpecService
|
||||
.list(new LambdaQueryWrapper<PmsSpec>()
|
||||
.eq(PmsSpec::getCategoryId, categoryId)
|
||||
.select(PmsSpec::getId)
|
||||
).stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 删除的商品分类规格
|
||||
if (CollectionUtil.isNotEmpty(databaseIds)) {
|
||||
List<Long> removeIds = databaseIds.stream()
|
||||
.filter(id -> CollectionUtil.isEmpty(formIds) || !formIds.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(removeIds)) {
|
||||
iPmsSpecService.removeByIds(removeIds);
|
||||
}
|
||||
}
|
||||
boolean result = iPmsSpecService.saveOrUpdateBatch(specCategories);
|
||||
return Result.judge(result);
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
package com.youlai.mall.pms.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.enums.QueryModeEnum;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "【系统管理】商品信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/spus")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class SpuController {
|
||||
|
||||
private IPmsSpuService iPmsSpuService;
|
||||
|
||||
@ApiOperation(value = "列表分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "queryMode", value = "查询模式", paramType = "query", dataType = "QueryModeEnum"),
|
||||
@ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "name", value = "商品名称", paramType = "query", dataType = "String"),
|
||||
@ApiImplicitParam(name = "categoryId", value = "商品类目", paramType = "query", dataType = "Long")
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(
|
||||
String queryMode,
|
||||
Integer page,
|
||||
Integer limit,
|
||||
String name,
|
||||
Long categoryId
|
||||
) {
|
||||
QueryModeEnum queryModeEnum = QueryModeEnum.getByCode(queryMode);
|
||||
switch (queryModeEnum) {
|
||||
case PAGE:
|
||||
IPage<PmsSpu> result = iPmsSpuService.list(
|
||||
new Page<>(page, limit),
|
||||
new PmsSpu().setName(name).setCategoryId(categoryId)
|
||||
);
|
||||
return Result.success(result.getRecords(), result.getTotal());
|
||||
default:
|
||||
return Result.failed(ResultCode.QUERY_MODE_IS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品id", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(@PathVariable Long id) {
|
||||
ProductFormDTO spu = iPmsSpuService.getBySpuId(id);
|
||||
return Result.success(spu);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "新增商品")
|
||||
@ApiImplicitParam(name = "productBO", value = "实体JSON对象", required = true, paramType = "body", dataType = "ProductBO")
|
||||
@PostMapping
|
||||
public Result add(@RequestBody ProductFormDTO productFormDTO) {
|
||||
boolean status = iPmsSpuService.add(productFormDTO);
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改商品")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "商品id", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "spu", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsSpu")
|
||||
})
|
||||
@PutMapping(value = "/{id}")
|
||||
public Result update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody ProductFormDTO spu) {
|
||||
boolean status = iPmsSpuService.updateById(spu);
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除商品")
|
||||
@ApiImplicitParam(name = "ids", value = "id集合,以英文逗号','分隔", required = true, paramType = "query", dataType = "String")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result delete(@PathVariable String ids) {
|
||||
iPmsSpuService.removeBySpuIds(Arrays.asList(ids.split(",")).stream().map(id -> Long.parseLong(id)).collect(Collectors.toList()));
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改商品")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "spu", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsSpu")
|
||||
})
|
||||
@PatchMapping(value = "/{id}")
|
||||
public Result patch(@PathVariable Integer id, @RequestBody PmsSpu spu) {
|
||||
LambdaUpdateWrapper<PmsSpu> updateWrapper = new LambdaUpdateWrapper<PmsSpu>().eq(PmsSpu::getId, id);
|
||||
updateWrapper.set(spu.getStatus() != null, PmsSpu::getStatus, spu.getStatus());
|
||||
boolean update = iPmsSpuService.update(updateWrapper);
|
||||
return Result.success(update);
|
||||
}
|
||||
}
|
@ -7,21 +7,22 @@ import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Api(tags = "【系统管理】商品库存")
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "系统管理端-库存信息")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/skus")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class SkuController {
|
||||
@RequestMapping("/api/v1/inventories")
|
||||
@RequiredArgsConstructor
|
||||
public class StockController {
|
||||
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
private final IPmsSkuService iPmsSkuService;
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品SkuID", required = true, paramType = "path", dataType = "Long")
|
||||
@ApiOperation(value = "商品库存详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(@PathVariable Long id) {
|
||||
PmsSku sku = iPmsSkuService.getById(id);
|
||||
@ -30,29 +31,26 @@ public class SkuController {
|
||||
|
||||
@ApiOperation(value = "修改库存")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "商品id", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "sku", value = "实体JSON对象", required = true, paramType = "body", dataType = "PmsSku")
|
||||
})
|
||||
@PutMapping(value = "/{id}")
|
||||
public Result update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody PmsSku sku) {
|
||||
public Result update(@PathVariable Long id, @RequestBody PmsSku sku) {
|
||||
boolean status = iPmsSkuService.updateById(sku);
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "修改库存")
|
||||
@ApiOperation(value = "修改商品库存")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "Sku ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "num", value = "库存数量", required = true, paramType = "query", dataType = "Long")
|
||||
})
|
||||
@PutMapping("/{id}/stock")
|
||||
@PatchMapping("/{id}/stock")
|
||||
public Result updateStock(@PathVariable Long id, @RequestParam Integer num) {
|
||||
PmsSku sku = iPmsSkuService.getById(id);
|
||||
sku.setStock(sku.getStock() + num);
|
||||
boolean result = iPmsSkuService.updateById(sku);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import com.youlai.common.constant.GlobalConstants;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategory;
|
||||
import com.youlai.mall.pms.pojo.vo.CategoryVO;
|
||||
import com.youlai.mall.pms.service.IPmsCategoryService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -17,8 +14,11 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "【移动端】商品分类")
|
||||
@RestController("APPCategoryController")
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Api(tags = "移动端-商品分类")
|
||||
@RestController("appCategoryController")
|
||||
@RequestMapping("/app-api/v1/categories")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@ -27,15 +27,10 @@ public class CategoryController {
|
||||
private IPmsCategoryService iPmsCategoryService;
|
||||
|
||||
@ApiOperation(value = "分类列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "parentId", paramType = "query", dataType = "Long")
|
||||
})
|
||||
@ApiImplicitParam(name = "parentId", paramType = "query", dataType = "Long")
|
||||
@GetMapping
|
||||
public Result list(Long parentId) {
|
||||
PmsCategory category = new PmsCategory();
|
||||
category.setParentId(parentId);
|
||||
category.setStatus(GlobalConstants.STATUS_YES);
|
||||
List<CategoryVO> list = iPmsCategoryService.listForTree(category);
|
||||
List<CategoryVO> list = iPmsCategoryService.listTreeCategory(parentId);
|
||||
return Result.success(list);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO;
|
||||
import com.youlai.mall.pms.pojo.vo.app.GoodsVO;
|
||||
import com.youlai.mall.pms.serviceapp.IGoodsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import jodd.util.StringUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "移动端-商品信息")
|
||||
@RestController(value = "appGoodsController")
|
||||
@RequestMapping("/app-api/v1/goods")
|
||||
@AllArgsConstructor
|
||||
public class GoodsController {
|
||||
|
||||
private IGoodsService goodsService;
|
||||
|
||||
@ApiOperation(value = "商品分页列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "page", value = "页码", example = "1", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", value = "每页数量", example = "10", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "name", value = "商品名称", example = "华为P50", paramType = "query", dataType = "String"),
|
||||
@ApiImplicitParam(name = "categoryId", value = "商品类目", example = "1", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "orderBy", value = "排序字段", example = "price", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "isAsc", value = "是否升序", example = "false", paramType = "query", dataType = "Boolean")
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(Integer page, Integer limit, String name, Long categoryId, String orderBy, Boolean isAsc) {
|
||||
Page<PmsSpu> pageResult = goodsService.page(new Page<>(page, limit), new QueryWrapper<PmsSpu>()
|
||||
.eq(categoryId != null, "category_id", categoryId)
|
||||
.like(StrUtil.isNotBlank(name), "name", name)
|
||||
.select("id", "name", "pic_url", "price", "sales")
|
||||
.orderBy(StringUtil.isNotBlank(orderBy), isAsc, StrUtil.toUnderlineCase(orderBy))
|
||||
);
|
||||
|
||||
List<GoodsVO> list = pageResult.getRecords().stream()
|
||||
.map(item -> {
|
||||
GoodsVO goodsVO = new GoodsVO();
|
||||
BeanUtil.copyProperties(item, goodsVO);
|
||||
return goodsVO;
|
||||
}).collect(Collectors.toList());
|
||||
return Result.success(list, pageResult.getTotal());
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result<GoodsDetailVO> detail(@PathVariable Long id) {
|
||||
GoodsDetailVO goodsDetailVO = goodsService.getGoodsById(id);
|
||||
return Result.success(goodsDetailVO);
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import com.youlai.mall.pms.service.IProductService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "【移动端】商品信息")
|
||||
@RestController("APPSpuController")
|
||||
@RequestMapping("/app-api/v1/products")
|
||||
@AllArgsConstructor
|
||||
public class ProductController {
|
||||
|
||||
private IPmsSpuService iPmsSpuService;
|
||||
|
||||
private IProductService iProductService;
|
||||
|
||||
@ApiOperation(value = "列表分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "limit", value = "每页数量", defaultValue = "10", paramType = "query", dataType = "Long"),
|
||||
@ApiImplicitParam(name = "name", value = "商品名称", paramType = "query", dataType = "String"),
|
||||
@ApiImplicitParam(name = "categoryId", value = "商品类目", paramType = "query", dataType = "Long")
|
||||
})
|
||||
@GetMapping
|
||||
public Result list(
|
||||
Integer page,
|
||||
Integer limit,
|
||||
String name,
|
||||
Long categoryId
|
||||
) {
|
||||
Page<PmsSpu> result = iPmsSpuService.page(new Page<>(page, limit), new LambdaQueryWrapper<PmsSpu>()
|
||||
.eq(categoryId != null, PmsSpu::getCategoryId, categoryId)
|
||||
.like(StrUtil.isNotBlank(name), PmsSpu::getName, name)
|
||||
.select(PmsSpu::getId,
|
||||
PmsSpu::getName,
|
||||
PmsSpu::getPic,
|
||||
PmsSpu::getPrice,
|
||||
PmsSpu::getSales
|
||||
)
|
||||
);
|
||||
List<ProductDTO> list = result.getRecords().stream()
|
||||
.map(item -> JSONUtil.toBean(JSONUtil.toJsonStr(item), ProductDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(list, result.getTotal());
|
||||
}
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(@PathVariable Long id) {
|
||||
ProductFormDTO product = iProductService.getProductById(id);
|
||||
return Result.success(product);
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @description TODO
|
||||
* @createTime 2021/3/7 22:55
|
||||
*/
|
||||
@Api(tags = "【移动端】商品搜索")
|
||||
@RestController("APPSearchController")
|
||||
@RequestMapping("/app-api/v1/search")
|
||||
@AllArgsConstructor
|
||||
public class SearchController {
|
||||
|
||||
@ApiOperation(value = "关键字搜索商品")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "key", value = "关键字", paramType = "query", dataType = "String"),
|
||||
})
|
||||
@GetMapping("/{name}")
|
||||
public Result searchByName(@PathVariable String name) {
|
||||
/* SearchSourceBuilder builder = new SearchSourceBuilder();
|
||||
builder.query(QueryBuilders.matchQuery("name", name));
|
||||
List<PmsProduct> list = elasticSearchService.search(builder.query(), PmsProduct.class, "pms_spu");
|
||||
return Result.success(list);*/
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "【移动端】商品库存")
|
||||
@RestController("APPSkuController")
|
||||
@RequestMapping("/app-api/v1/skus")
|
||||
@AllArgsConstructor
|
||||
public class SkuController {
|
||||
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
|
||||
@ApiOperation(value = "商品详情")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(@PathVariable Long id) {
|
||||
SkuDTO sku = iPmsSkuService.getSkuById(id);
|
||||
return Result.success(sku);
|
||||
}
|
||||
|
||||
@ApiOperation("获取商品的库存数量")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}/stock")
|
||||
public Result<Integer> getStockById(@PathVariable Long id) {
|
||||
Integer stock = iPmsSkuService.getStockById(id);
|
||||
return Result.success(stock);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "锁定库存")
|
||||
@ApiImplicitParam(name = "list", value = "商品列表", required = true, paramType = "body", dataType = "SkuLockDTO")
|
||||
@PutMapping("/lock_stock")
|
||||
public Result<Boolean> lockStock(@RequestBody List<SkuLockDTO> list) {
|
||||
boolean result = iPmsSkuService.lockStock(list);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "解锁库存")
|
||||
@ApiImplicitParam(name = "orderToken", value = "订单令牌", required = true, paramType = "body", dataType = "String")
|
||||
@PutMapping("/unlock_stock")
|
||||
public Result<Boolean> unlockStock(String orderToken) {
|
||||
boolean result = iPmsSkuService.unlockStock(orderToken);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "扣减库存")
|
||||
@ApiImplicitParam(name = "orderToken", value = "订单令牌", required = true, paramType = "body", dataType = "String")
|
||||
@PutMapping("/deduct_stock")
|
||||
public Result<Boolean> deductStock(String orderToken) {
|
||||
boolean result = iPmsSkuService.deductStock(orderToken);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.youlai.mall.pms.controller.app;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.LockStockDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "移动端-商品库存")
|
||||
@RestController(value = "appStockController")
|
||||
@RequestMapping("/app-api/v1/stocks")
|
||||
@AllArgsConstructor
|
||||
public class StockController {
|
||||
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
|
||||
@ApiOperation(value = "商品库存单元详情")
|
||||
@GetMapping("/{skuId}")
|
||||
public Result detail(@PathVariable Long skuId) {
|
||||
SkuDTO sku = iPmsSkuService.getSkuById(skuId);
|
||||
return Result.success(sku);
|
||||
}
|
||||
|
||||
@ApiOperation("获取商品的库存数量")
|
||||
@GetMapping("/{skuId}/stock")
|
||||
public Result<Integer> getStockById(@PathVariable Long skuId) {
|
||||
Integer stock = iPmsSkuService.getStockById(skuId);
|
||||
return Result.success(stock);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "锁定库存")
|
||||
@PutMapping("/_lock")
|
||||
public Result<Boolean> lockStock(@RequestBody List<LockStockDTO> list) {
|
||||
boolean result = iPmsSkuService.lockStock(list);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "解锁库存")
|
||||
@PutMapping("/_unlock")
|
||||
public Result<Boolean> unlockStock(String orderToken) {
|
||||
boolean result = iPmsSkuService.unlockStock(orderToken);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "扣减库存")
|
||||
@PutMapping("/_deduct")
|
||||
public Result<Boolean> deductStock(String orderToken) {
|
||||
boolean result = iPmsSkuService.deductStock(orderToken);
|
||||
return Result.judge(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.youlai.mall.pms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategory;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategoryBrand;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PmsCategoryBrandMapper extends BaseMapper<PmsCategoryBrand> {
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ package com.youlai.mall.pms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
@ -17,10 +17,6 @@ public interface PmsSkuMapper extends BaseMapper<PmsSku> {
|
||||
List<PmsSku> listBySpuId(Long spuId);
|
||||
|
||||
|
||||
@Select("<script>" +
|
||||
" select t1.id,t1.code,t1.name,t1.pic,t1.price,(t1.stock-t1.locked_stock) as stock,t2.name as spu_name from pms_sku t1" +
|
||||
" left join pms_spu t2 on t1.spu_id=t2.id" +
|
||||
" where t1.id=#{id}" +
|
||||
"</script>")
|
||||
|
||||
SkuDTO getSkuById(Long id);
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
package com.youlai.mall.pms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PmsSpecMapper extends BaseMapper<PmsSpec> {
|
||||
|
||||
@Select("<script>" +
|
||||
" SELECT " +
|
||||
" t1.id,t1.category_id,t1.name,t2.id AS spuId " +
|
||||
" FROM " +
|
||||
" pms_spec t1 " +
|
||||
" LEFT JOIN pms_spu t2 ON t1.category_id = t2.category_id " +
|
||||
" WHERE " +
|
||||
" t2.id =#{spuId} " +
|
||||
"</script>")
|
||||
@Results({
|
||||
@Result(id = true, column = "id", property = "id"),
|
||||
@Result(property = "values", column = "{specId= t1.id,spuId=spuId}", many = @Many(select = "com.youlai.mall.pms.mapper.PmsSpuSpecValueMapper.listByCondition"))
|
||||
})
|
||||
List<PmsSpec> listBySpuId(Long spuId);
|
||||
}
|
@ -3,39 +3,15 @@ package com.youlai.mall.pms.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import org.apache.ibatis.annotations.Many;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Mapper
|
||||
public interface PmsSpuMapper extends BaseMapper<PmsSpu> {
|
||||
|
||||
@Select("<script>" +
|
||||
" SELECT " +
|
||||
" t1.*," +
|
||||
" t2.NAME AS category_name ," +
|
||||
" t3.NAME AS brand_name " +
|
||||
" FROM " +
|
||||
" pms_spu t1" +
|
||||
" LEFT JOIN pms_category t2 ON t1.category_id = t2.id " +
|
||||
" LEFT JOIN pms_brand t3 ON t1.brand_id = t3.id " +
|
||||
" WHERE 1=1 " +
|
||||
" <if test ='spu.categoryId !=null and spu.categoryId > 0' >" +
|
||||
" AND t2.id = #{spu.categoryId} " +
|
||||
" </if>" +
|
||||
" ORDER BY t1.gmt_create DESC" +
|
||||
"</script>")
|
||||
@Results({
|
||||
@Result(id = true, column = "id", property = "id"),
|
||||
@Result(property = "skus",column = "id",many = @Many(select="com.youlai.mall.pms.mapper.PmsSkuMapper.listBySpuId"))
|
||||
})
|
||||
List<PmsSpu> list(Page<PmsSpu> page, PmsSpu spu);
|
||||
List<PmsSpu> list(Page<PmsSpu> page, String name, Long categoryId);
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
package com.youlai.mall.pms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuSpecValue;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Mapper
|
||||
public interface PmsSpuSpecValueMapper extends BaseMapper<PmsSpuSpecValue> {
|
||||
|
||||
@Select("<script>" +
|
||||
" SELECT " +
|
||||
" id, " +
|
||||
" spu_id, " +
|
||||
" spec_id, " +
|
||||
" value" +
|
||||
" FROM " +
|
||||
" pms_spu_spec_value " +
|
||||
" WHERE " +
|
||||
" spu_id = #{spuId} " +
|
||||
" AND spec_id = #{specId} " +
|
||||
"</script>")
|
||||
List<PmsSpuSpecValue> listByCondition(Map<String, String> param);
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.AttributeFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsAttribute;
|
||||
|
||||
public interface IPmsAttributeService extends IService<PmsAttribute> {
|
||||
|
||||
|
||||
|
||||
boolean saveBatch(AttributeFormDTO attributeForm);
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategoryBrand;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
public interface IPmsCategoryBrandService extends IService<PmsCategoryBrand> {
|
||||
|
||||
}
|
@ -1,15 +1,20 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.common.web.vo.CascaderVO;
|
||||
import com.youlai.common.pojo.vo.CascadeVO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategory;
|
||||
import com.youlai.mall.pms.pojo.vo.CategoryVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
public interface IPmsCategoryService extends IService<PmsCategory> {
|
||||
|
||||
List<CategoryVO> listForTree(PmsCategory category);
|
||||
|
||||
List<CascaderVO> listForCascader(PmsCategory category);
|
||||
List<CategoryVO> listTreeCategory(Long parentId);
|
||||
|
||||
List<CascadeVO> listCascadeCategory();
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.LockStockDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -12,7 +12,7 @@ public interface IPmsSkuService extends IService<PmsSku> {
|
||||
/**
|
||||
* 锁定库存
|
||||
*/
|
||||
boolean lockStock(List<SkuLockDTO> list);
|
||||
boolean lockStock(List<LockStockDTO> list);
|
||||
|
||||
/**
|
||||
* 锁定库存
|
||||
|
@ -1,12 +0,0 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IPmsSpecService extends IService<PmsSpec> {
|
||||
|
||||
List<PmsSpec> listBySpuId(Long spuId);
|
||||
|
||||
}
|
@ -3,22 +3,22 @@ package com.youlai.mall.pms.service;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.GoodsFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.vo.admin.GoodsDetailVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface IPmsSpuService extends IService<PmsSpu> {
|
||||
|
||||
IPage<PmsSpu> list(Page<PmsSpu> page, PmsSpu spu);
|
||||
IPage<PmsSpu> list(Page<PmsSpu> page, String name,Long categoryId);
|
||||
|
||||
boolean add(com.youlai.mall.pms.pojo.dto.admin.ProductFormDTO productFormDTO);
|
||||
boolean addGoods(GoodsFormDTO goodsFormDTO);
|
||||
|
||||
com.youlai.mall.pms.pojo.dto.admin.ProductFormDTO getBySpuId(Long id);
|
||||
boolean removeByGoodsIds(List<Long> spuIds);
|
||||
|
||||
boolean removeBySpuIds(List<Long> spuIds);
|
||||
boolean updateGoods(GoodsFormDTO goodsFormDTO);
|
||||
|
||||
boolean updateById(com.youlai.mall.pms.pojo.dto.admin.ProductFormDTO productFormDTO);
|
||||
|
||||
ProductFormDTO getProductByIdForApp(Long id);
|
||||
GoodsDetailVO getGoodsById(Long id);
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuSpecValue;
|
||||
|
||||
|
||||
public interface IPmsSpuSpecValueService extends IService<PmsSpuSpecValue> {
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package com.youlai.mall.pms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
|
||||
|
||||
public interface IProductService extends IService<PmsSpu> {
|
||||
|
||||
ProductFormDTO getProductById(Long id);
|
||||
}
|
@ -1,16 +1,61 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.mapper.PmsAttributeMapper;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.AttributeFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsAttribute;
|
||||
import com.youlai.mall.pms.service.IPmsAttributeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Service
|
||||
public class PmsAttributeServiceImpl extends ServiceImpl<PmsAttributeMapper, PmsAttribute> implements IPmsAttributeService {
|
||||
|
||||
@Override
|
||||
public boolean saveBatch(AttributeFormDTO attributeForm) {
|
||||
Long categoryId = attributeForm.getCategoryId();
|
||||
Integer type = attributeForm.getType();
|
||||
|
||||
List<Long> formIds = attributeForm.getAttributes().stream()
|
||||
.filter(item -> item.getId() != null)
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> dbIds = this.list(new LambdaQueryWrapper<PmsAttribute>()
|
||||
.eq(PmsAttribute::getCategoryId, categoryId)
|
||||
.eq(PmsAttribute::getType, attributeForm.getType())
|
||||
.select(PmsAttribute::getId)).stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 删除此次表单没有的属性ID
|
||||
if (CollectionUtil.isNotEmpty(dbIds)) {
|
||||
List<Long> rmIds = dbIds.stream()
|
||||
.filter(id -> CollectionUtil.isEmpty(formIds) || !formIds.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(rmIds)) {
|
||||
this.removeByIds(rmIds);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增/修改表单提交的属性
|
||||
List<AttributeFormDTO.Attribute> formAttributes = attributeForm.getAttributes();
|
||||
|
||||
List<PmsAttribute> attributeList = new ArrayList<>();
|
||||
|
||||
formAttributes.forEach(item -> {
|
||||
PmsAttribute attribute = PmsAttribute.builder().id(item.getId()).categoryId(categoryId).type(type).name(item.getName()).build();
|
||||
attributeList.add(attribute);
|
||||
});
|
||||
boolean result = this.saveOrUpdateBatch(attributeList);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.mapper.PmsCategoryBrandMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategoryBrand;
|
||||
import com.youlai.mall.pms.service.IPmsCategoryBrandService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PmsCategoryBrandServiceImpl extends ServiceImpl<PmsCategoryBrandMapper, PmsCategoryBrand> implements IPmsCategoryBrandService {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -3,7 +3,8 @@ package com.youlai.mall.pms.service.impl;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.web.vo.CascaderVO;
|
||||
import com.youlai.common.constant.GlobalConstants;
|
||||
import com.youlai.common.pojo.vo.CascadeVO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsCategory;
|
||||
import com.youlai.mall.pms.mapper.PmsCategoryMapper;
|
||||
import com.youlai.mall.pms.service.IPmsCategoryService;
|
||||
@ -17,25 +18,28 @@ import java.util.Optional;
|
||||
@Service
|
||||
public class PmsCategoryServiceImpl extends ServiceImpl<PmsCategoryMapper, PmsCategory> implements IPmsCategoryService {
|
||||
|
||||
|
||||
@Override
|
||||
public List<CategoryVO> listForTree(PmsCategory category) {
|
||||
List<PmsCategory> categoryList = this.list(
|
||||
new LambdaQueryWrapper<PmsCategory>()
|
||||
.eq(category.getStatus() != null, PmsCategory::getStatus, category.getStatus())
|
||||
.orderByAsc(PmsCategory::getSort)
|
||||
);
|
||||
|
||||
Long parentId = 0l;
|
||||
|
||||
if (category.getParentId() != null) {
|
||||
parentId = category.getParentId();
|
||||
}
|
||||
|
||||
List<CategoryVO> list = recursionForTreeList(parentId, categoryList);
|
||||
public List<CategoryVO> listTreeCategory(Long parentId) {
|
||||
List<PmsCategory> categoryList = this.list(new LambdaQueryWrapper<PmsCategory>()
|
||||
.eq(PmsCategory::getVisible, GlobalConstants.STATUS_YES).orderByDesc(PmsCategory::getSort));
|
||||
List<CategoryVO> list = recursionTree(parentId != null ? parentId : 0l, categoryList);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<CategoryVO> recursionForTreeList(Long parentId, List<PmsCategory> categoryList) {
|
||||
@Override
|
||||
public List<CascadeVO> listCascadeCategory() {
|
||||
List<PmsCategory> categoryList = this.list(
|
||||
new LambdaQueryWrapper<PmsCategory>()
|
||||
.eq(PmsCategory::getVisible, GlobalConstants.STATUS_YES)
|
||||
.orderByAsc(PmsCategory::getSort)
|
||||
);
|
||||
List<CascadeVO> list = recursionCascade(0l, categoryList);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static List<CategoryVO> recursionTree(Long parentId, List<PmsCategory> categoryList) {
|
||||
List<CategoryVO> list = new ArrayList<>();
|
||||
Optional.ofNullable(categoryList)
|
||||
.ifPresent(categories ->
|
||||
@ -44,40 +48,31 @@ public class PmsCategoryServiceImpl extends ServiceImpl<PmsCategoryMapper, PmsCa
|
||||
.forEach(category -> {
|
||||
CategoryVO categoryVO = new CategoryVO();
|
||||
BeanUtil.copyProperties(category, categoryVO);
|
||||
List<CategoryVO> children = recursionForTreeList(category.getId(), categoryList);
|
||||
List<CategoryVO> children = recursionTree(category.getId(), categoryList);
|
||||
categoryVO.setChildren(children);
|
||||
list.add(categoryVO);
|
||||
}));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<CascaderVO> listForCascader(PmsCategory category) {
|
||||
List<PmsCategory> categoryList = this.list(
|
||||
new LambdaQueryWrapper<PmsCategory>()
|
||||
.eq(category.getStatus() != null, PmsCategory::getStatus, category.getStatus())
|
||||
);
|
||||
List<CascaderVO> list = recursionForCascaderList(0l, categoryList);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<CascaderVO> recursionForCascaderList(Long parentId, List<PmsCategory> categoryList) {
|
||||
List<CascaderVO> list = new ArrayList<>();
|
||||
private List<CascadeVO> recursionCascade(Long parentId, List<PmsCategory> categoryList) {
|
||||
List<CascadeVO> list = new ArrayList<>();
|
||||
Optional.ofNullable(categoryList)
|
||||
.ifPresent(categories ->
|
||||
categories.stream().filter(category ->
|
||||
category.getParentId().equals(parentId))
|
||||
.forEach(category -> {
|
||||
CascaderVO categoryVO = new CascaderVO()
|
||||
CascadeVO categoryVO = new CascadeVO()
|
||||
.setLabel(category.getName())
|
||||
.setValue(category.getId().toString());
|
||||
BeanUtil.copyProperties(category, categoryVO);
|
||||
List<CascaderVO> children = recursionForCascaderList(category.getId(), categoryList);
|
||||
List<CascadeVO> children = recursionCascade(category.getId(), categoryList);
|
||||
categoryVO.setChildren(children);
|
||||
list.add(categoryVO);
|
||||
})
|
||||
);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.web.exception.BizException;
|
||||
import com.youlai.mall.pms.mapper.PmsSkuMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.LockStockDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import com.youlai.mall.pms.tcc.service.SeataTccSkuService;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
@ -54,7 +54,7 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
*/
|
||||
@GlobalTransactional
|
||||
@Override
|
||||
public boolean lockStock(List<SkuLockDTO> skuLockList) {
|
||||
public boolean lockStock(List<LockStockDTO> skuLockList) {
|
||||
log.info("=======================创建订单,开始锁定商品库存=======================");
|
||||
log.info("锁定商品信息:{}", skuLockList.toString());
|
||||
if (CollectionUtil.isEmpty(skuLockList)) {
|
||||
@ -79,17 +79,17 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
});
|
||||
|
||||
// 锁定失败的商品集合
|
||||
List<SkuLockDTO> unlockSkuList = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList());
|
||||
List<LockStockDTO> unlockSkuList = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(unlockSkuList)) {
|
||||
// 恢复已被锁定的库存
|
||||
List<SkuLockDTO> lockSkuList = skuLockList.stream().filter(SkuLockDTO::getLocked).collect(Collectors.toList());
|
||||
List<LockStockDTO> lockSkuList = skuLockList.stream().filter(LockStockDTO::getLocked).collect(Collectors.toList());
|
||||
lockSkuList.forEach(item ->
|
||||
this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.setSql("locked_stock = locked_stock - " + item.getCount()))
|
||||
);
|
||||
// 提示订单哪些商品库存不足
|
||||
List<Long> ids = unlockSkuList.stream().map(SkuLockDTO::getSkuId).collect(Collectors.toList());
|
||||
List<Long> ids = unlockSkuList.stream().map(LockStockDTO::getSkuId).collect(Collectors.toList());
|
||||
throw new BizException("商品" + ids.toString() + "库存不足");
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
return true;
|
||||
}
|
||||
|
||||
List<SkuLockDTO> skuLockList = JSONUtil.toList(json, SkuLockDTO.class);
|
||||
List<LockStockDTO> skuLockList = JSONUtil.toList(json, LockStockDTO.class);
|
||||
|
||||
skuLockList.forEach(item ->
|
||||
this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
@ -137,7 +137,7 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
return true;
|
||||
}
|
||||
|
||||
List<SkuLockDTO> skuLockList = JSONUtil.toList(json, SkuLockDTO.class);
|
||||
List<LockStockDTO> skuLockList = JSONUtil.toList(json, LockStockDTO.class);
|
||||
|
||||
skuLockList.forEach(item -> {
|
||||
boolean result = this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
|
@ -1,23 +0,0 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.mapper.PmsSpecMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Service
|
||||
public class PmsSpecServiceImpl extends ServiceImpl<PmsSpecMapper, PmsSpec> implements IPmsSpecService {
|
||||
|
||||
@Override
|
||||
public List<PmsSpec> listBySpuId(Long spuId) {
|
||||
List<PmsSpec> list = this.baseMapper.listBySpuId(spuId);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,225 +1,325 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.common.constant.PmsConstants;
|
||||
import com.youlai.mall.pms.common.enums.AttributeTypeEnum;
|
||||
import com.youlai.mall.pms.component.BloomRedisService;
|
||||
import com.youlai.mall.pms.mapper.PmsSpuMapper;
|
||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.*;
|
||||
import com.youlai.mall.pms.service.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import com.youlai.mall.pms.pojo.dto.admin.GoodsFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.pojo.vo.admin.GoodsDetailVO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_REDIS_BLOOM_FILTER;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/08/08
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class PmsSpuServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implements IPmsSpuService {
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
private IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||
private IPmsSpuSpecValueService iPmsSpuSpecValueService;
|
||||
private IPmsSpecService iPmsSpecService;
|
||||
private BloomRedisService bloomRedisService;
|
||||
|
||||
private final IPmsSkuService iPmsSkuService;
|
||||
private final IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||
private final BloomRedisService bloomRedisService;
|
||||
|
||||
/**
|
||||
* 商品分页列表
|
||||
*
|
||||
* @param page
|
||||
* @param name
|
||||
* @param categoryId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public IPage<PmsSpu> list(Page<PmsSpu> page, PmsSpu spu) {
|
||||
List<PmsSpu> list = this.baseMapper.list(page, spu);
|
||||
public IPage<PmsSpu> list(Page<PmsSpu> page, String name, Long categoryId) {
|
||||
List<PmsSpu> list = this.baseMapper.list(page, name, categoryId);
|
||||
page.setRecords(list);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品
|
||||
*
|
||||
* @param goods
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean add(ProductFormDTO productFormDTO) {
|
||||
SpuDTO SpuDTO = productFormDTO.getSpu();
|
||||
List<PmsSpuAttributeValue> attrValues = productFormDTO.getAttrs();
|
||||
List<PmsSpuSpecValue> specs = productFormDTO.getSpecs();
|
||||
List<PmsSku> skuList = productFormDTO.getSkus();
|
||||
|
||||
// spu保存
|
||||
PmsSpu spu = new PmsSpu();
|
||||
BeanUtil.copyProperties(SpuDTO, spu);
|
||||
if (SpuDTO.getPics() != null) {
|
||||
String picUrls = JSONUtil.toJsonStr(SpuDTO.getPics());
|
||||
spu.setPics(picUrls);
|
||||
}
|
||||
this.save(spu);
|
||||
|
||||
public boolean addGoods(GoodsFormDTO goods) {
|
||||
Long goodsId = this.saveSpu(goods);
|
||||
// 属性保存
|
||||
Optional.ofNullable(attrValues).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
iPmsSpuAttributeValueService.saveBatch(list);
|
||||
});
|
||||
List<GoodsFormDTO.AttributeValue> attrValList = goods.getAttrList();
|
||||
this.saveAttribute(goodsId, attrValList);
|
||||
// 规格保存
|
||||
List<GoodsFormDTO.AttributeValue> specList = goods.getSpecList();
|
||||
Map<String, Long> specTempIdIdMap = this.saveSpecification(goodsId, specList);
|
||||
// SKU保存
|
||||
List<PmsSku> skuList = goods.getSkuList();
|
||||
return this.saveSku(goodsId, skuList, specTempIdIdMap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改商品
|
||||
*
|
||||
* @param goods
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public boolean updateGoods(GoodsFormDTO goods) {
|
||||
|
||||
Long goodsId = goods.getId();
|
||||
// 属性保存
|
||||
List<GoodsFormDTO.AttributeValue> attrValList = goods.getAttrList();
|
||||
this.saveAttribute(goodsId, attrValList);
|
||||
|
||||
// 规格保存
|
||||
Optional.ofNullable(specs).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
iPmsSpuSpecValueService.saveBatch(list);
|
||||
});
|
||||
List<GoodsFormDTO.AttributeValue> specList = goods.getSpecList();
|
||||
Map<String, Long> specTempIdIdMap = this.saveSpecification(goodsId, specList);
|
||||
|
||||
// sku保存
|
||||
Optional.ofNullable(skuList).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
iPmsSkuService.saveBatch(skuList);
|
||||
});
|
||||
bloomRedisService.addByBloomFilter(PRODUCT_REDIS_BLOOM_FILTER, spu.getId() + "");
|
||||
return true;
|
||||
// SKU保存
|
||||
List<PmsSku> skuList = goods.getSkuList();
|
||||
this.saveSku(goodsId, skuList, specTempIdIdMap);
|
||||
|
||||
// SPU
|
||||
boolean saveResult = this.saveSpu(goods) > 0;
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品(SPU)详情
|
||||
*
|
||||
* @param id 商品(SPU)ID
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ProductFormDTO getBySpuId(Long id) {
|
||||
// spu
|
||||
SpuDTO spuDTO = new SpuDTO();
|
||||
public GoodsDetailVO getGoodsById(Long id) {
|
||||
GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
|
||||
|
||||
PmsSpu spu = this.getById(id);
|
||||
BeanUtil.copyProperties(spu, spuDTO);
|
||||
Assert.isTrue(spu != null, "商品不存在");
|
||||
|
||||
if (StrUtil.isNotBlank(spu.getPics())) {
|
||||
// spu专辑图片转换处理 json字符串 -> List
|
||||
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
||||
spuDTO.setPics(pics);
|
||||
BeanUtil.copyProperties(spu, goodsDetailVO);
|
||||
|
||||
// 商品图册JSON字符串转集合
|
||||
String album = spu.getAlbum();
|
||||
if (StrUtil.isNotBlank(album)) {
|
||||
List<String> picUrls = JSONUtil.toList(album, String.class);
|
||||
goodsDetailVO.setSubPicUrls(picUrls);
|
||||
}
|
||||
|
||||
// 属性
|
||||
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.
|
||||
list(new LambdaQueryWrapper<PmsSpuAttributeValue>().eq(PmsSpuAttributeValue::getSpuId, id));
|
||||
// 规格
|
||||
List<PmsSpuSpecValue> specs = iPmsSpuSpecValueService.list(new LambdaQueryWrapper<PmsSpuSpecValue>().eq(PmsSpuSpecValue::getSpuId, id));
|
||||
// sku
|
||||
List<PmsSku> skus = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, id));
|
||||
// 商品属性列表
|
||||
List<PmsSpuAttributeValue> attrList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getSpuId, id)
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue())
|
||||
);
|
||||
goodsDetailVO.setAttrList(attrList);
|
||||
|
||||
// 组合
|
||||
ProductFormDTO productFormDTO = new ProductFormDTO(spuDTO, attrs, specs, skus);
|
||||
return productFormDTO;
|
||||
// 商品规格列表
|
||||
List<PmsSpuAttributeValue> specList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getSpuId, id)
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue())
|
||||
);
|
||||
goodsDetailVO.setSpecList(specList);
|
||||
|
||||
// 商品SKU列表
|
||||
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, id));
|
||||
goodsDetailVO.setSkuList(skuList);
|
||||
return goodsDetailVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量删除商品(SPU)
|
||||
*
|
||||
* @param goodsIds
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean updateById(ProductFormDTO productFormDTO) {
|
||||
SpuDTO SpuDTO = productFormDTO.getSpu();
|
||||
|
||||
List<PmsSpuAttributeValue> attrValues = productFormDTO.getAttrs();
|
||||
List<PmsSpuSpecValue> specs = productFormDTO.getSpecs();
|
||||
List<PmsSku> skuList = productFormDTO.getSkus();
|
||||
|
||||
// spu保存
|
||||
PmsSpu spu = new PmsSpu();
|
||||
BeanUtil.copyProperties(SpuDTO, spu);
|
||||
if (SpuDTO.getPics() != null) {
|
||||
String pics = JSONUtil.toJsonStr(SpuDTO.getPics());
|
||||
spu.setPics(pics);
|
||||
@Transactional
|
||||
public boolean removeByGoodsIds(List<Long> goodsIds) {
|
||||
boolean result = true;
|
||||
for (Long goodsId : goodsIds) {
|
||||
// sku
|
||||
iPmsSkuService.remove(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, goodsId));
|
||||
// 规格
|
||||
iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper<PmsSpuAttributeValue>().eq(PmsSpuAttributeValue::getId, goodsId));
|
||||
// 属性
|
||||
iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper<PmsSpuAttributeValue>().eq(PmsSpuAttributeValue::getSpuId, goodsId));
|
||||
// spu
|
||||
result = this.removeById(goodsId);
|
||||
}
|
||||
this.updateById(spu);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 属性保存
|
||||
Optional.ofNullable(attrValues).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
|
||||
// 删除此次保存删除的
|
||||
List<Long> ids = list.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
List<Long> dbIds = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>().eq(PmsSpuAttributeValue::getSpuId, spu.getId())
|
||||
.select(PmsSpuAttributeValue::getId))
|
||||
.stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
List<Long> removeIds = dbIds.stream().filter(id -> !ids.contains(id)).collect(Collectors.toList());
|
||||
iPmsSpuAttributeValueService.removeByIds(removeIds);
|
||||
/**
|
||||
* 保存商品
|
||||
*
|
||||
* @param goods
|
||||
* @return
|
||||
*/
|
||||
private Long saveSpu(GoodsFormDTO goods) {
|
||||
PmsSpu pmsSpu = new PmsSpu();
|
||||
BeanUtil.copyProperties(goods, pmsSpu);
|
||||
// 商品图册
|
||||
pmsSpu.setAlbum(JSONUtil.toJsonStr(goods.getSubPicUrls()));
|
||||
boolean result = this.saveOrUpdate(pmsSpu);
|
||||
return result ? pmsSpu.getId() : 0;
|
||||
}
|
||||
|
||||
iPmsSpuAttributeValueService.saveOrUpdateBatch(list);
|
||||
});
|
||||
|
||||
// 规格值保存
|
||||
Optional.ofNullable(specs).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
/**
|
||||
* 保存SKU,需要替换提交表单中的临时规格ID
|
||||
*
|
||||
* @param goodsId
|
||||
* @param skuList
|
||||
* @param specTempIdIdMap
|
||||
* @return
|
||||
*/
|
||||
private boolean saveSku(Long goodsId, List<PmsSku> skuList, Map<String, Long> specTempIdIdMap) {
|
||||
|
||||
// 删除此次保存删除的
|
||||
List<Long> ids = list.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
List<Long> dbIds = iPmsSpuSpecValueService.list(new LambdaQueryWrapper<PmsSpuSpecValue>().eq(PmsSpuSpecValue::getSpuId, spu.getId())
|
||||
.select(PmsSpuSpecValue::getId))
|
||||
.stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
List<Long> removeIds = dbIds.stream().filter(id -> !ids.contains(id)).collect(Collectors.toList());
|
||||
iPmsSpuSpecValueService.removeByIds(removeIds);
|
||||
// 删除SKU
|
||||
List<Long> formSkuIds = skuList.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
|
||||
iPmsSpuSpecValueService.saveOrUpdateBatch(list);
|
||||
});
|
||||
List<Long> dbSkuIds = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>()
|
||||
.eq(PmsSku::getSpuId, goodsId)
|
||||
.select(PmsSku::getId))
|
||||
.stream().map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// sku保存
|
||||
Optional.ofNullable(skuList).ifPresent(list -> {
|
||||
list.forEach(item -> item.setSpuId(spu.getId()));
|
||||
List<Long> removeSkuIds = dbSkuIds.stream().filter(dbSkuId -> !formSkuIds.contains(dbSkuId)).collect(Collectors.toList());
|
||||
|
||||
// 删除此次保存删除的
|
||||
List<Long> ids = list.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
List<Long> dbIds = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spu.getId())
|
||||
.select(PmsSku::getId))
|
||||
.stream()
|
||||
.map(item -> item.getId())
|
||||
.collect(Collectors.toList());
|
||||
List<Long> removeIds = dbIds.stream().filter(id -> !ids.contains(id)).collect(Collectors.toList());
|
||||
iPmsSkuService.removeByIds(removeIds);
|
||||
if (CollectionUtil.isNotEmpty(removeSkuIds)) {
|
||||
iPmsSkuService.removeByIds(removeSkuIds);
|
||||
}
|
||||
|
||||
iPmsSkuService.saveOrUpdateBatch(skuList);
|
||||
});
|
||||
// 新增/修改SKU
|
||||
List<PmsSku> pmsSkuList = skuList.stream().map(sku -> {
|
||||
// 临时规格ID转换
|
||||
String specIds = Arrays.asList(sku.getSpecIds().split("\\|")).stream()
|
||||
.map(specId ->
|
||||
specId.startsWith(PmsConstants.TEMP_ID_PREFIX) ? specTempIdIdMap.get(specId) + "" : specId
|
||||
)
|
||||
.collect(Collectors.joining("_"));
|
||||
sku.setSpecIds(specIds);
|
||||
sku.setSpuId(goodsId);
|
||||
return sku;
|
||||
}).collect(Collectors.toList());
|
||||
return iPmsSkuService.saveOrUpdateBatch(pmsSkuList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存商品属性
|
||||
*
|
||||
* @param goodsId
|
||||
* @param attrValList
|
||||
* @return
|
||||
*/
|
||||
private boolean saveAttribute(Long goodsId, List<GoodsFormDTO.AttributeValue> attrValList) {
|
||||
List<Long> formAttrValIds = attrValList.stream()
|
||||
.filter(item -> item.getId() != null)
|
||||
.map(item -> Convert.toLong(item.getId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> dbAttrValIds = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getSpuId, goodsId)
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue())
|
||||
.select(PmsSpuAttributeValue::getId)
|
||||
).stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
|
||||
List<Long> removeAttrValIds = dbAttrValIds.stream().filter(id -> !formAttrValIds.contains(id)).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(removeAttrValIds)) {
|
||||
iPmsSpuAttributeValueService.removeByIds(removeAttrValIds);
|
||||
}
|
||||
|
||||
// 新增或修改商品属性
|
||||
List<PmsSpuAttributeValue> pmsSpuAttributeValueList = attrValList.stream().map(item -> {
|
||||
PmsSpuAttributeValue pmsSpuAttributeValue = new PmsSpuAttributeValue();
|
||||
BeanUtil.copyProperties(item, pmsSpuAttributeValue);
|
||||
pmsSpuAttributeValue.setSpuId(goodsId);
|
||||
pmsSpuAttributeValue.setType(AttributeTypeEnum.ATTRIBUTE.getValue());
|
||||
return pmsSpuAttributeValue;
|
||||
}).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(pmsSpuAttributeValueList)) {
|
||||
return iPmsSpuAttributeValueService.saveOrUpdateBatch(pmsSpuAttributeValueList);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBySpuIds(List<Long> spuIds) {
|
||||
Optional.ofNullable(spuIds).ifPresent(
|
||||
ids -> ids.forEach(spuId -> {
|
||||
// sku
|
||||
iPmsSkuService.remove(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
||||
// 规格
|
||||
iPmsSpuSpecValueService.remove(new LambdaQueryWrapper<PmsSpuSpecValue>().eq(PmsSpuSpecValue::getId, spuId));
|
||||
// 属性
|
||||
iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper<PmsSpuAttributeValue>().eq(PmsSpuAttributeValue::getSpuId, spuId));
|
||||
// spu
|
||||
this.removeById(spuId);
|
||||
})
|
||||
);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* 保存商品规格,新增的规格需要返回临时ID和持久化到数据库的ID的映射关系,替换SKU中的规格ID集合
|
||||
*
|
||||
* @param goodsId 商品ID
|
||||
* @param specList 规格列表
|
||||
* @return Map: key-临时ID;value-持久化返回ID
|
||||
*/
|
||||
private Map<String, Long> saveSpecification(Long goodsId, List<GoodsFormDTO.AttributeValue> specList) {
|
||||
|
||||
@Override
|
||||
public com.youlai.mall.pms.pojo.dto.app.ProductFormDTO getProductByIdForApp(Long spuId) {
|
||||
// spu
|
||||
PmsSpu spu = this.getById(spuId);
|
||||
SpuDTO SpuDTO = new SpuDTO();
|
||||
BeanUtil.copyProperties(spu, SpuDTO);
|
||||
if (StrUtil.isNotBlank(spu.getPics())) {
|
||||
// spu专辑图片转换处理 json字符串 -> List
|
||||
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
||||
SpuDTO.setPics(pics);
|
||||
// 删除规格
|
||||
List<Long> formSpecValIds = specList.stream()
|
||||
.filter(item -> item.getId() != null && !item.getId().startsWith(PmsConstants.TEMP_ID_PREFIX))
|
||||
.map(item -> Convert.toLong(item.getId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> dbSpecValIds = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getSpuId, goodsId)
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue())
|
||||
.select(PmsSpuAttributeValue::getId)
|
||||
).stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
|
||||
List<Long> removeAttrValIds = dbSpecValIds.stream().filter(id -> !formSpecValIds.contains(id)).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(removeAttrValIds)) {
|
||||
iPmsSpuAttributeValueService.removeByIds(removeAttrValIds);
|
||||
}
|
||||
// 属性
|
||||
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.list(
|
||||
new LambdaQueryWrapper<PmsSpuAttributeValue>(
|
||||
).eq(PmsSpuAttributeValue::getSpuId, spuId)
|
||||
);
|
||||
|
||||
// 规格
|
||||
List<PmsSpec> specs = iPmsSpecService.listBySpuId(spuId);
|
||||
|
||||
// sku
|
||||
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
||||
|
||||
com.youlai.mall.pms.pojo.dto.app.ProductFormDTO product = new com.youlai.mall.pms.pojo.dto.app.ProductFormDTO(SpuDTO, attrs, specs, skuList);
|
||||
return product;
|
||||
// 新增规格
|
||||
Map<String, Long> tempIdIdMap = new HashMap<>();
|
||||
List<GoodsFormDTO.AttributeValue> newSpecList = specList.stream()
|
||||
.filter(item -> item.getId().startsWith(PmsConstants.TEMP_ID_PREFIX)).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(newSpecList)) {
|
||||
newSpecList.forEach(item -> {
|
||||
PmsSpuAttributeValue specification = new PmsSpuAttributeValue();
|
||||
BeanUtil.copyProperties(item, specification, "id");
|
||||
specification.setSpuId(goodsId);
|
||||
specification.setType(AttributeTypeEnum.SPECIFICATION.getValue());
|
||||
iPmsSpuAttributeValueService.save(specification);
|
||||
tempIdIdMap.put(item.getId(), specification.getId());
|
||||
});
|
||||
}
|
||||
// 修改规格
|
||||
List<PmsSpuAttributeValue> pmsSpuAttributeValueList = specList.stream()
|
||||
.filter(item -> !item.getId().startsWith(PmsConstants.TEMP_ID_PREFIX))
|
||||
.map(spec -> {
|
||||
PmsSpuAttributeValue pmsSpuAttributeValue = new PmsSpuAttributeValue();
|
||||
BeanUtil.copyProperties(spec, pmsSpuAttributeValue);
|
||||
pmsSpuAttributeValue.setSpuId(goodsId);
|
||||
pmsSpuAttributeValue.setType(AttributeTypeEnum.SPECIFICATION.getValue());
|
||||
return pmsSpuAttributeValue;
|
||||
}).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(pmsSpuAttributeValueList)) {
|
||||
iPmsSpuAttributeValueService.updateBatchById(pmsSpuAttributeValueList);
|
||||
}
|
||||
return tempIdIdMap;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuSpecValue;
|
||||
import com.youlai.mall.pms.mapper.PmsSpuSpecValueMapper;
|
||||
import com.youlai.mall.pms.service.IPmsSpuSpecValueService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Service
|
||||
public class PmsSpuSpecValueServiceImpl extends ServiceImpl<PmsSpuSpecValueMapper, PmsSpuSpecValue> implements IPmsSpuSpecValueService {
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.youlai.mall.pms.serviceapp;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/8/8
|
||||
*/
|
||||
public interface IGoodsService extends IService<PmsSpu> {
|
||||
GoodsDetailVO getGoodsById(Long id);
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.youlai.mall.pms.serviceapp.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.mall.pms.common.enums.AttributeTypeEnum;
|
||||
import com.youlai.mall.pms.mapper.PmsSpuMapper;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||
import com.youlai.mall.pms.serviceapp.IGoodsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/8/8
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GoodsServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implements IGoodsService {
|
||||
|
||||
final IPmsSpuAttributeValueService spuAttributeValueService;
|
||||
final IPmsSkuService skuService;
|
||||
|
||||
@Override
|
||||
public GoodsDetailVO getGoodsById(Long goodsId) {
|
||||
|
||||
GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
|
||||
PmsSpu pmsSpu = this.baseMapper.selectById(goodsId);
|
||||
Assert.isTrue(pmsSpu != null, "商品不存在");
|
||||
// 商品基本信息
|
||||
GoodsDetailVO.GoodsInfo goodsInfo = new GoodsDetailVO.GoodsInfo();
|
||||
BeanUtil.copyProperties(pmsSpu, goodsInfo, "album");
|
||||
|
||||
List<String> album = new ArrayList<>();
|
||||
|
||||
if (StrUtil.isNotBlank(pmsSpu.getPicUrl())) {
|
||||
album.add(pmsSpu.getPicUrl());
|
||||
}
|
||||
if (StrUtil.isNotBlank(pmsSpu.getAlbum())) {
|
||||
album.addAll(JSONUtil.parseArray(pmsSpu.getAlbum()).toList(String.class));
|
||||
goodsInfo.setAlbum(album);
|
||||
}
|
||||
goodsDetailVO.setGoodsInfo(goodsInfo);
|
||||
|
||||
// 商品属性列表
|
||||
List<GoodsDetailVO.Attribute> attributeList = spuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue())
|
||||
.eq(PmsSpuAttributeValue::getSpuId, goodsId)
|
||||
.select(PmsSpuAttributeValue::getId, PmsSpuAttributeValue::getName, PmsSpuAttributeValue::getValue)
|
||||
).stream().map(item -> {
|
||||
GoodsDetailVO.Attribute attribute = new GoodsDetailVO.Attribute();
|
||||
BeanUtil.copyProperties(item, attribute);
|
||||
return attribute;
|
||||
}).collect(Collectors.toList());
|
||||
goodsDetailVO.setAttributeList(attributeList);
|
||||
|
||||
|
||||
// 商品规格列表
|
||||
List<PmsSpuAttributeValue> specSourceList = spuAttributeValueService.list(new LambdaQueryWrapper<PmsSpuAttributeValue>()
|
||||
.eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue())
|
||||
.eq(PmsSpuAttributeValue::getSpuId, goodsId)
|
||||
.select(PmsSpuAttributeValue::getId, PmsSpuAttributeValue::getName, PmsSpuAttributeValue::getValue)
|
||||
);
|
||||
|
||||
List<GoodsDetailVO.Specification> specList = new ArrayList<>();
|
||||
// 规格Map [key:"颜色",value:[{id:1,value:"黑"},{id:2,value:"白"}]]
|
||||
Map<String, List<PmsSpuAttributeValue>> specValueMap = specSourceList.stream()
|
||||
.collect(Collectors.groupingBy(item -> item.getName()));
|
||||
|
||||
for (Map.Entry<String, List<PmsSpuAttributeValue>> entry : specValueMap.entrySet()) {
|
||||
String specName = entry.getKey();
|
||||
List<PmsSpuAttributeValue> specValueSourceList = entry.getValue();
|
||||
|
||||
// 规格映射处理
|
||||
GoodsDetailVO.Specification spec = new GoodsDetailVO.Specification();
|
||||
spec.setName(specName);
|
||||
if (CollectionUtil.isNotEmpty(specValueSourceList)) {
|
||||
List<GoodsDetailVO.Specification.Value> specValueList = specValueSourceList.stream().map(item -> {
|
||||
GoodsDetailVO.Specification.Value specValue = new GoodsDetailVO.Specification.Value();
|
||||
specValue.setId(item.getId());
|
||||
specValue.setValue(item.getValue());
|
||||
return specValue;
|
||||
}).collect(Collectors.toList());
|
||||
spec.setValues(specValueList);
|
||||
specList.add(spec);
|
||||
}
|
||||
}
|
||||
goodsDetailVO.setSpecList(specList);
|
||||
// 商品SKU列表
|
||||
List<PmsSku> skuSourceList = skuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, goodsId));
|
||||
if (CollectionUtil.isNotEmpty(skuSourceList)) {
|
||||
List<GoodsDetailVO.Sku> skuList = skuSourceList.stream().map(item -> {
|
||||
GoodsDetailVO.Sku sku = new GoodsDetailVO.Sku();
|
||||
BeanUtil.copyProperties(item, sku);
|
||||
return sku;
|
||||
}).collect(Collectors.toList());
|
||||
goodsDetailVO.setSkuList(skuList);
|
||||
}
|
||||
return goodsDetailVO;
|
||||
}
|
||||
}
|
36
mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml
Normal file
36
mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.youlai.mall.pms.mapper.PmsSkuMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.youlai.mall.pms.pojo.entity.PmsSku">
|
||||
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||
<result property="spuId" column="spu_id" jdbcType="BIGINT"/>
|
||||
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||
<result property="sn" column="sn" jdbcType="VARCHAR"/>
|
||||
<result property="picUrl" column="pic_url" jdbcType="VARCHAR"/>
|
||||
<result property="specIds" column="specs" jdbcType="VARCHAR"/>
|
||||
<result property="price" column="price" jdbcType="BIGINT"/>
|
||||
<result property="stock" column="stock" jdbcType="INTEGER"/>
|
||||
<result property="lockedStock" column="locked_stock" jdbcType="INTEGER"/>
|
||||
<result property="gmtCreate" column="gmt_create" jdbcType="TIMESTAMP"/>
|
||||
<result property="gmtModified" column="gmt_modified" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id
|
||||
,spu_id,name,
|
||||
sn,pic_url,specs,
|
||||
origin_price,price,stock,
|
||||
locked_stock,gmt_create,gmt_modified
|
||||
</sql>
|
||||
|
||||
|
||||
<select id="getSkuById" resultType="com.youlai.mall.pms.pojo.dto.app.SkuDTO">
|
||||
select t1.id, t1.sn, t1.name, t1.pic_url, t1.price, (t1.stock - t1.locked_stock) as stock, t2.name as goodsName
|
||||
from pms_sku t1
|
||||
left join pms_spu t2 on t1.spu_id = t2.id
|
||||
where t1.id = #{id}
|
||||
</select>
|
||||
</mapper>
|
92
mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml
Normal file
92
mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.youlai.mall.pms.mapper.PmsSpuMapper">
|
||||
<resultMap id="BaseResultMap" type="com.youlai.mall.pms.pojo.entity.PmsSpu">
|
||||
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||
<result property="categoryId" column="category_id" jdbcType="BIGINT"/>
|
||||
<result property="brandId" column="brand_id" jdbcType="BIGINT"/>
|
||||
<result property="originPrice" column="origin_price" jdbcType="BIGINT"/>
|
||||
<result property="price" column="price" jdbcType="BIGINT"/>
|
||||
<result property="sales" column="sales" jdbcType="INTEGER"/>
|
||||
<result property="picUrl" column="pic_url" jdbcType="VARCHAR"/>
|
||||
<result property="album" column="album" jdbcType="OTHER"/>
|
||||
<result property="unit" column="unit" jdbcType="VARCHAR"/>
|
||||
<result property="description" column="description" jdbcType="VARCHAR"/>
|
||||
<result property="detail" column="detail" jdbcType="VARCHAR"/>
|
||||
<result property="status" column="status" jdbcType="TINYINT"/>
|
||||
<result property="gmtCreate" column="gmt_create" jdbcType="TIMESTAMP"/>
|
||||
<result property="gmtModified" column="gmt_modified" jdbcType="TIMESTAMP"/>
|
||||
<result property="categoryName" column="categoryName" jdbcType="VARCHAR"/>
|
||||
<result property="brandName" column="brandName" jdbcType="VARCHAR"/>
|
||||
<!-- Mybatis Plus 分页有BUG -->
|
||||
<!--<collection property="skuList" ofType="com.youlai.mall.pms.pojo.entity.PmsSku" javaType="list">
|
||||
<id property="id" column="skuId" jdbcType="BIGINT"/>
|
||||
<result property="name" column="skuName" jdbcType="VARCHAR"/>
|
||||
<result property="sn" column="sn" jdbcType="VARCHAR"/>
|
||||
<result property="picUrl" column="skuPicUrl" jdbcType="VARCHAR"/>
|
||||
<result property="specIds" column="specIds" jdbcType="VARCHAR"/>
|
||||
<result property="price" column="skuPrice" jdbcType="BIGINT"/>
|
||||
<result property="stock" column="stock" jdbcType="INTEGER"/>
|
||||
<result property="lockedStock" column="locked_stock" jdbcType="INTEGER"/>
|
||||
</collection>-->
|
||||
<collection property="skuList" column="id" select="getSkuListBySpuId">
|
||||
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||
<result property="sn" column="sn" jdbcType="VARCHAR"/>
|
||||
<result property="picUrl" column="pic_url" jdbcType="VARCHAR"/>
|
||||
<result property="specIds" column="spec_ids" jdbcType="VARCHAR"/>
|
||||
<result property="price" column="price" jdbcType="BIGINT"/>
|
||||
<result property="stock" column="stock" jdbcType="INTEGER"/>
|
||||
<result property="lockedStock" column="locked_stock" jdbcType="INTEGER"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id
|
||||
,name,category_id,
|
||||
brand_id,origin_price,price,
|
||||
sales,pic_url,album,
|
||||
unit,description,detail,
|
||||
status,gmt_create,gmt_modified
|
||||
</sql>
|
||||
<select id="list" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
t1.id,
|
||||
t1.name,
|
||||
t1.pic_url,
|
||||
t1.origin_price,
|
||||
t1.price,
|
||||
t1.sales,
|
||||
t1.unit,
|
||||
t1.detail,
|
||||
t1.description,
|
||||
t3.NAME categoryName,
|
||||
t4.NAME brandName
|
||||
FROM pms_spu t1
|
||||
LEFT JOIN pms_category t3 ON t1.category_id = t3.id
|
||||
LEFT JOIN pms_brand t4 ON t1.brand_id = t4.id
|
||||
WHERE 1 = 1
|
||||
<if test="categoryId!=null">
|
||||
AND t1.category_id =#{categoryId}
|
||||
</if>
|
||||
<if test='name!=null and name neq ""'>
|
||||
AND t1.name like concat('%',#{name},'%')
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getSkuListBySpuId" resultType="com.youlai.mall.pms.pojo.entity.PmsSku">
|
||||
SELECT id ,
|
||||
NAME ,
|
||||
sn,
|
||||
pic_url ,
|
||||
spec_ids,
|
||||
price ,
|
||||
stock
|
||||
FROM pms_sku
|
||||
WHERE spu_id = #{id}
|
||||
</select>
|
||||
</mapper>
|
@ -1,75 +0,0 @@
|
||||
package com.youlai.mall.pms.controller;
|
||||
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import com.youlai.mall.pms.controller.admin.SpuController;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
public class ProductControllerTest {
|
||||
|
||||
@Autowired
|
||||
public MockMvc mockMvc;
|
||||
@Autowired
|
||||
public SpuController spuController;
|
||||
|
||||
|
||||
@Test
|
||||
public void saveGoods() throws Exception {
|
||||
|
||||
String goods = "{\"spu\":{\"name\":\"小米手机10\",\"categoryId\":\"8\",\"brandId\":\"1\",\"originPrice\":599900,\"price\":499900,\"pic\":\"http://101.37.69.49:9000/default/40ffc46040ca431aba23c48798a82bb8.jpg\",\"album\":\"[\\\"http://101.37.69.49:9000/default/dbb1c4e37b6244f3a6b0f635db90bf54.jpg\\\"]\",\"unit\":\"台\",\"description\":\"商品简介\",\"detail\":\"<p>商品详情</p>\",\"status\":1},\"attributes\":[{\"name\":\"上市时间\",\"value\":\"2020-10-10\"}],\"specifications\":[{\"name\":\"颜色\",\"value\":\"黑色\"},{\"name\":\"颜色\",\"value\":\"白色\"},{\"name\":\"内存\",\"value\":\"4G\"},{\"name\":\"内存\",\"value\":\"6G\"},{\"name\":\"存储\",\"value\":\"64G\"},{\"name\":\"存储\",\"value\":\"128G\"}],\"skuList\":[{\"颜色\":\"黑色\",\"内存\":\"4G\",\"存储\":\"64G\",\"price\":401,\"originPrice\":1,\"stock\":2,\"pic\":\"http://101.37.69.49:9000/default/d7c36e289eb14dcea67d20ebcac79d87.jpg\",\"barCode\":\"1605317058485\",\"specification\":\"{\\\"颜色\\\":\\\"黑色\\\",\\\"内存\\\":\\\"4G\\\",\\\"存储\\\":\\\"64G\\\"}\"},{\"颜色\":\"黑色\",\"内存\":\"4G\",\"存储\":\"128G\",\"price\":301,\"originPrice\":1,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/29697a3f43f64172b91b4d1d241ca602.jpg\",\"barCode\":\"1605317059016\",\"specification\":\"{\\\"颜色\\\":\\\"黑色\\\",\\\"内存\\\":\\\"4G\\\",\\\"存储\\\":\\\"128G\\\"}\"},{\"颜色\":\"黑色\",\"内存\":\"6G\",\"存储\":\"64G\",\"price\":200.99999999999997,\"originPrice\":1,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/d4b46f2405b54635bb1c0589f68a74e6.png\",\"barCode\":\"1605317059753\",\"specification\":\"{\\\"颜色\\\":\\\"黑色\\\",\\\"内存\\\":\\\"6G\\\",\\\"存储\\\":\\\"64G\\\"}\"},{\"颜色\":\"黑色\",\"内存\":\"6G\",\"存储\":\"128G\",\"price\":301,\"originPrice\":1,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/432579106d32465296f930d15eafd466.png\",\"barCode\":\"1605317060895\",\"specification\":\"{\\\"颜色\\\":\\\"黑色\\\",\\\"内存\\\":\\\"6G\\\",\\\"存储\\\":\\\"128G\\\"}\"},{\"颜色\":\"白色\",\"内存\":\"4G\",\"存储\":\"64G\",\"price\":200.99999999999997,\"originPrice\":2.01,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/f5eb5e307adf439cb7da0f847f4ddace.png\",\"barCode\":\"1605317061416\",\"specification\":\"{\\\"颜色\\\":\\\"白色\\\",\\\"内存\\\":\\\"4G\\\",\\\"存储\\\":\\\"64G\\\"}\"},{\"颜色\":\"白色\",\"内存\":\"4G\",\"存储\":\"128G\",\"price\":200.99999999999997,\"originPrice\":1.01,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/9de00b77c06245538572c09ad689dfda.jpg\",\"specification\":\"{\\\"颜色\\\":\\\"白色\\\",\\\"内存\\\":\\\"4G\\\",\\\"存储\\\":\\\"128G\\\"}\"},{\"颜色\":\"白色\",\"内存\":\"6G\",\"存储\":\"64G\",\"price\":200.99999999999997,\"originPrice\":1.01,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/d48ac97541f44cea8087b8f26da588c4.jpg\",\"barCode\":\"1605317062900\",\"specification\":\"{\\\"颜色\\\":\\\"白色\\\",\\\"内存\\\":\\\"6G\\\",\\\"存储\\\":\\\"64G\\\"}\"},{\"颜色\":\"白色\",\"内存\":\"6G\",\"存储\":\"128G\",\"price\":301,\"originPrice\":0.01,\"stock\":1,\"pic\":\"http://101.37.69.49:9000/default/9b2a4dfae67b44b89cc9589de691ee8d.jpg\",\"barCode\":\"1605317063290\",\"specification\":\"{\\\"颜色\\\":\\\"白色\\\",\\\"内存\\\":\\\"6G\\\",\\\"存储\\\":\\\"128G\\\"}\"}]}";
|
||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/goods")
|
||||
.contentType("application/json")
|
||||
.content(goods))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(ResultCode.SUCCESS.getCode()))
|
||||
.andDo(print())
|
||||
.andReturn();
|
||||
|
||||
log.info(result.getResponse().getContentAsString());
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public IPmsSpecService iPmsSpecService;
|
||||
|
||||
@Test
|
||||
public void getProductSpecList() {
|
||||
List<PmsSpec> specifications = iPmsSpecService.listBySpuId(1l);
|
||||
log.info(specifications.toString());
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||
|
||||
|
||||
|
||||
@Autowired
|
||||
private IPmsSpuService iPmsSpuService;
|
||||
|
||||
@Test
|
||||
public void getProduct() {
|
||||
ProductFormDTO product = iPmsSpuService.getProductByIdForApp(1l);
|
||||
log.info(product.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import com.youlai.mall.pms.pojo.vo.admin.GoodsDetailVO;
|
||||
import com.youlai.mall.pms.service.IPmsSpuService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/7/17
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
class PmsSpuServiceImplTest {
|
||||
|
||||
@Autowired
|
||||
private IPmsSpuService iPmsSpuService;
|
||||
|
||||
@Test
|
||||
void getGoodsById() {
|
||||
GoodsDetailVO goodsDetail = iPmsSpuService.getGoodsById(1l);
|
||||
log.info(goodsDetail.toString());
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.youlai.mall.sms.pojo.to;
|
||||
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.youlai.mall.sms.pojo.vo;
|
||||
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.SkuDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
@ -24,17 +24,12 @@ public class SysMenu extends BaseEntity {
|
||||
|
||||
private String name;
|
||||
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 路由名称
|
||||
*/
|
||||
private String routeName;
|
||||
private String iconUrl;
|
||||
|
||||
/**
|
||||
* 路由路径
|
||||
*/
|
||||
private String routePath;
|
||||
private String path;
|
||||
|
||||
private String component;
|
||||
|
||||
|
@ -6,9 +6,8 @@ import lombok.Setter;
|
||||
/**
|
||||
* 权限类型
|
||||
*
|
||||
* @Author haoxr
|
||||
* @Date 2021-02-05 10:10
|
||||
* @Version 1.0.0
|
||||
* @author xianrui
|
||||
* @date 2021-02-05
|
||||
*/
|
||||
|
||||
public enum PermTypeEnum {
|
||||
|
@ -3,7 +3,7 @@ package com.youlai.admin.common.util;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.nimbusds.jose.JWSObject;
|
||||
import com.youlai.common.constant.AuthConstants;
|
||||
import com.youlai.common.domain.JWTPayload;
|
||||
import com.youlai.common.pojo.JwtPayload;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
@ -20,10 +20,10 @@ public class JWTUtils {
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static JWTPayload getJWTPayload(String token) {
|
||||
public static JwtPayload getJWTPayload(String token) {
|
||||
token = token.replace(AuthConstants.AUTHORIZATION_PREFIX, Strings.EMPTY);
|
||||
JWSObject jwsObject = JWSObject.parse(token);
|
||||
JWTPayload payload = JSONUtil.toBean(jwsObject.getPayload().toString(), JWTPayload.class);
|
||||
JwtPayload payload = JSONUtil.toBean(jwsObject.getPayload().toString(), JwtPayload.class);
|
||||
return payload;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ public class JWTUtils {
|
||||
* @return
|
||||
*/
|
||||
public static boolean isExpired(String token) {
|
||||
JWTPayload payload = getJWTPayload(token);
|
||||
JwtPayload payload = getJWTPayload(token);
|
||||
// 计算是否过期
|
||||
long currentTimeSeconds = System.currentTimeMillis() / 1000;
|
||||
Long exp = payload.getExp();
|
||||
|
@ -20,7 +20,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @author xianrui
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Api(tags = "菜单接口")
|
||||
|
@ -14,9 +14,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @description TODO
|
||||
* @createTime 2021/6/1 22:40
|
||||
* @author xianrui
|
||||
* @date 2021/6/1 22:40
|
||||
*/
|
||||
@Api(tags = "路由接口")
|
||||
@RestController
|
||||
|
@ -20,8 +20,8 @@ import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* @Author haoxr
|
||||
* @Date 2020-11-06
|
||||
* @author xianrui
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Service
|
||||
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {
|
||||
@ -107,17 +107,13 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
|
||||
RouteVO routeVO = new RouteVO();
|
||||
|
||||
routeVO.setName(menu.getId() + ""); // 根据name路由跳转 this.$router.push({path:xxx})
|
||||
routeVO.setPath(menu.getRoutePath()); // 根据path路由跳转 this.$router.push({name:xxx})
|
||||
|
||||
if (SystemConstants.ROOT_MENU_ID.equals(parentId)) {
|
||||
routeVO.setComponent("Layout");
|
||||
} else {
|
||||
routeVO.setComponent(menu.getComponent());
|
||||
}
|
||||
routeVO.setPath(menu.getPath()); // 根据path路由跳转 this.$router.push({name:xxx})
|
||||
routeVO.setRedirect(menu.getRedirect());
|
||||
routeVO.setComponent(menu.getComponent());
|
||||
routeVO.setRedirect(menu.getRedirect());
|
||||
routeVO.setMeta(routeVO.new Meta(
|
||||
menu.getName(),
|
||||
menu.getIcon(),
|
||||
menu.getIconUrl(),
|
||||
menu.getRoles()
|
||||
));
|
||||
// 菜单显示隐藏
|
||||
|
@ -4,7 +4,7 @@ package com.youlai.admin.service.impl;
|
||||
import com.youlai.admin.common.util.JWTUtils;
|
||||
import com.youlai.admin.service.ITokenService;
|
||||
import com.youlai.common.constant.AuthConstants;
|
||||
import com.youlai.common.domain.JWTPayload;
|
||||
import com.youlai.common.pojo.JwtPayload;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
@ -27,7 +27,7 @@ public class TokenServiceImpl implements ITokenService {
|
||||
@SneakyThrows
|
||||
public boolean invalidateToken(String token) {
|
||||
|
||||
JWTPayload payload = JWTUtils.getJWTPayload(token);
|
||||
JwtPayload payload = JWTUtils.getJWTPayload(token);
|
||||
|
||||
// 计算是否过期
|
||||
long currentTimeSeconds = System.currentTimeMillis() / 1000;
|
||||
@ -42,7 +42,7 @@ public class TokenServiceImpl implements ITokenService {
|
||||
|
||||
@Override
|
||||
public int getTokenStatus(String token) {
|
||||
JWTPayload payload = JWTUtils.getJWTPayload(token);
|
||||
JwtPayload payload = JWTUtils.getJWTPayload(token);
|
||||
|
||||
// 计算是否过期
|
||||
long currentTimeSeconds = System.currentTimeMillis() / 1000;
|
||||
|
@ -7,11 +7,10 @@
|
||||
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||
<result property="parentId" column="parent_id" jdbcType="BIGINT"/>
|
||||
<result property="routeName" column="route_name" jdbcType="VARCHAR"/>
|
||||
<result property="routePath" column="route_path" jdbcType="VARCHAR"/>
|
||||
<result property="path" column="path" jdbcType="VARCHAR"/>
|
||||
<result property="component" column="component" jdbcType="VARCHAR"/>
|
||||
<result property="redirect" column="redirect" jdbcType="VARCHAR"/>
|
||||
<result property="icon" column="icon" jdbcType="VARCHAR"/>
|
||||
<result property="iconUrl" column="icon_url" jdbcType="VARCHAR"/>
|
||||
<result property="sort" column="sort" jdbcType="INTEGER"/>
|
||||
<result property="visible" column="visible" jdbcType="BOOLEAN"/>
|
||||
<result property="gmtCreate" column="gmt_create" jdbcType="TIMESTAMP"/>
|
||||
@ -33,10 +32,9 @@
|
||||
select t1.id,
|
||||
t1.name,
|
||||
t1.parent_id,
|
||||
t1.route_name,
|
||||
t1.route_path,
|
||||
t1.path,
|
||||
t1.component,
|
||||
t1.icon,
|
||||
t1.icon_url,
|
||||
t1.sort,
|
||||
t1.visible,
|
||||
t1.redirect,
|
||||
|
@ -1,13 +1,15 @@
|
||||
package com.youlai.common.domain;
|
||||
package com.youlai.common.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* JWT载体
|
||||
*
|
||||
* @author hxr
|
||||
* @date 2021-03-10
|
||||
*/
|
||||
@Data
|
||||
public class JWTPayload {
|
||||
public class JwtPayload {
|
||||
|
||||
private String jti;
|
||||
|
@ -1,18 +1,21 @@
|
||||
package com.youlai.common.web.vo;
|
||||
package com.youlai.common.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 级联试图对象
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CascaderVO {
|
||||
public class CascadeVO {
|
||||
|
||||
private String value;
|
||||
|
||||
private String label;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private List<CascaderVO> children;
|
||||
private List<CascadeVO> children;
|
||||
}
|
@ -2,7 +2,6 @@ package com.youlai.common.result;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-06-23
|
||||
**/
|
||||
public interface IResultCode {
|
||||
|
||||
|
@ -1,16 +1,17 @@
|
||||
package com.youlai.common.result;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-06-23
|
||||
**/
|
||||
@Data
|
||||
// 忽略null值
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
@ -43,6 +44,8 @@ public class Result<T> implements Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> Result<T> failed() {
|
||||
return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), ResultCode.SYSTEM_EXECUTION_ERROR.getMsg(), null);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.youlai.common.result;
|
||||
|
||||
import com.youlai.common.enums.QueryModeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
@ -10,8 +10,11 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
@EnableTransactionManagement
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
|
@ -13,15 +13,13 @@ public class FieldFillHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
|
||||
this.setFieldValByName("gmtCreate", new Date(), metaObject);
|
||||
this.setFieldValByName("gmtModified", new Date(), metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
this.setFieldValByName("gmtModified", new Date(), metaObject);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,8 @@ public class RedissonConfig {
|
||||
singleServerConfig
|
||||
//可以用"rediss://"来启用SSL连接
|
||||
.setAddress(properties.getServerAddress() + ":" + properties.getPort())
|
||||
.setPassword(properties.getPassword());
|
||||
// .setPassword(properties.getPassword())
|
||||
;
|
||||
RedissonClient redisson = Redisson.create(config);
|
||||
return redisson;
|
||||
}
|
||||
|
@ -17,6 +17,11 @@
|
||||
<artifactId>common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
@ -93,7 +93,6 @@ public class ResourceServerConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link https://blog.csdn.net/qq_24230139/article/details/105091273
|
||||
* ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
|
||||
* 需要把jwt的Claim中的authorities加入
|
||||
|
@ -83,7 +83,6 @@ public class ResourceServerManager implements ReactiveAuthorizationManager<Autho
|
||||
urlPermRolesRules = redisTemplate.opsForHash().entries(GlobalConstants.URL_PERM_ROLES_KEY);
|
||||
}
|
||||
|
||||
|
||||
// 根据请求路径判断有访问权限的角色列表
|
||||
List<String> authorizedRoles = new ArrayList<>(); // 拥有访问权限的角色
|
||||
boolean requireCheck = false; // 是否需要鉴权,默认“没有设置权限规则”不用鉴权
|
||||
|
Loading…
Reference in New Issue
Block a user