47 changed files with 1509 additions and 203 deletions
@ -0,0 +1,33 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.core.base; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@ApiModel |
|||
public class HiverBasePageQuery { |
|||
@ApiModelProperty(value = "页码", example = "1") |
|||
private int pageNum = 1; |
|||
|
|||
@ApiModelProperty(value = "每页记录数", example = "10") |
|||
private int pageSize = 10; |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.dao; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
|
|||
public interface GoodsAttributeDao extends HiverBaseDao<GoodsAttribute, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.dao; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
|
|||
public interface GoodsCategoryAttributeDao extends HiverBaseDao<GoodsCategoryAttribute, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.dao; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
|
|||
public interface GoodsCategoryBrandDao extends HiverBaseDao<GoodsCategoryBrand, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.dao; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.entity.Goods; |
|||
|
|||
public interface GoodsDao extends HiverBaseDao<Goods, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.dao; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
|
|||
public interface GoodsStockDao extends HiverBaseDao<GoodsStock, String> { |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Mapper |
|||
public interface GoodsAttributeMapper extends BaseMapper<GoodsAttribute> { |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Mapper |
|||
public interface GoodsCategoryAttributeMapper extends BaseMapper<GoodsCategoryAttribute> { |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Mapper |
|||
public interface GoodsCategoryBrandMapper extends BaseMapper<GoodsCategoryBrand> { |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.Goods; |
|||
import cc.hiver.mall.pojo.query.GoodsPageQuery; |
|||
import cc.hiver.mall.pojo.vo.GoodsPageVO; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Mapper |
|||
public interface GoodsMapper extends BaseMapper<Goods> { |
|||
/** |
|||
* 商品分页列表 |
|||
* |
|||
* @param page |
|||
* @param queryParams |
|||
* @return |
|||
*/ |
|||
List<GoodsPageVO> listGoodsPages(Page<GoodsPageVO> page, GoodsPageQuery queryParams); |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import cc.hiver.mall.pojo.dto.GoodsStockDto; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Mapper |
|||
public interface GoodsStockMapper extends BaseMapper<GoodsStock> { |
|||
/** |
|||
* 获取商品库存单元信息 |
|||
* |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
GoodsStockDto getStockInfo(String id); |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.dto; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.ToString; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
@ToString |
|||
public class CheckPriceDTO { |
|||
/** |
|||
* 订单编号 |
|||
*/ |
|||
private String orderSn; |
|||
|
|||
/** |
|||
* 订单总金额 |
|||
*/ |
|||
private BigDecimal orderTotalAmount; |
|||
|
|||
/** |
|||
* 订单商品明细 |
|||
*/ |
|||
private List<OrderSku> orderSkus; |
|||
|
|||
/** |
|||
* 订单商品对象 |
|||
*/ |
|||
@Data |
|||
@AllArgsConstructor |
|||
@NoArgsConstructor |
|||
public static class OrderSku { |
|||
/** |
|||
* 商品ID |
|||
*/ |
|||
private String goodsId; |
|||
|
|||
/** |
|||
* 商品数量 |
|||
*/ |
|||
private Integer count; |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.dto; |
|||
|
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import javax.persistence.Column; |
|||
import java.math.BigDecimal; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
public class GoodsStockDto { |
|||
@ApiModelProperty(value = "序号") |
|||
private String id; |
|||
|
|||
@ApiModelProperty(value = "库存编码") |
|||
private String sn; |
|||
|
|||
@ApiModelProperty(value = "库存名称") |
|||
private String name; |
|||
|
|||
@ApiModelProperty(value = "商品名称") |
|||
private String goodsName; |
|||
|
|||
@ApiModelProperty(value = "采购价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal purchasePrice; |
|||
|
|||
@ApiModelProperty(value = "市场价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal price; |
|||
|
|||
@ApiModelProperty(value = "批发价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal wholesalePrice; |
|||
|
|||
@ApiModelProperty(value = "库存数量") |
|||
private Integer stock = 0; |
|||
|
|||
@ApiModelProperty(value = "商品图片") |
|||
private String picUrl; |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.dto; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.ToString; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@ToString |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class LockStockDTO { |
|||
/** |
|||
* 订单编号 |
|||
*/ |
|||
private String orderSn; |
|||
|
|||
/** |
|||
* 锁定商品集合 |
|||
*/ |
|||
private List<LockedStock> lockedStocks; |
|||
|
|||
@Data |
|||
@AllArgsConstructor |
|||
@NoArgsConstructor |
|||
public static class LockedStock { |
|||
/** |
|||
* 锁定商品ID |
|||
*/ |
|||
private String goodsId; |
|||
|
|||
/** |
|||
* 商品数量 |
|||
*/ |
|||
private Integer count; |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.form; |
|||
|
|||
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; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@ApiModel("属性表单") |
|||
public class GoodsCategoryAttributeForm { |
|||
@ApiModelProperty("分类ID") |
|||
@NotNull |
|||
private String categoryId; |
|||
|
|||
@ApiModelProperty("属性类型(1:规格;2:属性)") |
|||
@NotNull |
|||
private Integer type; |
|||
|
|||
@ApiModelProperty("属性集合") |
|||
@NotEmpty |
|||
private List<Attribute> attributes; |
|||
|
|||
@Data |
|||
public static class Attribute { |
|||
@ApiModelProperty("属性ID") |
|||
private String id; |
|||
|
|||
@ApiModelProperty("属性名称") |
|||
@NotBlank |
|||
private String name; |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.form; |
|||
|
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import javax.persistence.Column; |
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
public class GoodsForm { |
|||
@ApiModelProperty(value = "序号") |
|||
private String id; |
|||
|
|||
@ApiModelProperty(value = "商品名称") |
|||
private String name; |
|||
|
|||
@ApiModelProperty(value = "商品类型ID") |
|||
private String categoryId; |
|||
|
|||
@ApiModelProperty(value = "商品品牌ID") |
|||
private String brandId; |
|||
|
|||
@ApiModelProperty(value = "采购价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal purchasePrice; |
|||
|
|||
@ApiModelProperty(value = "市场价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal price; |
|||
|
|||
@ApiModelProperty(value = "批发价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal wholesalePrice; |
|||
|
|||
@ApiModelProperty(value = "商品主图") |
|||
private String picUrl; |
|||
|
|||
@ApiModelProperty("商品副图") |
|||
private String[] subPicUrls; |
|||
|
|||
@ApiModelProperty(value = "视频地址") |
|||
private String videoUrl; |
|||
|
|||
@ApiModelProperty(value = "商品简介") |
|||
private String description; |
|||
|
|||
@ApiModelProperty(value = "商品详情") |
|||
private String detail; |
|||
|
|||
@ApiModelProperty(value = "是否启用 0上架 -1下架") |
|||
private Integer status; |
|||
|
|||
@ApiModelProperty(value = "属性列表") |
|||
private List<GoodsAttribute> attrList; |
|||
|
|||
@ApiModelProperty(value = "规格列表") |
|||
private List<GoodsAttribute> specList; |
|||
|
|||
@ApiModelProperty(value = "库存列表") |
|||
private List<GoodsStock> goodsStockList; |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.query; |
|||
|
|||
import cc.hiver.core.base.HiverBasePageQuery; |
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@ApiModel("商品分页查询对象") |
|||
@Data |
|||
public class GoodsPageQuery extends HiverBasePageQuery { |
|||
@ApiModelProperty("关键字") |
|||
private String keywords; |
|||
|
|||
@ApiModelProperty("商品分类ID") |
|||
private Long categoryId; |
|||
|
|||
@ApiModelProperty("排序字段名") |
|||
private String sortField; |
|||
|
|||
@ApiModelProperty("排序规则(asc:升序;desc:降序)") |
|||
private String sort; |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.vo; |
|||
|
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import javax.persistence.Column; |
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@ApiModel("商品详情视图对象") |
|||
public class GoodsDetailVO { |
|||
@ApiModelProperty(value = "序号") |
|||
private String id; |
|||
|
|||
@ApiModelProperty(value = "商品名称") |
|||
private String name; |
|||
|
|||
@ApiModelProperty(value = "商品类型ID") |
|||
private String categoryId; |
|||
|
|||
@ApiModelProperty(value = "商品品牌ID") |
|||
private String brandId; |
|||
|
|||
@ApiModelProperty(value = "采购价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal purchasePrice; |
|||
|
|||
@ApiModelProperty(value = "市场价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal price; |
|||
|
|||
@ApiModelProperty(value = "批发价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal wholesalePrice; |
|||
|
|||
@ApiModelProperty(value = "商品主图") |
|||
private String picUrl; |
|||
|
|||
@ApiModelProperty("商品副图") |
|||
private String[] subPicUrls; |
|||
|
|||
@ApiModelProperty(value = "视频地址") |
|||
private String videoUrl; |
|||
|
|||
@ApiModelProperty(value = "商品简介") |
|||
private String description; |
|||
|
|||
@ApiModelProperty(value = "商品详情") |
|||
private String detail; |
|||
|
|||
@ApiModelProperty(value = "是否启用 0上架 -1下架") |
|||
private Integer status; |
|||
|
|||
@ApiModelProperty(value = "属性列表") |
|||
private List<GoodsAttribute> attrList; |
|||
|
|||
@ApiModelProperty(value = "规格列表") |
|||
private List<GoodsAttribute> specList; |
|||
|
|||
@ApiModelProperty(value = "库存列表") |
|||
private List<GoodsStock> goodsStockList; |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.pojo.vo; |
|||
|
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
import javax.persistence.Column; |
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class GoodsPageVO { |
|||
@ApiModelProperty(value = "序号") |
|||
private String id; |
|||
|
|||
@ApiModelProperty(value = "商品名称") |
|||
private String name; |
|||
|
|||
@ApiModelProperty(value = "商品类型ID") |
|||
private String categoryId; |
|||
|
|||
@ApiModelProperty(value = "商品品牌ID") |
|||
private String brandId; |
|||
|
|||
@ApiModelProperty(value = "采购价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal purchasePrice; |
|||
|
|||
@ApiModelProperty(value = "市场价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal price; |
|||
|
|||
@ApiModelProperty(value = "批发价") |
|||
@Column(precision = 10, scale = 2) |
|||
private BigDecimal wholesalePrice; |
|||
|
|||
@ApiModelProperty(value = "销量") |
|||
private Integer sales; |
|||
|
|||
@ApiModelProperty(value = "商品主图") |
|||
private String picUrl; |
|||
|
|||
@ApiModelProperty(value = "视频地址") |
|||
private String videoUrl; |
|||
|
|||
@ApiModelProperty(value = "商品图册") |
|||
private String album; |
|||
|
|||
@ApiModelProperty(value = "单位") |
|||
private String unit; |
|||
|
|||
@ApiModelProperty(value = "商品简介") |
|||
private String description; |
|||
|
|||
@ApiModelProperty(value = "商品详情") |
|||
private String detail; |
|||
|
|||
@ApiModelProperty(value = "是否启用 0上架 -1下架") |
|||
private Integer status; |
|||
|
|||
@ApiModelProperty(value = "分类名称") |
|||
private String categoryName; |
|||
|
|||
@ApiModelProperty(value = "品牌名称") |
|||
private String brandName; |
|||
|
|||
@ApiModelProperty(value = "库存列表") |
|||
private List<GoodsStock> goodsStockList; |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.service; |
|||
|
|||
import cc.hiver.core.base.HiverBaseService; |
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
|
|||
public interface GoodsAttributeService extends HiverBaseService<GoodsAttribute, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.service; |
|||
|
|||
import cc.hiver.core.base.HiverBaseService; |
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
|
|||
public interface GoodsCategoryAttributeService extends HiverBaseService<GoodsCategoryAttribute, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.service; |
|||
|
|||
import cc.hiver.core.base.HiverBaseService; |
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
|
|||
public interface GoodsCategoryBrandService extends HiverBaseService<GoodsCategoryBrand, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.service; |
|||
|
|||
import cc.hiver.core.base.HiverBaseService; |
|||
import cc.hiver.mall.entity.Goods; |
|||
|
|||
public interface GoodsService extends HiverBaseService<Goods, String> { |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
package cc.hiver.mall.service; |
|||
|
|||
import cc.hiver.core.base.HiverBaseService; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
|
|||
public interface GoodsStockService extends HiverBaseService<GoodsStock, String> { |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
package cc.hiver.mall.service.mybatis; |
|||
|
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
|
|||
public interface GoodsAttributeService extends IService<GoodsAttribute> { |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
package cc.hiver.mall.service.mybatis; |
|||
|
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
import cc.hiver.mall.pojo.form.GoodsCategoryAttributeForm; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
|
|||
public interface GoodsCategoryAttributeService extends IService<GoodsCategoryAttribute> { |
|||
boolean saveBatch(GoodsCategoryAttributeForm formData); |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
package cc.hiver.mall.service.mybatis; |
|||
|
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
|
|||
public interface GoodsCategoryBrandService extends IService<GoodsCategoryBrand> { |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.service.mybatis; |
|||
|
|||
import cc.hiver.mall.entity.Goods; |
|||
import cc.hiver.mall.pojo.form.GoodsForm; |
|||
import cc.hiver.mall.pojo.query.GoodsPageQuery; |
|||
import cc.hiver.mall.pojo.vo.GoodsDetailVO; |
|||
import cc.hiver.mall.pojo.vo.GoodsPageVO; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
public interface GoodsService extends IService<Goods> { |
|||
/** |
|||
* 「管理端」商品分页列表 |
|||
* |
|||
* @param queryParams |
|||
* @return |
|||
*/ |
|||
IPage<GoodsPageVO> listGoodsPages(GoodsPageQuery queryParams); |
|||
|
|||
/** |
|||
* 「管理端」获取商品详情 |
|||
* |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
GoodsDetailVO getGoodsDetail(String id); |
|||
|
|||
/** |
|||
* 新增商品 |
|||
* |
|||
* @param formData |
|||
* @return |
|||
*/ |
|||
boolean addGoods(GoodsForm formData); |
|||
|
|||
/** |
|||
* 修改商品 |
|||
* |
|||
* @param formData |
|||
* @return |
|||
*/ |
|||
boolean updateGoods(GoodsForm formData); |
|||
|
|||
/** |
|||
* 删除商品 |
|||
* |
|||
* @param ids 商品ID,多个以英文逗号(,)分割 |
|||
* @return |
|||
*/ |
|||
boolean removeByGoodsIds(String[] ids); |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
package cc.hiver.mall.service.mybatis; |
|||
|
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import cc.hiver.mall.pojo.dto.CheckPriceDTO; |
|||
import cc.hiver.mall.pojo.dto.GoodsStockDto; |
|||
import cc.hiver.mall.pojo.dto.LockStockDTO; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
|
|||
public interface GoodsStockService extends IService<GoodsStock> { |
|||
/** |
|||
* 获取商品的库存数量 |
|||
* |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
Integer getStockNum(String id); |
|||
|
|||
/** |
|||
* 获取商品库存信息 |
|||
* |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
GoodsStockDto getStockInfo(String id); |
|||
|
|||
/** |
|||
* 锁定库存 |
|||
*/ |
|||
boolean lockStock(LockStockDTO lockStockDTO); |
|||
|
|||
/** |
|||
* 解锁库存 |
|||
*/ |
|||
boolean unlockStock(String orderSn); |
|||
|
|||
/** |
|||
* 扣减库存 |
|||
*/ |
|||
boolean deductStock(String orderSn); |
|||
|
|||
/** |
|||
* 商品验价 |
|||
* |
|||
* @param checkPriceDTO |
|||
* @return |
|||
*/ |
|||
boolean checkPrice(CheckPriceDTO checkPriceDTO); |
|||
|
|||
/** |
|||
* 修改商品库存数量 |
|||
* |
|||
* @param id |
|||
* @param stockNum 商品库存数量 |
|||
* @return |
|||
*/ |
|||
boolean updateStockNum(String id, Integer stockNum); |
|||
|
|||
/** |
|||
* 扣减商品库存 |
|||
* |
|||
* @param id |
|||
* @param num 商品库存数量 |
|||
* @return |
|||
*/ |
|||
boolean deductStock(String id, Integer num); |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
package cc.hiver.mall.serviceimpl; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.dao.GoodsAttributeDao; |
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import cc.hiver.mall.service.GoodsAttributeService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@Transactional |
|||
public class GoodsAttributeServiceImpl implements GoodsAttributeService { |
|||
@Autowired |
|||
private GoodsAttributeDao goodsAttributeDao; |
|||
|
|||
@Override |
|||
public HiverBaseDao<GoodsAttribute, String> getRepository() { |
|||
return goodsAttributeDao; |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
package cc.hiver.mall.serviceimpl; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.dao.GoodsCategoryAttributeDao; |
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
import cc.hiver.mall.service.GoodsCategoryAttributeService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@Transactional |
|||
public class GoodsCategoryAttributeServiceImpl implements GoodsCategoryAttributeService { |
|||
@Autowired |
|||
private GoodsCategoryAttributeDao goodsCategoryAttributeDao; |
|||
|
|||
@Override |
|||
public HiverBaseDao<GoodsCategoryAttribute, String> getRepository() { |
|||
return goodsCategoryAttributeDao; |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
package cc.hiver.mall.serviceimpl; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.dao.GoodsCategoryBrandDao; |
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
import cc.hiver.mall.service.GoodsCategoryBrandService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@Transactional |
|||
public class GoodsCategoryBrandServiceImpl implements GoodsCategoryBrandService { |
|||
@Autowired |
|||
private GoodsCategoryBrandDao goodsCategoryBrandDao; |
|||
|
|||
@Override |
|||
public HiverBaseDao<GoodsCategoryBrand, String> getRepository() { |
|||
return goodsCategoryBrandDao; |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
package cc.hiver.mall.serviceimpl; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.dao.GoodsDao; |
|||
import cc.hiver.mall.entity.Goods; |
|||
import cc.hiver.mall.service.GoodsService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@Transactional |
|||
public class GoodsServiceImpl implements GoodsService { |
|||
@Autowired |
|||
private GoodsDao goodsDao; |
|||
|
|||
@Override |
|||
public HiverBaseDao<Goods, String> getRepository() { |
|||
return goodsDao; |
|||
} |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
package cc.hiver.mall.serviceimpl; |
|||
|
|||
import cc.hiver.core.base.HiverBaseDao; |
|||
import cc.hiver.mall.dao.GoodsStockDao; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import cc.hiver.mall.service.GoodsStockService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@Transactional |
|||
public class GoodsStockServiceImpl implements GoodsStockService { |
|||
@Autowired |
|||
private GoodsStockDao goodsStockDao; |
|||
|
|||
@Override |
|||
public HiverBaseDao<GoodsStock, String> getRepository() { |
|||
return goodsStockDao; |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
package cc.hiver.mall.serviceimpl.mybatis; |
|||
|
|||
import cc.hiver.mall.dao.mapper.GoodsAttributeMapper; |
|||
import cc.hiver.mall.entity.GoodsAttribute; |
|||
import cc.hiver.mall.service.mybatis.GoodsAttributeService; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
public class GoodsAttributeServiceImpl extends ServiceImpl<GoodsAttributeMapper, GoodsAttribute> implements GoodsAttributeService { |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
package cc.hiver.mall.serviceimpl.mybatis; |
|||
|
|||
import cc.hiver.mall.dao.mapper.GoodsCategoryAttributeMapper; |
|||
import cc.hiver.mall.entity.GoodsCategoryAttribute; |
|||
import cc.hiver.mall.pojo.form.GoodsCategoryAttributeForm; |
|||
import cc.hiver.mall.service.mybatis.GoodsCategoryAttributeService; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Service |
|||
public class GoodsCategoryAttributeServiceImpl extends ServiceImpl<GoodsCategoryAttributeMapper, GoodsCategoryAttribute> implements GoodsCategoryAttributeService { |
|||
@Override |
|||
public boolean saveBatch(GoodsCategoryAttributeForm formData) { |
|||
String categoryId = formData.getCategoryId(); |
|||
Integer attributeType = formData.getType(); |
|||
|
|||
List<String> formIds = formData.getAttributes().stream() |
|||
.filter(item -> item.getId() != null) |
|||
.map(item -> item.getId()) |
|||
.collect(Collectors.toList()); |
|||
|
|||
List<String> dbIds = this.list(new LambdaQueryWrapper<GoodsCategoryAttribute>() |
|||
.eq(GoodsCategoryAttribute::getCategoryId, categoryId) |
|||
.eq(GoodsCategoryAttribute::getType, attributeType) |
|||
.select(GoodsCategoryAttribute::getId)).stream() |
|||
.map(item -> item.getId()) |
|||
.collect(Collectors.toList()); |
|||
|
|||
// 删除此次表单没有的属性ID
|
|||
if (CollectionUtil.isNotEmpty(dbIds)) { |
|||
List<String> rmIds = dbIds.stream() |
|||
.filter(id -> CollectionUtil.isEmpty(formIds) || !formIds.contains(id)) |
|||
.collect(Collectors.toList()); |
|||
if (CollectionUtil.isNotEmpty(rmIds)) { |
|||
this.removeByIds(rmIds); |
|||
} |
|||
} |
|||
|
|||
// 新增/修改表单提交的属性
|
|||
List<GoodsCategoryAttributeForm.Attribute> formAttributes = formData.getAttributes(); |
|||
|
|||
List<GoodsCategoryAttribute> attributeList = new ArrayList<>(); |
|||
|
|||
formAttributes.forEach(item -> { |
|||
GoodsCategoryAttribute attribute = new GoodsCategoryAttribute(); |
|||
attribute.setCategoryId(categoryId); |
|||
attribute.setType(attributeType); |
|||
attribute.setName(item.getName()); |
|||
attributeList.add(attribute); |
|||
}); |
|||
boolean result = this.saveOrUpdateBatch(attributeList); |
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
package cc.hiver.mall.serviceimpl.mybatis; |
|||
|
|||
import cc.hiver.mall.dao.mapper.GoodsCategoryBrandMapper; |
|||
import cc.hiver.mall.entity.GoodsCategoryBrand; |
|||
import cc.hiver.mall.service.mybatis.GoodsCategoryBrandService; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
public class GoodsCategoryBrandServiceImpl extends ServiceImpl<GoodsCategoryBrandMapper, GoodsCategoryBrand> implements GoodsCategoryBrandService { |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
/* |
|||
Copyright [2022] [https://hiver.cc]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
*/ |
|||
package cc.hiver.mall.serviceimpl.mybatis; |
|||
|
|||
import cc.hiver.mall.dao.mapper.GoodsMapper; |
|||
import cc.hiver.mall.entity.Goods; |
|||
import cc.hiver.mall.pojo.form.GoodsForm; |
|||
import cc.hiver.mall.pojo.query.GoodsPageQuery; |
|||
import cc.hiver.mall.pojo.vo.GoodsDetailVO; |
|||
import cc.hiver.mall.pojo.vo.GoodsPageVO; |
|||
import cc.hiver.mall.service.mybatis.GoodsService; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author Yazhi Li |
|||
*/ |
|||
@Service |
|||
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService { |
|||
@Override |
|||
public IPage<GoodsPageVO> listGoodsPages(GoodsPageQuery queryParams) { |
|||
Page<GoodsPageVO> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize()); |
|||
List<GoodsPageVO> list = this.baseMapper.listGoodsPages(page, queryParams); |
|||
page.setRecords(list); |
|||
return page; |
|||
} |
|||
|
|||
@Override |
|||
public GoodsDetailVO getGoodsDetail(String id) { |
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
public boolean addGoods(GoodsForm formData) { |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public boolean updateGoods(GoodsForm formData) { |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public boolean removeByGoodsIds(String[] ids) { |
|||
return false; |
|||
} |
|||
} |
|||
@ -0,0 +1,197 @@ |
|||
package cc.hiver.mall.serviceimpl.mybatis; |
|||
|
|||
import cc.hiver.core.common.constant.MallConstant; |
|||
import cc.hiver.mall.dao.mapper.GoodsStockMapper; |
|||
import cc.hiver.mall.entity.GoodsStock; |
|||
import cc.hiver.mall.pojo.dto.CheckPriceDTO; |
|||
import cc.hiver.mall.pojo.dto.GoodsStockDto; |
|||
import cc.hiver.mall.pojo.dto.LockStockDTO; |
|||
import cc.hiver.mall.service.mybatis.GoodsStockService; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.lang.Assert; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.redisson.api.RLock; |
|||
import org.redisson.api.RedissonClient; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.transaction.Transactional; |
|||
import java.math.BigDecimal; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class GoodsStockServiceImpl extends ServiceImpl<GoodsStockMapper, GoodsStock> implements GoodsStockService { |
|||
@Autowired |
|||
private RedisTemplate redisTemplate; |
|||
|
|||
@Autowired |
|||
private RedissonClient redissonClient; |
|||
|
|||
@Override |
|||
@Cacheable(cacheNames = "mall", key = "'stock_num:'+#id") |
|||
public Integer getStockNum(String id) { |
|||
GoodsStock goodsStock = this.getOne(new LambdaQueryWrapper<GoodsStock>().eq(GoodsStock::getId, id) |
|||
.select(GoodsStock::getStock)); |
|||
Integer stockNum = goodsStock != null ? goodsStock.getStock() : 0; |
|||
return stockNum; |
|||
} |
|||
|
|||
@Override |
|||
public GoodsStockDto getStockInfo(String id) { |
|||
GoodsStockDto goodsStockDto = this.baseMapper.getStockInfo(id); |
|||
return goodsStockDto; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional |
|||
public boolean lockStock(LockStockDTO lockStock) { |
|||
String orderSn = lockStock.getOrderSn(); |
|||
log.info("创建订单【{}】锁定商品库存:{}", orderSn, lockStock); |
|||
List<LockStockDTO.LockedStock> lockedSkus = lockStock.getLockedStocks(); |
|||
Assert.isTrue(CollectionUtil.isNotEmpty(lockedSkus), "锁定的商品为空"); |
|||
// 循环遍历锁定商品
|
|||
for (LockStockDTO.LockedStock lockedSku : lockedSkus) { |
|||
// 获取商品分布式锁
|
|||
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId()); |
|||
// 加锁
|
|||
lock.lock(); |
|||
try { |
|||
boolean lockResult = this.update(new LambdaUpdateWrapper<GoodsStock>() |
|||
.setSql("locked_stock_num = locked_stock_num + " + lockedSku.getCount()) |
|||
.eq(GoodsStock::getId, lockedSku.getGoodsId()) |
|||
.apply("stock - locked_stock >= {0}", lockedSku.getCount()) |
|||
); |
|||
Assert.isTrue(lockResult, "锁定商品 {} 失败", lockedSku.getGoodsId()); |
|||
} finally { |
|||
// 释放锁
|
|||
if (lock.isLocked()) { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
} |
|||
redisTemplate.opsForValue().set(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn, lockedSkus); |
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
public boolean unlockStock(String orderSn) { |
|||
log.info("订单取消:释放订单【{}】锁定的商品库存", orderSn); |
|||
List<LockStockDTO.LockedStock> lockedSkus = (List<LockStockDTO.LockedStock>) redisTemplate.opsForValue() |
|||
.get(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn); |
|||
// 遍历解锁商品
|
|||
if (CollectionUtil.isNotEmpty(lockedSkus)) { |
|||
for (LockStockDTO.LockedStock lockedSku : lockedSkus) { |
|||
// 获取商品分布式锁
|
|||
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId()); |
|||
// 加锁
|
|||
lock.lock(); |
|||
try { |
|||
this.update(new LambdaUpdateWrapper<GoodsStock>() |
|||
.eq(GoodsStock::getId, lockedSku.getGoodsId()) |
|||
.setSql("locked_stock_num = locked_stock_num - " + lockedSku.getCount())); |
|||
} finally { |
|||
// 释放锁
|
|||
if (lock.isLocked()) { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// 移除订单的商品信息缓存
|
|||
redisTemplate.delete(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn); |
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
public boolean deductStock(String orderSn) { |
|||
log.info("订单【{}】支付成功:扣减订单商品库存", orderSn); |
|||
// 获取订单提交时锁定的商品
|
|||
List<LockStockDTO.LockedStock> lockedSkus = (List<LockStockDTO.LockedStock>) redisTemplate.opsForValue() |
|||
.get(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn); |
|||
if (CollectionUtil.isNotEmpty(lockedSkus)) { |
|||
for (LockStockDTO.LockedStock lockedSku : lockedSkus) { |
|||
// 获取商品分布式锁
|
|||
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId()); |
|||
// 加锁
|
|||
lock.lock(); |
|||
try { |
|||
this.update(new LambdaUpdateWrapper<GoodsStock>() |
|||
.eq(GoodsStock::getId, lockedSku.getGoodsId()) |
|||
.setSql("stock = stock_ - " + lockedSku.getCount()) |
|||
.setSql("locked_stock = locked_stock - " + lockedSku.getCount()) |
|||
); |
|||
} finally { |
|||
// 释放锁
|
|||
if (lock.isLocked()) { |
|||
lock.unlock(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// 移除订单的商品缓存
|
|||
redisTemplate.delete(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn); |
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
public boolean checkPrice(CheckPriceDTO checkPrice) { |
|||
log.info("订单【{}】商品验价:{}", checkPrice); |
|||
// 订单总金额
|
|||
BigDecimal orderTotalAmount = checkPrice.getOrderTotalAmount(); |
|||
// 计算商品总金额
|
|||
List<CheckPriceDTO.OrderSku> orderSkus = checkPrice.getOrderSkus(); |
|||
if (orderTotalAmount == null || CollectionUtil.isEmpty(orderSkus)) { |
|||
log.warn("订单【{}】验价失败:订单总金额或订单商品为空,无法进行验价!"); |
|||
return false; |
|||
} |
|||
// 订单商品ID集合
|
|||
List<String> orderGoodsIds = orderSkus.stream().map(orderItem -> orderItem.getGoodsId()) |
|||
.collect(Collectors.toList()); |
|||
// 获取商品的实时价格
|
|||
List<GoodsStock> goodsList = this.list(new LambdaQueryWrapper<GoodsStock>().in(GoodsStock::getId, orderGoodsIds) |
|||
.select(GoodsStock::getId, GoodsStock::getPrice) |
|||
); |
|||
if (CollectionUtil.isEmpty(goodsList)) { |
|||
log.warn("订单【{}】验价失败:订单商品库存不存在或已下架!"); |
|||
return false; |
|||
} |
|||
// 计算商品实时总价
|
|||
BigDecimal skuTotalAmount = goodsList.stream().map(sku -> { |
|||
// 获取订单中该商品数量
|
|||
CheckPriceDTO.OrderSku matchOrderSku = orderSkus.stream() |
|||
.filter(orderSku -> sku.getId().equals(orderSku.getGoodsId())) |
|||
.findFirst().orElse(null); |
|||
// 单个商品实时总价 = 实时单价 * 订单该商品数量
|
|||
return matchOrderSku != null ? sku.getPrice().multiply(new BigDecimal(matchOrderSku.getCount())) : BigDecimal.ZERO; |
|||
}).reduce(BigDecimal.ZERO, BigDecimal::add); |
|||
// 比较订单总价和商品实时总价
|
|||
boolean checkPriceResult = orderTotalAmount.compareTo(skuTotalAmount) == 0; |
|||
return checkPriceResult; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional |
|||
public boolean updateStockNum(String id, Integer stockNum) { |
|||
boolean result = this.update(new LambdaUpdateWrapper<GoodsStock>() |
|||
.eq(GoodsStock::getId, id) |
|||
.set(GoodsStock::getStock, stockNum) |
|||
); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean deductStock(String id, Integer num) { |
|||
boolean result = this.update(new LambdaUpdateWrapper<GoodsStock>() |
|||
.setSql("stock = stock - " + num) |
|||
.eq(GoodsStock::getId, id) |
|||
); |
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
<?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="cc.hiver.mall.dao.mapper.GoodsMapper"> |
|||
|
|||
<resultMap id="BaseResultMap" type="cc.hiver.mall.pojo.vo.GoodsPageVO"> |
|||
<id property="id" column="id" jdbcType="VARCHAR"/> |
|||
<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="purchasePrice" column="purchase_price" jdbcType="BIGINT"/> |
|||
<result property="price" column="price" jdbcType="BIGINT"/> |
|||
<result property="wholesalePrice" column="wholesale_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="categoryName" column="categoryName" jdbcType="VARCHAR"/> |
|||
<result property="brandName" column="brandName" jdbcType="VARCHAR"/> |
|||
<collection property="goodsStockList" column="id" select="cc.hiver.mall.dao.mapper.listGoodsByGoodsId"> |
|||
<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> |
|||
|
|||
<!--商品分页列表--> |
|||
<select id="listGoodsPages" 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 t_goods t1 |
|||
LEFT JOIN t_goods_category t3 ON t1.category_id = t3.id |
|||
LEFT JOIN t_goods_brand t4 ON t1.brand_id = t4.id |
|||
<where> |
|||
<if test='queryParams.keywords!=null and queryParams.keywords.trim() neq ""'> |
|||
AND t1.name like concat('%',#{queryParams.keywords},'%') |
|||
</if> |
|||
<if test="queryParams.categoryId!=null"> |
|||
AND t1.category_id =#{queryParams.categoryId} |
|||
</if> |
|||
|
|||
</where> |
|||
ORDER BY |
|||
t1.update_time DESC, |
|||
t1.create_time DESC |
|||
</select> |
|||
</mapper> |
|||
@ -0,0 +1,33 @@ |
|||
<?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="cc.hiver.mall.dao.mapper.GoodsStockMapper"> |
|||
<!-- 根据商品ID获取商品库存单元列表 --> |
|||
<select id="listGoodsByGoodsId" resultType="cc.hiver.mall.entity.GoodsStock"> |
|||
SELECT id , |
|||
name , |
|||
sn, |
|||
pic_url , |
|||
spec_ids, |
|||
price , |
|||
stock |
|||
FROM t_goods_stock |
|||
WHERE goods_id = #{id} |
|||
</select> |
|||
|
|||
<!-- 获取商品库存单元信息 --> |
|||
<select id="getStockInfo" resultType="cc.hiver.mall.pojo.dto.GoodsStockDto"> |
|||
select |
|||
t1.id, |
|||
t1.sn, |
|||
concat(t2.name,' ',t1.name) name, |
|||
t1.pic_url, |
|||
t1.price, |
|||
t1.stock, |
|||
t2.name as goodsName |
|||
from t_goods_stock t1 |
|||
left join t_goods t2 on t1.goods_id = t2.id |
|||
where t1.id = #{id} |
|||
</select> |
|||
</mapper> |
|||
Loading…
Reference in new issue