Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop into fengtianyangyang_clerk

 Conflicts:
	DB/version4.2.3toMASTER.sql
	common-api/src/main/java/cn/lili/controller/common/SiteController.java
	common-api/src/main/java/cn/lili/controller/common/UploadController.java
	config/application.yml
	framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java
	framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java
	framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
	framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java
This commit is contained in:
fengtianyangyang 2022-08-09 18:54:19 +08:00
commit 26dd8ed13a
237 changed files with 4985 additions and 2159 deletions

View File

@ -1,2 +1,64 @@
/** 新增已退货数量 **/
ALTER TABLE li_order_item ADD return_goods_number int DEFAULT 0 COMMENT '退货数量 ';
ALTER TABLE li_order_item ADD return_goods_number int DEFAULT 0 COMMENT '退货数量 ';
-- 促销重构sql
ALTER TABLE li_coupon DROP COLUMN promotion_status;
ALTER TABLE li_coupon_activity DROP COLUMN promotion_status;
ALTER TABLE li_coupon_activity ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '范围关联的ID';
ALTER TABLE li_coupon_activity ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_full_discount DROP COLUMN promotion_status;
ALTER TABLE li_full_discount ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_full_discount ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_kanjia_activity_goods DROP COLUMN promotion_status;
ALTER TABLE li_kanjia_activity_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_kanjia_activity_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_kanjia_activity_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL;
ALTER TABLE li_pintuan DROP COLUMN promotion_status;
ALTER TABLE li_pintuan ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_pintuan ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_points_goods DROP COLUMN promotion_status;
ALTER TABLE li_points_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_points_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_points_goods ADD `original_price` double(10,2) DEFAULT NULL COMMENT '原价';
ALTER TABLE li_points_goods ADD `thumbnail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '缩略图';
ALTER TABLE li_points_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品编号';
ALTER TABLE li_points_goods ADD `goods_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '货品名称';
ALTER TABLE li_promotion_goods DROP COLUMN promotion_status;
ALTER TABLE li_promotion_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_promotion_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_promotion_goods ADD `original_price` double(10,2) DEFAULT NULL COMMENT '原价';
ALTER TABLE li_promotion_goods ADD `points` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '兑换积分';
ALTER TABLE li_promotion_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品编号';
ALTER TABLE li_seckill DROP COLUMN promotion_status;
ALTER TABLE li_seckill ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_seckill ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_full_discount RENAME COLUMN is_coupon TO coupon_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_free_freight TO free_freight_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_full_minus TO full_minus_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_full_rate TO full_rate_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_gift TO gift_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_point TO point_flag;
ALTER TABLE li_member_coupon RENAME COLUMN is_platform TO platform_flag;
ALTER TABLE li_goods RENAME COLUMN is_auth TO auth_flag;
ALTER TABLE li_goods_sku RENAME COLUMN is_promotion TO promotion_flag;
ALTER TABLE li_goods_sku RENAME COLUMN is_auth TO auth_flag;
-- 增加会员表索引
ALTER TABLE li_member ADD INDEX query_mobile (`mobile`) COMMENT 'query_member';
-- 会员签到唯一索引 惠券查询索引
ALTER TABLE li_member_sign ADD INDEX query_create_time (`create_time`) COMMENT 'query_create_time';
ALTER TABLE li_member_sign ADD INDEX query_member_id (`member_id`) COMMENT 'query_member_id';
ALTER TABLE li_member_sign add unique uk_member_day (member_id, create_time) COMMENT 'uk_member_day';

View File

@ -1,86 +0,0 @@
/** 新增已退货数量 **/
ALTER TABLE li_order_item ADD return_goods_number int DEFAULT 0 COMMENT '退货数量 ';
-- 促销重构sql
ALTER TABLE li_coupon DROP COLUMN promotion_status;
ALTER TABLE li_coupon_activity DROP COLUMN promotion_status;
ALTER TABLE li_coupon_activity ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '范围关联的ID';
ALTER TABLE li_coupon_activity ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_full_discount DROP COLUMN promotion_status;
ALTER TABLE li_full_discount ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_full_discount ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_kanjia_activity_goods DROP COLUMN promotion_status;
ALTER TABLE li_kanjia_activity_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_kanjia_activity_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_kanjia_activity_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL;
ALTER TABLE li_pintuan DROP COLUMN promotion_status;
ALTER TABLE li_pintuan ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_pintuan ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_points_goods DROP COLUMN promotion_status;
ALTER TABLE li_points_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_points_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_points_goods ADD `original_price` double(10,2) DEFAULT NULL COMMENT '原价';
ALTER TABLE li_points_goods ADD `thumbnail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '缩略图';
ALTER TABLE li_points_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品编号';
ALTER TABLE li_points_goods ADD `goods_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '货品名称';
ALTER TABLE li_promotion_goods DROP COLUMN promotion_status;
ALTER TABLE li_promotion_goods ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_promotion_goods ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_promotion_goods ADD `original_price` double(10,2) DEFAULT NULL COMMENT '原价';
ALTER TABLE li_promotion_goods ADD `points` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '兑换积分';
ALTER TABLE li_promotion_goods ADD `goods_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品编号';
ALTER TABLE li_seckill DROP COLUMN promotion_status;
ALTER TABLE li_seckill ADD `scope_id` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '范围关联的ID';
ALTER TABLE li_seckill ADD `scope_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'PORTION_GOODS' COMMENT '关联范围类型';
ALTER TABLE li_full_discount RENAME COLUMN is_coupon TO coupon_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_free_freight TO free_freight_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_full_minus TO full_minus_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_full_rate TO full_rate_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_gift TO gift_flag;
ALTER TABLE li_full_discount RENAME COLUMN is_point TO point_flag;
ALTER TABLE li_member_coupon RENAME COLUMN is_platform TO platform_flag;
ALTER TABLE li_goods RENAME COLUMN is_auth TO auth_flag;
ALTER TABLE li_goods_sku RENAME COLUMN is_promotion TO promotion_flag;
ALTER TABLE li_goods_sku RENAME COLUMN is_auth TO auth_flag;
-- 增加会员表索引
ALTER TABLE li_member ADD INDEX query_mobile (`mobile`) COMMENT 'query_member';
-- 会员签到唯一索引 惠券查询索引
ALTER TABLE li_member_sign ADD INDEX query_create_time (`create_time`) COMMENT 'query_create_time';
ALTER TABLE li_member_sign ADD INDEX query_member_id (`member_id`) COMMENT 'query_member_id';
ALTER TABLE li_member_sign add unique uk_member_day (member_id, create_time) COMMENT 'uk_member_day';
/**增加店铺发货信息**/
ALTER TABLE li_store_detail ADD `sales_consignor_address_id` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货地址id';
ALTER TABLE li_store_detail ADD `sales_consignor_address_path` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货地址名称';
ALTER TABLE li_store_detail ADD `sales_consignor_detail` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货详细地址';
ALTER TABLE li_store_detail ADD `sales_consignor_mobile` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货人手机';
ALTER TABLE li_store_detail ADD `sales_consignor_name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货人姓名';
/**增加电子面单店铺信息**/
ALTER TABLE `li_store_logistics` ADD `customer_name` varchar(255) DEFAULT NULL COMMENT '客户代码';
ALTER TABLE `li_store_logistics` ADD `customer_pwd` varchar(255) DEFAULT NULL COMMENT '客户密码';
ALTER TABLE `li_store_logistics` ADD `month_code` varchar(255) DEFAULT NULL COMMENT '月结号/密钥';
ALTER TABLE `li_store_logistics` ADD `send_site` varchar(255) DEFAULT NULL COMMENT '归属网点';
ALTER TABLE `li_store_logistics` ADD `send_staff` varchar(255) DEFAULT NULL COMMENT '收件快递员';
ALTER TABLE `li_store_logistics` ADD `face_sheet_flag` bit(1) DEFAULT NULL COMMENT '是否使用电子面单';
/**是否使用电子面单标志**/
ALTER TABLE li_store_logistics RENAME COLUMN is_face_sheet TO face_sheet_flag;

View File

@ -0,0 +1,46 @@
/** 增加签到日期 **/
ALTER TABLE li_member_sign
ADD day int DEFAULT NULL COMMENT '签到日 ';
ALTER TABLE li_member_sign
DROP INDEX uk_member_day;
ALTER TABLE li_member_sign
add unique uk_member_day (member_id, day) COMMENT 'uk_member_day';
-- ----------------------------
-- Table structure for li_hot_words_history
-- ----------------------------
DROP TABLE IF EXISTS `li_hot_words_history`;
CREATE TABLE `li_hot_words_history`
(
`id` bigint NOT NULL COMMENT 'ID',
`create_time` datetime(6) DEFAULT NULL COMMENT '创建时间',
`keywords` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '热词',
`score` int DEFAULT NULL COMMENT '热词分数',
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 COLLATE = utf8_bin COMMENT '热词历史表';
-- ----------------------------
-- Records of li_hot_words_history
-- ----------------------------
-- ----------------------------
-- Table structure for li_wholesale
-- ----------------------------
DROP TABLE IF EXISTS `li_wholesale`;
CREATE TABLE `li_wholesale`
(
`id` bigint NOT NULL,
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime(6) DEFAULT NULL,
`delete_flag` bit(1) DEFAULT NULL,
`update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime(6) DEFAULT NULL,
`price` decimal(10, 2) DEFAULT NULL COMMENT '价格',
`goods_id` bigint DEFAULT NULL COMMENT '商品id',
`sku_id` bigint DEFAULT NULL COMMENT '商品skuId',
`num` int DEFAULT NULL COMMENT '起购量',
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_bin COMMENT '批发规则表';

View File

@ -1,10 +1,6 @@
## Lilishop B2B2C商城系统
##### 开源不易如有帮助请点Star
#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,进群先看文档后提问)
#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,其他问题先看文档后提问)
<<<<<<< HEAD
##### 交流 qq 1群 961316482已满
@ -16,12 +12,17 @@
##### 交流 qq 1群 961316482已满
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=BAhURE3DG2YWhQk6kRxVapbLykqMoPS8&jump_from=webapi"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群" title="Lilishop交流群">点击快捷加群</a>
##### 交流 qq 2群 875294241
##### 交流 qq 2群 875294241(已满)
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=_lrekOvr5k2p5uTn5GRidI-chKEmpCX3&jump_from=webapi"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群2群" title="Lilishop交流群2群">点击快捷加群</a>
>>>>>>> ae0c4aea12996d3d72eca7c6ccdc97922373e4d7
##### 交流 qq 3群 263785057
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=VUogkDvaso4zLTFH8nxFPDRKq0EthUn1&jump_from=webapi"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群3群" title="Lilishop交流群3群">点击快捷加群</a>
##### 体验 公众号/小程序/APP 体验,扫描二维码
![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png)
@ -35,13 +36,13 @@
Lilishop商城系统支持商家入驻后端基于SpringBoot 研发,前端使用 Vue、uniapp开发 **系统全端全部代码开源**
商城前后端分离支持分布式部署支持Docker各个API独立并且有独立的消费者。
前后端分离支持分布式部署支持Docker各个API独立并且有独立的消费者。
### 商城 API/消费者 聚合版
api不需要单独部署只需启动一个jar包就可以正常运转 如有需要,可以点击跳转
https://gitee.com/beijing_hongye_huicheng/lilishop-simplify
### 商城 开发/使用/常见问题 帮助文档
### 开发/使用/常见问题 帮助文档
https://docs.pickmall.cn
@ -68,7 +69,7 @@ PS手机验证码为 111111
![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png)
### 快速部署本地商城
### 快速本地部署
[点击跳转](https://docs.pickmall.cn/deploy/%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87.html)
@ -145,11 +146,19 @@ PS手机验证码为 111111
### 版本升级
```
商城后续会持续版本升级修复bug完善功能覆盖更多业务场景 o2o/b2b/s2b2b2c/跨境电商
后续会考虑推出微服务商城系统/商城中台等
系统后续会提供多场景解决方案。
更多架构微服务、Saas、中台等都会支持。 支持差价升级商业授权
```
### 商业授权
商业版本与开源版本代码一致,没有区分
商业使用需要授权授权方式可选择联系官网客服或者qq群联系群主。
商业授权模式为永久授权,支持永久升级。
商业案例由于涉及部分多层二开关系,如需了解可以咨询销售。
### 开源须知
1.仅允许用于个人学习研究使用.
@ -158,11 +167,12 @@ PS手机验证码为 111111
3.软件受国家计算机软件著作权保护登记号2021SR0805085
4.限制商用如果需要商业使用请联系我们。QQ3409056806.
4.限制商用如果需要商业使用请联系我们。QQ3409056806.或者加入qq群联系群主。
### 交流群
##### 官方qq 1群 961316482已满
##### 官方qq 2群 875294241
##### 官方qq 2群 875294241(已满)
##### 官网qq 3群 263785057

View File

@ -14,6 +14,7 @@ import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
import cn.lili.modules.search.service.EsGoodsSearchService;
import cn.lili.modules.search.service.HotWordsService;
import cn.lili.modules.statistics.aop.PageViewPoint;
import cn.lili.modules.statistics.aop.enums.PageViewEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -62,6 +63,9 @@ public class GoodsBuyerController {
@Autowired
private EsGoodsSearchService goodsSearchService;
@Autowired
private HotWordsService hotWordsService;
@ApiOperation(value = "通过id获取商品信息")
@ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "path", dataType = "Long")
@GetMapping(value = "/get/{goodsId}")
@ -117,7 +121,7 @@ public class GoodsBuyerController {
@ApiOperation(value = "获取搜索热词")
@GetMapping("/hot-words")
public ResultMessage<List<String>> getGoodsHotWords(Integer count) {
List<String> hotWords = goodsSearchService.getHotWords(count);
List<String> hotWords = hotWordsService.getHotWords(count);
return ResultUtil.data(hotWords);
}

View File

@ -5,6 +5,7 @@ import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.service.FootprintService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@ -34,7 +35,7 @@ public class FootprintController {
@ApiOperation(value = "分页获取")
@GetMapping
public ResultMessage<List<EsGoodsIndex>> getByPage(PageVO page) {
public ResultMessage<IPage<EsGoodsIndex>> getByPage(PageVO page) {
return ResultUtil.data(footprintService.footPrintPage(page));
}

View File

@ -48,7 +48,7 @@ public class MemberEvaluationBuyerController {
@ApiOperation(value = "查看会员评价详情")
@ApiImplicitParam(name = "id", value = "评价ID", required = true, paramType = "path")
@GetMapping(value = "/get/{id}")
public ResultMessage<MemberEvaluationVO> save(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) {
public ResultMessage<MemberEvaluationVO> get(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) {
return ResultUtil.data(memberEvaluationService.queryById(id));
}

View File

@ -1,5 +1,6 @@
package cn.lili.controller.member;
import cn.lili.cache.limit.annotation.LimitPoint;
import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;

View File

@ -82,7 +82,7 @@ public class OrderComplaintBuyerController {
@PostMapping("/communication")
public ResultMessage<OrderComplaintCommunicationVO> addCommunication(@RequestParam String complainId, @RequestParam String content) {
AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser());
OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.BUYER.name(), currentUser.getId(), currentUser.getNickName());
OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.BUYER.name(), currentUser.getNickName(), currentUser.getId());
orderComplaintCommunicationService.addCommunication(communicationVO);
return ResultUtil.data(communicationVO);
}

View File

@ -3,7 +3,7 @@ package cn.lili.controller.other.broadcast;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.goods.entity.dos.Studio;
import cn.lili.modules.goods.entity.vos.StudioVO;
import cn.lili.modules.goods.service.StudioService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
@ -35,7 +35,7 @@ public class StudioController {
@ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query", dataType = "String")
})
@GetMapping
public ResultMessage<IPage<Studio>> page(PageVO pageVO, Integer recommend, String status) {
public ResultMessage<IPage<StudioVO>> page(PageVO pageVO, Integer recommend, String status) {
return ResultUtil.data(studioService.studioList(pageVO, recommend, status));
}

View File

@ -146,7 +146,6 @@ public class MemberBuyerController {
@ApiOperation(value = "修改密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "password", value = "是否保存登录", required = true, paramType = "query")
})
@PostMapping("/resetPassword")
@ -177,6 +176,34 @@ public class MemberBuyerController {
return ResultUtil.data(memberService.modifyPass(tokenUser.getId(), password, newPassword));
}
@ApiOperation(value = "初始设置密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query")
})
@PutMapping("/canInitPassword")
public ResultMessage<Object> canInitPassword() {
return ResultUtil.data(memberService.canInitPass());
}
@ApiOperation(value = "初始设置密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query")
})
@PutMapping("/initPassword")
public ResultMessage<Object> initPassword(@NotNull(message = "密码不能为空") @RequestParam String password) {
memberService.initPass(password);
return ResultUtil.success();
}
@ApiOperation(value = "注销账号")
@ApiImplicitParams({
@ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query")
})
@PutMapping("/cancellation")
public ResultMessage<Member> cancellation(@NotNull(message = "密码不能为空") @RequestParam String password) {
memberService.cancellation(password);
return ResultUtil.success();
}
@ApiOperation(value = "刷新token")
@GetMapping("/refresh/{refreshToken}")

View File

@ -0,0 +1,30 @@
package cn.lili.init;
import cn.lili.modules.search.service.EsGoodsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* @author paulG
* @since 2022/6/9
**/
@Component
@Slf4j
public class EsGoodsIndexInitRunner implements ApplicationRunner {
@Autowired
private EsGoodsIndexService esGoodsIndexService;
@Override
public void run(ApplicationArguments args) {
try {
esGoodsIndexService.initIndex();
} catch (Exception e) {
log.error("检测ES商品索引失败", e);
}
}
}

View File

@ -1,7 +1,7 @@
package cn.lili.buyer.test.cart;
import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.service.BrandService;
import com.xkcoding.http.util.StringUtil;
@ -27,7 +27,7 @@ class FileTest {
@Autowired
private FileManagerPlugin fileManagerPlugin;
private FilePlugin fileManagerPlugin;
@Autowired
private BrandService brandService;

View File

@ -2,9 +2,9 @@ package cn.lili.controller.common;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.system.service.RegionService;
import cn.lili.modules.system.entity.dos.Region;
import cn.lili.modules.system.entity.vo.RegionVO;
import cn.lili.modules.system.service.RegionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -38,6 +38,11 @@ public class RegionController {
return ResultUtil.data(regionService.getRegion(cityCode,townName));
}
@GetMapping(value = "/name")
@ApiOperation(value = "根据名字获取地区地址id")
public ResultMessage<String> getItemByLastName(String lastName) {
return ResultUtil.data(regionService.getItemByLastName(lastName));
}
@GetMapping(value = "/item/{id}")
@ApiImplicitParam(name = "id", value = "地区ID", required = true, dataType = "String", paramType = "path")

View File

@ -8,9 +8,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* 滑块验证码接口
@ -21,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/common/common/site")
@Api(tags = "系统基础设置接口")
@Api(tags = "系统基础接口")
public class SiteController {
@Autowired

View File

@ -12,7 +12,8 @@ import cn.lili.common.utils.Base64DecodeMultipartFile;
import cn.lili.common.utils.CommonUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.file.entity.File;
import cn.lili.modules.file.plugin.QiNiuManagerPlugin;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.file.plugin.FilePluginFactory;
import cn.lili.modules.file.service.FileService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.enums.SettingEnum;
@ -47,7 +48,7 @@ public class UploadController {
@Autowired
private SettingService settingService;
@Autowired
private QiNiuManagerPlugin fileManagerPlugin;
private FilePluginFactory filePluginFactory;
@Autowired
private Cache cache;
@ -86,7 +87,7 @@ public class UploadController {
try {
InputStream inputStream = file.getInputStream();
//上传至第三方云服务或服务器
result = fileManagerPlugin.inputStreamUpload(inputStream, fileKey);
result = filePluginFactory.filePlugin().inputStreamUpload(inputStream, fileKey);
//保存数据信息至数据库
newFile.setName(file.getOriginalFilename());
newFile.setFileSize(file.getSize());

View File

@ -1,8 +1,5 @@
package cn.lili.controller.security;
import cn.lili.cache.Cache;
import cn.lili.common.security.CustomAccessDeniedHandler;
import cn.lili.common.properties.IgnoredUrlsProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
@ -25,19 +22,10 @@ import org.springframework.web.cors.CorsConfigurationSource;
public class CommonSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 忽略验权配置
*/
@Autowired
private IgnoredUrlsProperties ignoredUrlsProperties;
/**
* spring security - 权限不足处理
*/
@Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
@Autowired
private Cache<String> cache;
@Autowired
private CorsConfigurationSource corsConfigurationSource;
@Override

View File

@ -121,6 +121,8 @@ ignored:
- /source/**
- /common/common/slider/**
- /common/common/sms/**
- /common/common/logo
- /common/common/site
- /druid/**
- /swagger-ui.html
- /doc.html

View File

@ -25,20 +25,11 @@ spring:
admin:
client:
url: http://192.168.0.116:8000
# mongodb
data:
mongodb:
uri: 192.168.0.116:27017
database: lilishop
username: root
password: lilishop
authentication-database: admin
# replica-set-name: mongoreplset
cache:
type: redis
# Redis
redis:
host: 192.168.0.116
host: 127.0.0.1
port: 6379
password: lilishop
lettuce:
@ -70,6 +61,7 @@ spring:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.0.116:3306/clerk?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: lilishop
maxActive: 50
@ -128,6 +120,7 @@ ignored:
- /store/passport/login/refresh/**
- /common/common/slider/**
- /common/common/sms/**
- /common/common/site
- /buyer/payment/cashier/**
- /buyer/other/pageData/**
- /buyer/other/article/**
@ -191,7 +184,6 @@ logging:
cn.lili: info
# org.hibernate: debug
# org.springframework: debug
# org.springframework.data.mongodb.core: debug
file:
# 指定路径
path: logs
@ -278,7 +270,7 @@ lili:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.0.116:9200
cluster-nodes: 127.0.0.1:9200
index:
number-of-replicas: 0
number-of-shards: 3
@ -289,7 +281,7 @@ lili:
# password: LiLiShopES
logstash:
server: 192.168.0.116:4560
server: 127.0.0.1:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group
@ -310,7 +302,7 @@ lili:
after-sale-topic: lili_after_sale_topic
after-sale-group: lili_after_sale_group
rocketmq:
name-server: 192.168.0.116:9876
name-server: 127.0.0.1:9876
isVIPChannel: false
producer:
group: lili_group
@ -319,7 +311,7 @@ rocketmq:
xxl:
job:
admin:
addresses: http://192.168.0.116:9001/xxl-job-admin
addresses: http://127.0.0.1:9001/xxl-job-admin
executor:
appname: xxl-job-executor-lilishop
address:

View File

@ -19,6 +19,7 @@ import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.enums.*;
import cn.lili.modules.order.order.service.OrderItemService;
@ -96,6 +97,15 @@ public class FullDiscountExecute implements TradeEvent, OrderStatusChangeEvent {
if (orderMessage.getNewStatus().equals(OrderStatusEnum.PAID)) {
log.debug("满减活动,订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
renderGift(JSONUtil.toBean(cache.getString(CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn()), CartVO.class), orderMessage);
} else if (orderMessage.getNewStatus().equals(OrderStatusEnum.CANCELLED)) {
log.debug("满减活动,取消订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
OrderSearchParams searchParams = new OrderSearchParams();
searchParams.setParentOrderSn(orderMessage.getOrderSn());
searchParams.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
List<Order> orders = orderService.queryListByParams(searchParams);
if (orders != null && !orders.isEmpty()) {
orderService.systemCancel(orders.get(0).getSn(),"主订单取消,赠送订单字段自动取消");
}
}
}
@ -190,6 +200,7 @@ public class FullDiscountExecute implements TradeEvent, OrderStatusChangeEvent {
BeanUtil.copyProperties(priceDetailDTO, order, "id");
//生成订单参数
order.setSn(SnowFlake.createStr("G"));
order.setParentOrderSn(originOrder.getSn());
order.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
order.setOrderStatus(OrderStatusEnum.UNPAID.name());
order.setPayStatus(PayStatusEnum.PAID.name());

View File

@ -5,6 +5,7 @@ import cn.lili.common.utils.SpringContextUtil;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.entity.RefundLog;
@ -33,52 +34,32 @@ public class PaymentExecute implements OrderStatusChangeEvent {
@Override
public void orderChange(OrderMessage orderMessage) {
switch (orderMessage.getNewStatus()) {
case CANCELLED:
Order order = orderService.getBySn(orderMessage.getOrderSn());
if (orderMessage.getNewStatus() == OrderStatusEnum.CANCELLED) {
Order order = orderService.getBySn(orderMessage.getOrderSn());
//如果未付款则不去要退回相关代码执行
if (order.getPayStatus().equals(PayStatusEnum.UNPAID.name())) {
return;
}
PaymentMethodEnum paymentMethodEnum = PaymentMethodEnum.valueOf(order.getPaymentMethod());
//进行退款操作
switch (paymentMethodEnum) {
case WALLET:
case ALIPAY:
case WECHAT:
//获取支付方式
Payment payment =
(Payment) SpringContextUtil.getBean(paymentMethodEnum.getPlugin());
//如果未付款则不去要退回相关代码执行
if (order.getPayStatus().equals(PayStatusEnum.UNPAID.name())) {
return;
}
PaymentMethodEnum paymentMethodEnum = PaymentMethodEnum.valueOf(order.getPaymentMethod());
RefundLog refundLog = RefundLog.builder()
.isRefund(false)
.totalAmount(order.getFlowPrice())
.payPrice(order.getFlowPrice())
.memberId(order.getMemberId())
.paymentName(order.getPaymentMethod())
.afterSaleNo("订单取消")
.orderSn(order.getSn())
.paymentReceivableNo(order.getReceivableNo())
.outOrderNo("AF" + SnowFlake.getIdStr())
.outOrderNo("AF" + SnowFlake.getIdStr())
.refundReason("订单取消")
.build();
payment.cancel(refundLog);
break;
case BANK_TRANSFER:
break;
default:
log.error("订单支付执行异常,订单编号:{}", orderMessage.getOrderSn());
break;
}
break;
default:
break;
//获取支付方式
Payment payment =
(Payment) SpringContextUtil.getBean(paymentMethodEnum.getPlugin());
RefundLog refundLog = RefundLog.builder()
.isRefund(false)
.totalAmount(order.getFlowPrice())
.payPrice(order.getFlowPrice())
.memberId(order.getMemberId())
.paymentName(order.getPaymentMethod())
.afterSaleNo("订单取消")
.orderSn(order.getSn())
.paymentReceivableNo(order.getReceivableNo())
.outOrderNo("AF" + SnowFlake.getIdStr())
.refundReason("订单取消")
.build();
payment.refund(refundLog);
}
}
}

View File

@ -29,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 库存扣减他表示了订单状态是否出库成功
@ -156,7 +157,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
* @param stocks
*/
private void checkStocks(List<Integer> stocks, OrderDetailVO order) {
if (order.getOrderItems().size() == stocks.size()) {
if (!stocks.isEmpty() && order.getOrderItems().size() == stocks.size() && stocks.stream().anyMatch(Objects::nonNull)) {
return;
}
initSkuCache(order.getOrderItems());
@ -357,6 +358,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
GoodsSku goodsSku = new GoodsSku();
goodsSku.setId(orderItem.getSkuId());
goodsSku.setGoodsId(orderItem.getGoodsId());
goodsSkus.add(goodsSku);
}
//批量获取商品库存

View File

@ -6,6 +6,8 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassLoaderUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lili.common.aop.annotation.RetryOperation;
import cn.lili.common.exception.RetryException;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.modules.distribution.entity.dos.DistributionGoods;
import cn.lili.modules.distribution.entity.dto.DistributionGoodsSearchParams;
@ -30,7 +32,6 @@ import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.promotion.service.PromotionService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.store.service.StoreService;
import cn.lili.rocketmq.tags.GoodsTagsEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
@ -58,11 +59,6 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
*/
@Autowired
private EsGoodsIndexService goodsIndexService;
/**
* 店铺
*/
@Autowired
private StoreService storeService;
/**
* 商品
*/
@ -121,6 +117,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
private PromotionGoodsService promotionGoodsService;
@Override
@RetryOperation
public void onMessage(MessageExt messageExt) {
switch (GoodsTagsEnum.valueOf(messageExt.getTags())) {
@ -135,20 +132,32 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
String goodsId = new String(messageExt.getBody());
log.info("生成索引: {}", goodsId);
Goods goods = this.goodsService.getById(goodsId);
updateGoodsIndex(goods);
this.updateGoodsIndex(goods);
} catch (Exception e) {
log.error("生成商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
log.error("生成商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
case GENERATOR_STORE_GOODS_INDEX:
try {
String storeId = new String(messageExt.getBody());
this.updateGoodsIndex(storeId);
} catch (Exception e) {
log.error("生成店铺商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
case UPDATE_GOODS_INDEX_PROMOTIONS:
this.updateGoodsIndexPromotions(new String(messageExt.getBody()));
break;
case DELETE_GOODS_INDEX_PROMOTIONS:
BasePromotions promotions = JSONUtil.toBean(new String(messageExt.getBody()), BasePromotions.class);
if (CharSequenceUtil.isNotEmpty(promotions.getScopeId())) {
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(Arrays.asList(promotions.getScopeId().split(",")), promotions.getId());
JSONObject jsonObject = JSONUtil.parseObj(new String(messageExt.getBody()));
String promotionKey = jsonObject.getStr("promotionKey");
if (CharSequenceUtil.isEmpty(promotionKey)) {
break;
}
if (CharSequenceUtil.isNotEmpty(jsonObject.getStr("scopeId"))) {
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(Arrays.asList(jsonObject.getStr("scopeId").split(",")), promotionKey);
} else {
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(null, promotions.getId());
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(promotionKey);
}
break;
case UPDATE_GOODS_INDEX:
@ -159,7 +168,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
List<Goods> goodsList = goodsService.queryListByParams(searchParams);
this.updateGoodsIndex(goodsList);
} catch (Exception e) {
log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
log.error("更新商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
case UPDATE_GOODS_INDEX_FIELD:
@ -172,7 +181,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
Map<String, Object> updateFields = updateIndexFields.get("updateFields", Map.class);
goodsIndexService.updateIndex(queryFields, updateFields);
} catch (Exception e) {
log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
log.error("更新商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
case RESET_GOODS_INDEX:
@ -181,13 +190,12 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
List<EsGoodsIndex> goodsIndices = JSONUtil.toList(goodsIdsJsonStr, EsGoodsIndex.class);
goodsIndexService.updateBulkIndex(goodsIndices);
} catch (Exception e) {
log.error("重置商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
log.error("重置商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
//审核商品
case GOODS_AUDIT:
Goods goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class);
updateGoodsNum(goods);
updateGoodsIndex(goods);
break;
//删除商品
@ -195,19 +203,10 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
try {
String goodsIdsJsonStr = new String(messageExt.getBody());
for (String goodsId : JSONUtil.toList(goodsIdsJsonStr, String.class)) {
Goods goodsById = this.goodsService.getById(goodsId);
if (goodsById != null) {
this.deleteGoods(goodsById);
this.updateGoodsNum(goodsById);
List<String> skuIdsByGoodsId = this.goodsSkuService.getSkuIdsByGoodsId(goodsId);
if (skuIdsByGoodsId != null && !skuIdsByGoodsId.isEmpty()) {
this.goodsIndexService.deleteIndexByIds(skuIdsByGoodsId);
}
}
goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("goodsId", goodsId).build());
}
} catch (Exception e) {
log.error("删除商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
log.error("删除商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
//规格删除
@ -216,6 +215,16 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
List<String> skuIds = JSONUtil.toList(message, String.class);
goodsCollectionService.deleteSkuCollection(skuIds);
break;
case STORE_GOODS_DELETE:
try {
String storeId = new String(messageExt.getBody());
goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("storeId", storeId).build());
} catch (RetryException re) {
throw re;
} catch (Exception e) {
log.error("删除店铺商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
}
break;
//商品评价
case GOODS_COMMENT_COMPLETE:
MemberEvaluation memberEvaluation = JSONUtil.toBean(new String(messageExt.getBody()), MemberEvaluation.class);
@ -244,22 +253,26 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
try {
log.info("更新商品索引促销信息: {}", promotionsJsonStr);
JSONObject jsonObject = JSONUtil.parseObj(promotionsJsonStr);
// 转换为详细的促销信息促销信息必须继承自 BasePromotions且必须保证派生类存在与sdk包下
BasePromotions promotions = (BasePromotions) jsonObject.get("promotions",
ClassLoaderUtil.loadClass(jsonObject.get("promotionsType").toString()));
// 获取促销唯一key, 促销类型 + 促销id 组成
String esPromotionKey = jsonObject.get("esPromotionKey").toString();
if (PromotionsScopeTypeEnum.PORTION_GOODS.name().equals(promotions.getScopeType())) {
PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams();
searchParams.setPromotionId(promotions.getId());
List<PromotionGoods> promotionGoodsList = this.promotionGoodsService.listFindAll(searchParams);
List<String> skuIds = promotionGoodsList.stream().map(PromotionGoods::getSkuId).collect(Collectors.toList());
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(skuIds, promotions.getId());
// 更新商品索引促销信息删除原索引中相关的促销信息更新索引中促销信息
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(skuIds, esPromotionKey);
this.goodsIndexService.updateEsGoodsIndexByList(promotionGoodsList, promotions, esPromotionKey);
} else if (PromotionsScopeTypeEnum.PORTION_GOODS_CATEGORY.name().equals(promotions.getScopeType())) {
GoodsSearchParams searchParams = new GoodsSearchParams();
searchParams.setCategoryPath(promotions.getScopeId());
List<GoodsSku> goodsSkuByList = this.goodsSkuService.getGoodsSkuByList(searchParams);
List<String> skuIds = goodsSkuByList.stream().map(GoodsSku::getId).collect(Collectors.toList());
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(skuIds, promotions.getId());
// 更新商品索引促销信息删除原索引中相关的促销信息更新索引中促销信息
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(skuIds, esPromotionKey);
this.goodsIndexService.updateEsGoodsIndexPromotions(skuIds, promotions, esPromotionKey);
} else if (PromotionsScopeTypeEnum.ALL.name().equals(promotions.getScopeType())) {
this.goodsIndexService.updateEsGoodsIndexAllByList(promotions, esPromotionKey);
@ -303,6 +316,22 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
goodsIndexService.updateBulkIndex(goodsIndices);
}
/**
* 更新商品索引根据店铺id
*
* @param storeId 店铺id
*/
private void updateGoodsIndex(String storeId) {
//如果商品通过审核&&并且已上架
GoodsSearchParams searchParams = new GoodsSearchParams();
searchParams.setStoreId(storeId);
for (Goods goods : this.goodsService.queryListByParams(searchParams)) {
this.updateGoodsIndex(goods);
}
}
/**
* 更新商品索引
*
@ -339,20 +368,19 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
*/
private void generatorGoodsIndex(Goods goods, List<GoodsSku> goodsSkuList) {
int skuSource = 100;
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
for (GoodsSku goodsSku : goodsSkuList) {
EsGoodsIndex esGoodsOld = goodsIndexService.findById(goodsSku.getId());
EsGoodsIndex goodsIndex = this.settingUpGoodsIndexData(goods, goodsSku);
goodsIndex.setSkuSource(skuSource--);
log.info("goodsSku{}", goodsSku);
log.info("esGoodsOld{}", esGoodsOld);
//如果商品库存不为0并且es中有数据
if (goodsSku.getQuantity() > 0 && esGoodsOld == null) {
if (goodsSku.getQuantity() > 0) {
log.info("生成商品索引 {}", goodsIndex);
this.goodsIndexService.addIndex(goodsIndex);
} else if (goodsSku.getQuantity() > 0 && esGoodsOld != null) {
goodsIndexService.updateIndex(goodsIndex);
esGoodsIndices.add(goodsIndex);
}
}
this.goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("goodsId", goods.getId()).build());
this.goodsIndexService.addIndex(esGoodsIndices);
}
private EsGoodsIndex settingUpGoodsIndexData(Goods goods, GoodsSku goodsSku) {
@ -389,7 +417,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
}
}
if (goodsIndex.getPromotionMap() == null || goodsIndex.getPromotionMap().isEmpty()) {
if (goodsIndex.getOriginPromotionMap() == null || goodsIndex.getOriginPromotionMap().isEmpty()) {
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsSkuPromotionMap(goodsIndex.getStoreId(), goodsIndex.getId());
goodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(goodsCurrentPromotionMap));
}
@ -421,21 +449,6 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
}
}
/**
* 修改商品数量
*
* @param goods 信息体
*/
private void updateGoodsNum(Goods goods) {
try {
//更新店铺商品数量
assert goods != null;
storeService.updateStoreGoodsNum(goods.getStoreId());
} catch (Exception e) {
log.error("修改商品数量错误");
}
}
/**
* 商品购买完成
* 1.更新商品购买数量

View File

@ -34,7 +34,7 @@ public class CouponExecute implements EveryDayExecute {
*/
@Override
public void execute() {
//将过期优惠券变更为过期状
//将过期优惠券变更为过期状
LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
.le(MemberCoupon::getEndTime, new Date())

View File

@ -1,11 +1,24 @@
package cn.lili.timetask.handler.impl.hotwords;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.search.entity.dos.HotWordsHistory;
import cn.lili.modules.search.service.HotWordsHistoryService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.HotWordsSetting;
import cn.lili.modules.system.entity.dto.HotWordsSettingItem;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.timetask.handler.EveryDayExecute;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
/**
* @author paulG
@ -18,13 +31,54 @@ public class HotWordsEveryDayTaskExecute implements EveryDayExecute {
@Autowired
private Cache cache;
@Autowired
private HotWordsHistoryService hotWordsHistoryService;
@Autowired
private SettingService settingService;
/**
* 执行每日任务
*/
@Override
public void execute() {
//获取大于0分的热词
Set<DefaultTypedTuple> tuples = cache.zRangeByScore(CachePrefix.HOT_WORD.getPrefix(), 1, Integer.MAX_VALUE);
//如果任务不为空
if (!CollectionUtils.isEmpty(tuples)) {
//因为是第二天统计第一天的数据所以这里获取昨天凌晨的时间
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - 1);
//批量保存热词
List<HotWordsHistory> hotWordsHistories = new ArrayList<>();
for (DefaultTypedTuple tuple : tuples) {
String keywords = (String) tuple.getValue();
Double score = tuple.getScore();
hotWordsHistories.add(new HotWordsHistory(keywords, score.intValue(), calendar.getTime()));
}
hotWordsHistoryService.saveBatch(hotWordsHistories);
}
//移除昨日的热搜词
cache.remove(CachePrefix.HOT_WORD.getPrefix());
//设置今日默认热词
Setting setting = settingService.get(SettingEnum.HOT_WORDS.name());
if (setting == null) {
return;
}
HotWordsSetting hotWordsSetting = JSONUtil.toBean(setting.getSettingValue(), HotWordsSetting.class);
List<HotWordsSettingItem> hotWordsSettingItems = hotWordsSetting.getHotWordsSettingItems();
if (hotWordsSettingItems != null && !hotWordsSettingItems.isEmpty()) {
for (HotWordsSettingItem hotWordsSettingItem : hotWordsSettingItems) {
cache.zAdd(CachePrefix.HOT_WORD.getPrefix(), hotWordsSettingItem.getScore(), hotWordsSettingItem.getKeywords());
}
}
}
}

View File

@ -160,7 +160,7 @@ public class OrderEveryDayTaskExecute implements EveryDayExecute {
private void closeAfterSale(OrderSetting orderSetting) {
//订单关闭售后申请时间 = 当前时间 - 自动关闭售后申请天数
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoEvaluation());
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getCloseAfterSale());
//关闭售后订单=未售后订单+小于订单关闭售后申请时间
QueryWrapper queryWrapper = new QueryWrapper();

View File

@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
@ -54,8 +55,16 @@ public class OnlineMemberStatistics implements EveryHourExecute {
calendar.set(Calendar.MILLISECOND, 0);
Calendar finalCalendar = calendar;
AtomicReference<Integer> lastNum = new AtomicReference<>(0);
onlineMemberVOS = onlineMemberVOS.stream()
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(finalCalendar.getTime()))
.filter(onlineMemberVO -> {
//如果为过滤参数则记录为过期参数则为统一时段上一周期的在线人数
if (!onlineMemberVO.getDate().after(finalCalendar.getTime())) {
lastNum.set(onlineMemberVO.getNum());
}
return onlineMemberVO.getDate().after(finalCalendar.getTime());
})
.collect(Collectors.toList());
//计入新数据
@ -63,7 +72,7 @@ public class OnlineMemberStatistics implements EveryHourExecute {
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size()));
onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size(), lastNum.get()));
//写入缓存
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
@ -95,7 +104,7 @@ public class OnlineMemberStatistics implements EveryHourExecute {
onlineMemberVOS = onlineMemberVOS.stream()
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(calendar.getTime()))
.collect(Collectors.toList());
onlineMemberVOS.add(new OnlineMemberVO(time, num));
onlineMemberVOS.add(new OnlineMemberVO(time, num, num));
//写入缓存
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);

View File

@ -0,0 +1,49 @@
package cn.lili.timetask.handler.impl.store;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
import cn.lili.modules.store.service.StoreService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 店铺信息更新
*
* @author Chopper
* @since 2021/3/15 5:30 下午
*/
@Component
@Slf4j
public class StoreExecute implements EveryDayExecute {
/**
* 店铺
*/
@Autowired
private StoreService storeService;
@Autowired
private GoodsSkuService goodsSkuService;
@Override
public void execute() {
//获取所有开启的店铺
List<Store> storeList = storeService.list(new LambdaQueryWrapper<Store>().eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()));
for (Store store : storeList) {
try {
Long num = goodsSkuService.countSkuNum(store.getId());
storeService.updateStoreGoodsNum(store.getId(), num);
} catch (Exception e) {
log.error("店铺id为{},更新商品数量失败", store.getId(), e);
}
}
}
}

View File

@ -1,4 +1,4 @@
package cn.lili.timetask.handler.impl.storerating;
package cn.lili.timetask.handler.impl.store;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.modules.member.entity.dos.MemberEvaluation;

View File

@ -67,7 +67,7 @@ spring:
default-datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: lilishop
maxActive: 20

651
deploy-api.yml Normal file
View File

@ -0,0 +1,651 @@
apiVersion: v1
kind: Namespace
metadata:
name: lilishop-service
---
apiVersion: v1
kind: Service
metadata:
name: buyer-api-service
namespace: lilishop-service
labels:
app.kubernetes.io/name: buyer-api-service
app.kubernetes.io/instance: api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
type: NodePort
ports:
- name: "8888"
nodePort: 30888
port: 8888
targetPort: buyer8888
selector:
lilishop.service: buyer-api
---
apiVersion: v1
kind: Service
metadata:
name: common-api-service
namespace: lilishop-service
labels:
app.kubernetes.io/name: common-api-service
app.kubernetes.io/instance: api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
type: NodePort
ports:
- name: "8890"
nodePort: 30890
port: 8890
targetPort: common8890
selector:
lilishop.service: common-api
---
apiVersion: v1
kind: Service
metadata:
name: seller-api-service
namespace: lilishop-service
labels:
app.kubernetes.io/name: seller-api-service
app.kubernetes.io/instance: api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
type: NodePort
ports:
- name: "8889"
nodePort: 30889
port: 8889
targetPort: seller8889
selector:
lilishop.service: seller-api
---
apiVersion: v1
kind: Service
metadata:
name: manager-api-service
namespace: lilishop-service
labels:
app.kubernetes.io/name: manager-api-service
app.kubernetes.io/instance: api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
type: NodePort
ports:
- name: "8887"
nodePort: 30887
port: 8887
targetPort: manager8887
selector:
lilishop.service: manager-api
---
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: lilishop-service
labels:
app.kubernetes.io/name: mysql-db-config
app.kubernetes.io/instance: mysql-single
app.kubernetes.io/version: "8.0.28"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: lilishop
data:
application.yml: |
server:
servlet:
context-path: /
tomcat:
uri-encoding: UTF-8
threads:
min-spare: 50
max: 1000
# 与Spring Boot 2一样默认情况下大多数端点都不通过http公开我们公开了所有端点。对于生产您应该仔细选择要公开的端点。
management:
# health:
# elasticsearch:
# enabled: false
# datasource:
# enabled: false
endpoints:
web:
exposure:
include: '*'
spring:
# 要在其中注册的Spring Boot Admin Server的URL。
boot:
admin:
client:
url: http://192.168.0.116:8000
cache:
type: redis
# Redis
redis:
host: redis-service.lilishop-middleware
port: 6379
password: lilishop
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制) 默认 8
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-wait: 20
# 连接池中的最大空闲连接 默认 8
max-idle: 10
# 连接池中的最小空闲连接 默认 8
min-idle: 8
# 文件大小上传配置
servlet:
multipart:
max-file-size: 20MB
max-request-size: 20MB
jackson:
time-zone: GMT+8
serialization:
#关闭jackson 对json做解析
fail-on-empty-beans: false
shardingsphere:
datasource:
# 数据库名称,可自定义,可以为多个,以逗号隔开,每个在这里定义的库,都要在下面定义连接属性
names: default-datasource
default-datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql.lilishop-middleware:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: lilishop
maxActive: 50
initialSize: 20
maxWait: 60000
minIdle: 5
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#是否缓存preparedStatement也就是PSCache。在mysql下建议关闭。 PSCache对支持游标的数据库性能提升巨大比如说oracle。
poolPreparedStatements: false
#要启用PSCache-1为关闭 必须配置大于0当大于0时poolPreparedStatements自动触发修改为true 可以把这个数值配置大一些比如说100
maxOpenPreparedStatements: -1
#配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,log4j2
#通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#合并多个DruidDataSource的监控数据
useGlobalDataSourceStat: true
loginUsername: druid
loginPassword: druid
# sharding:
# default-data-source-name: default-datasource
# #需要拆分的表,可以设置多个 在 li_order 级别即可
# tables:
# #需要进行分表的逻辑表名
# li_order:
# #实际的表结点,下面代表的是li_order_为开头的所有表如果能确定表的范围例如按月份分表这里的写法是data2020.li_order_$->{2020..2021}_$->{01..12} 表示例如 li_order_2020_01 li_order_2020_03 li_order_2021_01
# actual-data-nodes: data2020.li_order_$->{2019..2021}_$->{01..12}
# table-strategy:
# # 分表策略,根据创建日期
# standard:
# sharding-column: create_time
# #分表策略
# precise-algorithm-class-name: cn.lili.mybatis.sharding.CreateTimeShardingTableAlgorithm
# #范围查询实现
# range-algorithm-class-name: cn.lili.mybatis.sharding.CreateTimeShardingTableAlgorithm
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
# 忽略鉴权url
ignored:
urls:
- /editor-app/**
- /actuator**
- /actuator/**
- /MP_verify_qSyvBPhDsPdxvOhC.txt
- /weixin/**
- /source/**
- /store/passport/login/**
- /store/passport/login/refresh/**
- /common/common/slider/**
- /common/common/sms/**
- /buyer/payment/cashier/**
- /buyer/other/pageData/**
- /buyer/other/article/**
- /buyer/goods/**
- /buyer/store/**
- /buyer/passport/connect/**
- /buyer/members/**
- /buyer/passport/member/**
- /buyer/passport/member/refresh/**
- /buyer/promotion/pintuan/**
- /buyer/promotion/seckill/**
- /buyer/promotion/pointsGoods/**
- /buyer/promotion/coupon
- /buyer/member/evaluation/**/goodsEvaluation
- /buyer/member/evaluation/**/evaluationNumber
- /buyer/other/appVersion/**
- /buyer/broadcast/studio/**
- /manager/passport/user/login
- /manager/passport/user/refresh/**
- /manager/other/elasticsearch
- /manager/other/customWords
- /druid/**
- /swagger-ui.html
- /doc.html
- /swagger-resources/**
- /swagger/**
- /webjars/**
- /v2/api-docs**
- /configuration/ui
- /boot-admin
- /manager/promotion/seckill/init
- /**/*.js
- /**/*.css
- /**/*.png
- /**/*.ico
# Swagger界面内容配置
swagger:
title: lilishop API接口文档
description: lilishop Api Documentation
version: 4.2.2
termsOfServiceUrl: https://pickmall.cn
contact:
name: lili
url: https://pickmall.cn
email: admin@pickmall.com
# Mybatis-plus
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
configuration:
#缓存开启
cache-enabled: true
#日志
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 日志
logging:
# 输出级别
level:
cn.lili: info
# org.hibernate: debug
# org.springframework: debug
file:
# 指定路径
path: logs
logback:
rollingpolicy:
# 最大保存天数
max-history: 7
# 每个文件最大大小
max-file-size: 5MB
#加密参数
jasypt:
encryptor:
password: lili
lili:
#验证码设置
verification-code:
#图形验证码有效时间 秒 包含滑块验证码有效时间, 以及验证通过之后,缓存中存储的验证结果有效时间
effectiveTime: 300
#水印
watermark: LILI-SHOP
#干扰项数量 最大2 默认0
interfereNum: 1
#允许误差像素
faultTolerant: 3
#短信模版配置
sms:
#登录
LOGIN: SMS_205755300
#注册
REGISTER: SMS_205755298
#找回密码
FIND_USER: SMS_205755301
#设置密码
UPDATE_PASSWORD: SMS_205755297
#支付密码
WALLET_PASSWORD: SMS_205755301
system:
isDemoSite: false
isTestModel: true
# 脱敏级别:
# 0不做脱敏处理
# 1管理端用户手机号等信息脱敏
# 2商家端信息脱敏为2时表示管理端商家端同时脱敏
sensitiveLevel: 1
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48
# 当前在线人数刷新时间间隔单位秒设置为600则每10分钟刷新一次
currentOnlineUpdate: 600
#qq lbs 申请
lbs:
key: 4BYBZ-7MT6S-PUAOA-6BNWL-FJUD7-UUFXT
sk: zhNKVrJK6UPOhqIjn8AQvG37b9sz6
#域名
domain:
pc: http://192.168.0.116:8888
wap: http://192.168.0.116:8888
seller: http://192.168.0.116:8888
admin: http://192.168.0.116:8888
#api地址
api:
buyer: http://192.168.0.116:8888
base: http://192.168.0.116:8888
manager: http://192.168.0.116:8888
seller: http://192.168.0.116:8888
# jwt 细节设定
jwt-setting:
# token过期时间分钟
tokenExpireTime: 30
# 使用Spring @Cacheable注解失效时间
cache:
# 过期时间 单位秒 永久不过期设为-1
timeout: 1500
#多线程配置
thread:
corePoolSize: 5
maxPoolSize: 50
queueCapacity: 50
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: elasticsearch.lilishop-middleware:9200
index:
number-of-replicas: 0
number-of-shards: 3
index-prefix: lili
schema: http
# account:
# username: elastic
# password: LiLiShopES
logstash:
server: logstash-service.lilishop-middleware:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group
msg-ext-topic: lili_msg_topic
msg-ext-group: lili_msg_group
goods-topic: lili_goods_topic
goods-group: lili_goods_group
order-topic: lili_order_topic
order-group: lili_order_group
member-topic: lili_member_topic
member-group: lili_member_group
other-topic: lili_other_topic
other-group: lili_other_group
notice-topic: lili_notice_topic
notice-group: lili_notice_group
notice-send-topic: lili_send_notice_topic
notice-send-group: lili_send_notice_group
after-sale-topic: lili_after_sale_topic
after-sale-group: lili_after_sale_group
rocketmq:
name-server: rocketmq.lilishop-middleware:9876
isVIPChannel: false
producer:
group: lili_group
send-message-timeout: 30000
xxl:
job:
admin:
addresses: http://xxl-job-service.lilishop-middleware:9001/xxl-job-admin
executor:
appname: xxl-job-executor-lilishop
address:
ip:
port: 8891
logpath: ./xxl-job/executor
logretentiondays: 7
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: buyer-api
namespace: lilishop-service
labels:
app.kubernetes.io/name: buyer-api-service
app.kubernetes.io/instance: buyer-api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
replicas: 1
selector:
matchLabels:
lilishop.service: buyer-api
template:
metadata:
labels:
lilishop.service: buyer-api
spec:
containers:
- image: 192.168.0.108:31320/buyer-api:4.2.4.1
name: buyer-api
env:
- name: TZ
value: Asia/Shanghai
- name: JAVA_OPTS
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
ports:
- name: buyer8888
containerPort: 8888
volumeMounts:
- mountPath: /application.yml
name: application-yml
subPath: application.yml
restartPolicy: Always
volumes:
- configMap:
name: api-config
name: application-yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: common-api
namespace: lilishop-service
labels:
app.kubernetes.io/name: common-api-service
app.kubernetes.io/instance: common-api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
replicas: 1
selector:
matchLabels:
lilishop.service: common-api
template:
metadata:
labels:
lilishop.service: common-api
spec:
containers:
- image: 192.168.0.108:31320/common-api:4.2.4.1
name: common-api
env:
- name: TZ
value: Asia/Shanghai
- name: JAVA_OPTS
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
ports:
- name: common8890
containerPort: 8890
volumeMounts:
- mountPath: /application.yml
name: application-yml
subPath: application.yml
restartPolicy: Always
volumes:
- configMap:
name: api-config
name: application-yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: seller-api
namespace: lilishop-service
labels:
app.kubernetes.io/name: seller-api-service
app.kubernetes.io/instance: seller-api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
replicas: 1
selector:
matchLabels:
lilishop.service: seller-api
template:
metadata:
labels:
lilishop.service: seller-api
spec:
containers:
- image: 192.168.0.108:31320/seller-api:4.2.4.1
name: seller-api
env:
- name: TZ
value: Asia/Shanghai
- name: JAVA_OPTS
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
ports:
- name: seller8889
containerPort: 8889
volumeMounts:
- mountPath: /application.yml
name: application-yml
subPath: application.yml
restartPolicy: Always
volumes:
- configMap:
name: api-config
name: application-yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: manager-api
namespace: lilishop-service
labels:
app.kubernetes.io/name: manager-api-service
app.kubernetes.io/instance: manager-api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
replicas: 1
selector:
matchLabels:
lilishop.service: manager-api
template:
metadata:
labels:
lilishop.service: manager-api
spec:
containers:
- image: 192.168.0.108:31320/manager-api:4.2.4.1
name: manager-api
env:
- name: TZ
value: Asia/Shanghai
- name: JAVA_OPTS
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
ports:
- name: manager8887
containerPort: 8887
volumeMounts:
- mountPath: /application.yml
name: application-yml
subPath: application.yml
restartPolicy: Always
volumes:
- configMap:
name: api-config
name: application-yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: consumer
namespace: lilishop-service
labels:
app.kubernetes.io/name: consumer-service
app.kubernetes.io/instance: buyer-api
app.kubernetes.io/version: "4.2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: lilishop
tier: "api-service"
spec:
replicas: 1
selector:
matchLabels:
lilishop.service: consumer
template:
metadata:
labels:
lilishop.service: consumer
spec:
containers:
- image: 192.168.0.108:31320/consumer:4.2.4.1
name: consumer
env:
- name: TZ
value: Asia/Shanghai
- name: JAVA_OPTS
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
volumeMounts:
- mountPath: /application.yml
name: application-yml
subPath: application.yml
restartPolicy: Always
volumes:
- configMap:
name: api-config
name: application-yml

View File

@ -132,6 +132,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- Redis-->
<dependency>
@ -143,6 +144,12 @@
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -422,6 +429,13 @@
</exclusions>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
</dependencies>

View File

@ -465,16 +465,19 @@ public enum CachePrefix {
*/
INIT_INDEX_FLAG,
/**
* 店铺
*/
STORE,
/**
* 店铺分类
*/
STORE_CATEGORY,
/**
* 用户菜单
*/
MENU_USER_ID,
/**
* 用户菜单
* <p>
* 这个缓存并非永久缓存而是300秒缓存也就是说修改用户关联的部门关联的角色
* 部门关联的角色角色关联的菜单等等最多需要5分钟才能生效
*/
STORE_MENU_USER_ID,
/**

View File

@ -6,6 +6,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 要实现对象的缓存定义自己的序列化和反序列化器使用阿里的fastjson来实现的比较多
@ -13,8 +14,8 @@ import java.nio.charset.Charset;
* @author Bulbasaur
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private final Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
super();
@ -26,7 +27,10 @@ public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
if (null == t) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
return JSON.toJSONString(t,
SerializerFeature.WriteClassName,
SerializerFeature.DisableCircularReferenceDetect)
.getBytes(DEFAULT_CHARSET);
}
@Override

View File

@ -11,7 +11,6 @@ import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -56,13 +55,11 @@ import java.util.Map;
public class RedisConfig extends CachingConfigurerSupport {
private static final String REDIS_PREFIX = "redis://";
@Value("${lili.cache.timeout:7200}")
private Integer timeout;
@Autowired
private RedisProperties redisProperties;
/**
* 当有多个管理器的时候必须使用该注解在一个管理器上注释表示该管理器为默认的管理器
*
@ -101,7 +98,7 @@ public class RedisConfig extends CachingConfigurerSupport {
public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
//value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
@ -113,16 +110,15 @@ public class RedisConfig extends CachingConfigurerSupport {
}
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() {
public RedissonClient redisson(RedisProperties redisProperties) {
Config config = new Config();
if (redisProperties.getSentinel() != null && !redisProperties.getSentinel().getNodes().isEmpty()) {
// 哨兵模式
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
sentinelServersConfig.setMasterName(redisProperties.getSentinel().getMaster());
List<String> sentinelAddress = new ArrayList<>();
for (String node : redisProperties.getCluster().getNodes()) {
sentinelAddress.add("redis://" + node);
sentinelAddress.add(REDIS_PREFIX + node);
}
sentinelServersConfig.setSentinelAddresses(sentinelAddress);
if (CharSequenceUtil.isNotEmpty(redisProperties.getSentinel().getPassword())) {
@ -133,7 +129,7 @@ public class RedisConfig extends CachingConfigurerSupport {
ClusterServersConfig clusterServersConfig = config.useClusterServers();
List<String> clusterNodes = new ArrayList<>();
for (String node : redisProperties.getCluster().getNodes()) {
clusterNodes.add("redis://" + node);
clusterNodes.add(REDIS_PREFIX + node);
}
clusterServersConfig.setNodeAddresses(clusterNodes);
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
@ -141,10 +137,11 @@ public class RedisConfig extends CachingConfigurerSupport {
}
} else {
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort());
singleServerConfig.setAddress(REDIS_PREFIX + redisProperties.getHost() + ":" + redisProperties.getPort());
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
singleServerConfig.setPassword(redisProperties.getPassword());
}
singleServerConfig.setPingConnectionInterval(1000);
}
return Redisson.create(config);

View File

@ -0,0 +1,25 @@
package cn.lili.common.aop.annotation;
import java.lang.annotation.*;
/**
* 异常重试注解
*
* @author paulG
* @since 2022/4/26
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RetryOperation {
/**
* 重试次数
*/
int retryCount() default 3;
/**
* 重试间隔
*/
int waitSeconds() default 10;
}

View File

@ -1,13 +1,5 @@
package cn.lili.common.aop.interceptor;
/**
* 防重复提交业务
*
* @author Chopper
* @version v1.0
* 2022-01-25 09:20
*/
import cn.lili.cache.Cache;
import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
import cn.lili.common.enums.ResultCode;
@ -23,6 +15,13 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 防重复提交业务
*
* @author Chopper
* @version v1.0
* 2022-01-25 09:20
*/
@Aspect
@Component
@Slf4j
@ -37,8 +36,8 @@ public class PreventDuplicateSubmissionsInterceptor {
try {
Long count = cache.incr(getParams(), preventDuplicateSubmissions.expire());
//如果超过1或者设置的参数则表示重复提交了
if (count.intValue() >= preventDuplicateSubmissions.expire()) {
//如果超过2或者设置的参数则表示重复提交了
if (count.intValue() >= 2) {
throw new ServiceException(ResultCode.LIMIT_ERROR);
}
}

View File

@ -0,0 +1,50 @@
package cn.lili.common.aop.interceptor;
import cn.lili.common.aop.annotation.RetryOperation;
import cn.lili.common.exception.RetryException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
* @author paulG
* @since 2022/4/26
**/
@Aspect
@Component
@Slf4j
public class RetryAspect {
@Around(value = "@annotation(retryOperation)")
public Object retryOperation(ProceedingJoinPoint joinPoint, RetryOperation retryOperation) throws Throwable {
Object response = null;
int retryCount = retryOperation.retryCount();
int waitSeconds = retryOperation.waitSeconds();
boolean successful = false;
do {
try {
response = joinPoint.proceed();
successful = true;
} catch (RetryException ex) {
log.info("Operation failed, retries remaining: {}", retryCount);
retryCount--;
if (retryCount < 0) {
successful = true;
log.error(ex.getMessage());
}
if (waitSeconds > 0 && !successful) {
log.info("Waiting for {} second(s) before next retry", waitSeconds);
Thread.sleep(waitSeconds * 1000L);
}
}
} while (!successful);
return response;
}
}

View File

@ -40,6 +40,7 @@ public enum ResultCode {
FILE_TYPE_NOT_SUPPORT(1010, "不支持上传的文件类型!"),
PLATFORM_NOT_SUPPORTED_IM(1006, "平台未开启IM"),
STORE_NOT_SUPPORTED_IM(1007, "店铺未开启IM"),
UNINITIALIZED_PASSWORD(1008, "非初始化密码,无法进行初始化设置"),
/**
* 分类
*/
@ -75,9 +76,13 @@ public enum ResultCode {
GOODS_SKU_QUANTITY_ERROR(11011, "商品库存数量不能为负数"),
GOODS_SKU_QUANTITY_NOT_ENOUGH(11011, "商品库存不足"),
MUST_HAVE_GOODS_SKU(11012, "规格必须要有一个!"),
MUST_HAVE_SALES_MODEL(11022, "销售模式为批发时必须要有批发规则!"),
HAVE_INVALID_SALES_MODEL(11023, "批发规则存在小于等于0的无效数据"),
GOODS_PARAMS_ERROR(11013, "商品参数错误,刷新后重试"),
PHYSICAL_GOODS_NEED_TEMP(11014, "实物商品需选择配送模板"),
VIRTUAL_GOODS_NOT_NEED_TEMP(11015, "实物商品需选择配送模板"),
VIRTUAL_GOODS_NOT_NEED_TEMP(11015, "虚拟商品无需选择配送模板"),
GOODS_NOT_EXIST_STORE(11017, "当前用户无权操作此商品"),
GOODS_TYPE_ERROR(11016, "需选择商品类型"),
@ -187,6 +192,7 @@ public enum ResultCode {
MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"),
ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"),
ORDER_NOT_SUPPORT_DISTRIBUTION(31011, "购物车中包含不支持配送的商品,请重新选择收货地址,或者重新选择商品"),
ORDER_NOT_EXIST_VALID(31041, "购物车中无有效商品,请检查购物车内商品,或者重新选择商品"),
ORDER_CAN_NOT_CANCEL(31012, "当前订单状态不可取消"),
ORDER_BATCH_DELIVER_ERROR(31013, "批量发货,文件读取失败"),
ORDER_ITEM_NOT_EXIST(31014, "当前订单项不存在!"),
@ -258,6 +264,7 @@ public enum ResultCode {
*/
PROMOTION_GOODS_NOT_EXIT(40000, "当前促销商品不存在!"),
PROMOTION_GOODS_QUANTITY_NOT_EXIT(40020, "当前促销商品库存不足!"),
PROMOTION_GOODS_DO_NOT_JOIN_WHOLESALE(40050, "批发商品无法参加促销"),
PROMOTION_SAME_ACTIVE_EXIST(40001, "活动时间内已存在同类活动,请选择关闭、删除当前时段的活动"),
PROMOTION_START_TIME_ERROR(40002, "活动起始时间不能小于当前时间"),
PROMOTION_END_TIME_ERROR(40003, "活动结束时间不能小于当前时间"),
@ -282,11 +289,6 @@ public enum ResultCode {
COUPON_RECEIVE_ERROR(41005, "当前优惠券已经被领取完了,下次要早点来哦"),
COUPON_NUM_INSUFFICIENT_ERROR(41006, "优惠券剩余领取数量不足"),
COUPON_NOT_EXIST(41007, "当前优惠券不存在"),
COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"),
COUPON_ACTIVITY_NOT_EXIST(410022, "当前优惠券活动不存在"),
COUPON_SAVE_ERROR(41020, "保存优惠券失败"),
COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"),
COUPON_DELETE_ERROR(41021, "删除优惠券失败"),
COUPON_LIMIT_NUM_LESS_THAN_0(41008, "领取限制数量不能为负数"),
COUPON_LIMIT_GREATER_THAN_PUBLISH(41009, "领取限制数量超出发行数量"),
COUPON_DISCOUNT_ERROR(41010, "优惠券折扣必须小于10且大于0"),
@ -297,6 +299,15 @@ public enum ResultCode {
COUPON_MEMBER_NOT_EXIST(41015, "没有当前会员优惠券"),
COUPON_MEMBER_STATUS_ERROR(41016, "当前会员优惠券已过期/作废无法变更状态!"),
SPECIAL_CANT_USE(41019, "特殊商品不能使用优惠券,不能使用"),
COUPON_SAVE_ERROR(41020, "保存优惠券失败"),
COUPON_DELETE_ERROR(41021, "删除优惠券失败"),
COUPON_ACTIVITY_NOT_EXIST(41022, "当前优惠券活动不存在"),
COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"),
COUPON_ACTIVITY_MAX_NUM(41024, "优惠券活动赠券数量最多为3"),
COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"),
/**
* 拼团

View File

@ -0,0 +1,32 @@
package cn.lili.common.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
/**
* 事务提交后发生mq事件
*
* @author paulG
* @since 2022/1/19
**/
public class TransactionCommitSendMQEvent extends ApplicationEvent {
private static final long serialVersionUID = 5885956821347953071L;
@Getter
private final String topic;
@Getter
private final String tag;
@Getter
private final Object message;
public TransactionCommitSendMQEvent(Object source, String topic, String tag, Object message) {
super(source);
this.topic = topic;
this.tag = tag;
this.message = message;
}
}

View File

@ -0,0 +1,21 @@
package cn.lili.common.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 如需异常重试则抛出此异常
*
* @author paulG
* @since 2022/4/26
**/
@EqualsAndHashCode(callSuper = true)
@Data
public class RetryException extends RuntimeException {
private static final long serialVersionUID = 7886918292771470846L;
public RetryException(String message) {
super(message);
}
}

View File

@ -0,0 +1,38 @@
package cn.lili.common.listener;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
/**
* 事务提交监听器
*
* @author paulG
* @since 2022/1/19
**/
@Component
@Slf4j
public class TransactionCommitSendMQListener {
/**
* rocketMq
*/
@Autowired
private RocketMQTemplate rocketMQTemplate;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void send(TransactionCommitSendMQEvent event) {
log.info("事务提交发送mq信息!{}", event);
String destination = event.getTopic() + ":" + event.getTag();
//发送订单变更mq消息
rocketMQTemplate.asyncSend(destination, event.getMessage(), RocketmqSendCallbackBuilder.commonCallback());
}
}

View File

@ -1,7 +1,7 @@
package cn.lili.common.utils;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
/**
* 通用工具
@ -9,6 +9,8 @@ import java.util.UUID;
*/
public class CommonUtil {
public static final String BASE_NUMBER = "0123456789";
/**
* 以UUID重命名
* @param fileName 文件名称
@ -24,12 +26,12 @@ public class CommonUtil {
* 随机6位数生成
*/
public static String getRandomNum() {
Random random = new Random();
int num = random.nextInt(999999);
//不足六位前面补0
String str = String.format("%06d", num);
return str;
StringBuilder sb = new StringBuilder(6);
for (int i = 0; i < 6; i++) {
int num = ThreadLocalRandom.current().nextInt(BASE_NUMBER.length());
sb.append(BASE_NUMBER.charAt(num));
}
return sb.toString();
}
}

View File

@ -20,6 +20,23 @@ public class DateUtil {
public static final String FULL_DATE = "yyyyMMddHHmmss";
/**
* 当天的开始时间
*
* @return 今天开始时间
*/
public static Long getDayOfStart() {
return DateUtil.getDateline()/(60*24*60);
}
/**
* 指定日的开始时间
*
* @return 指定日时间
*/
public static Long getDayOfStart(Date date) {
return date.getTime()/(60*24*60);
}
/**
* 当天的开始时间
*

View File

@ -147,6 +147,20 @@ public class StringUtils extends StrUtil {
return str.concat(appendStr);
}
/**
* 切割字符串
*
* @param str 字符串
* @param length 长度
* @return 处理后的字符串
*/
public static String sub(String str, Integer length) {
if (str.length() < length) {
return str;
}
return str.substring(0, length);
}
/**
* 过滤特殊字符串
*

View File

@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author paulG
@ -124,7 +123,7 @@ public abstract class BaseElasticsearchService {
" \"type\": \"keyword\"\n" +
" },\n" +
" \"type\": {\n" +
" \"type\": \"long\"\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"value\": {\n" +
" \"type\": \"keyword\"\n" +
@ -165,14 +164,8 @@ public abstract class BaseElasticsearchService {
" \"type\": \"long\"\n" +
" },\n" +
" \"releaseTime\": {\n" +
" \"type\": \"text\",\n" +
" \"fielddata\": true, \n" +
" \"fields\": {\n" +
" \"keyword\": {\n" +
" \"type\": \"keyword\",\n" +
" \"ignore_above\": 256\n" +
" }\n" +
" }\n" +
" \"type\": \"date\",\n" +
" \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\"\n" +
" },\n" +
" \"categoryPath\": {\n" +
" \"type\": \"text\",\n" +
@ -348,20 +341,20 @@ public abstract class BaseElasticsearchService {
PutMappingRequest request = new PutMappingRequest(index).source(source, XContentType.JSON);
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<AcknowledgedResponse> response = new AtomicReference<>();
client.indices().putMappingAsync(
request,
RequestOptions.DEFAULT,
new ActionListener<AcknowledgedResponse>() {
@Override
public void onResponse(AcknowledgedResponse r) {
response.set(r);
latch.countDown();
log.info("创建索引mapping成功{}", r);
}
@Override
public void onFailure(Exception e) {
latch.countDown();
log.error("创建索引mapping失败", e);
}
});
latch.await(10, TimeUnit.SECONDS);

View File

@ -16,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import javax.annotation.PreDestroy;
import java.io.IOException;
@ -69,11 +68,6 @@ public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
return client;
}
@Bean("elasticsearchRestTemplate")
public ElasticsearchRestTemplate elasticsearchRestTemplate() {
return new ElasticsearchRestTemplate(this.client);
}
private HttpHost[] getHttpHosts() {
List<String> clusterNodes = elasticsearchProperties.getClusterNodes();
HttpHost[] httpHosts = new HttpHost[clusterNodes.size()];

View File

@ -112,4 +112,11 @@ public interface ConnectService extends IService<Connect> {
* @return
*/
Connect queryConnect(ConnectQueryDTO connectQueryDTO);
/**
* 根据会员id删除记录
*
* @param userId 会员id
*/
void deleteByMemberId(String userId);
}

View File

@ -8,7 +8,9 @@ import cn.lili.cache.CachePrefix;
import cn.lili.common.context.ThreadContextHolder;
import cn.lili.common.enums.ClientTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.token.Token;
@ -29,11 +31,13 @@ import cn.lili.modules.system.entity.dto.connect.WechatConnectSetting;
import cn.lili.modules.system.entity.dto.connect.dto.WechatConnectSettingItem;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.rocketmq.tags.MemberTagsEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -66,6 +70,14 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
private MemberTokenGenerate memberTokenGenerate;
@Autowired
private Cache cache;
/**
* RocketMQ 配置
*/
@Autowired
private RocketmqCustomProperties rocketmqCustomProperties;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
@Transactional(rollbackFor = Exception.class)
@ -89,6 +101,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
}
return memberTokenGenerate.createToken(member, longTerm);
} catch (NoPermissionException e) {
log.error("联合登陆失败:", e);
throw e;
}
}
@ -121,7 +134,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
@Override
public void bind(String unionId, String type) {
AuthUser authUser = UserContext.getCurrentUser();
AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
Connect connect = new Connect(authUser.getId(), unionId, type);
this.save(connect);
}
@ -160,6 +173,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
@Override
@Transactional
public Token miniProgramAutoLogin(WechatMPLoginParams params) {
Object cacheData = cache.get(CachePrefix.WECHAT_SESSION_PARAMS.getPrefix() + params.getUuid());
@ -186,8 +200,8 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
/**
* 通过微信返回等code 获取openid 等信息
*
* @param code
* @return
* @param code 微信code
* @return 微信返回的信息
*/
public JSONObject getConnect(String code) {
WechatConnectSettingItem setting = getWechatMPSetting();
@ -208,11 +222,12 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
* @param params 微信小程序自动登录参数
* @param openId 微信openid
* @param unionId 微信unionid
* @return
* @return token
*/
@Transactional(rollbackFor = Exception.class)
public Token phoneMpBindAndLogin(String sessionKey, WechatMPLoginParams params, String openId, String unionId) {
String encryptedData = params.getEncryptedData(), iv = params.getIv();
String encryptedData = params.getEncryptedData();
String iv = params.getIv();
JSONObject userInfo = this.getUserInfo(encryptedData, sessionKey, iv);
log.info("联合登陆返回:{}", userInfo.toString());
String phone = (String) userInfo.get("purePhoneNumber");
@ -232,6 +247,8 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
memberService.save(newMember);
newMember = memberService.findByUsername(newMember.getUsername());
bindMpMember(openId, unionId, newMember);
// 发送会员注册信息
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), newMember));
return memberTokenGenerate.createToken(newMember, true);
}
@ -245,6 +262,13 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
return this.getOne(queryWrapper);
}
@Override
public void deleteByMemberId(String userId) {
LambdaQueryWrapper<Connect> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Connect::getUserId, userId);
this.remove(queryWrapper);
}
/**
* 会员绑定 绑定微信小程序
* <p>
@ -252,9 +276,9 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
* 这样微信小程序注册之后其他app 公众号页面都可以实现绑定自动登录功能
* </p>
*
* @param openId
* @param unionId
* @param member
* @param openId 微信openid
* @param unionId 微信unionid
* @param member 会员
*/
private void bindMpMember(String openId, String unionId, Member member) {
@ -265,7 +289,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
lambdaQueryWrapper.eq(Connect::getUnionId, unionId);
lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT.name());
List<Connect> connects = this.list(lambdaQueryWrapper);
if (connects.size() == 0) {
if (connects.isEmpty()) {
Connect connect = new Connect();
connect.setUnionId(unionId);
connect.setUserId(member.getId());
@ -274,7 +298,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
}
}//如果openid 不为空 则为账号绑定openid
if (CharSequenceUtil.isNotEmpty(openId)) {
LambdaQueryWrapper<Connect> lambdaQueryWrapper = new LambdaQueryWrapper();
LambdaQueryWrapper<Connect> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(Connect::getUnionId, openId);
lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT_MP_OPEN_ID.name());
List<Connect> connects = this.list(lambdaQueryWrapper);

View File

@ -50,6 +50,9 @@ public class DistributionOrder extends BaseIdEntity {
private String distributionId;
@ApiModelProperty(value = "分销员名称")
private String distributionName;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "解冻日期")
private Date settleCycle;
@ApiModelProperty(value = "提成金额")

View File

@ -73,6 +73,7 @@ public class DistributionCashServiceImpl extends ServiceImpl<DistributionCashMap
}
//将提现金额存入冻结金额,扣减可提现金额
distribution.setCanRebate(CurrencyUtil.sub(distribution.getCanRebate(), applyMoney));
distribution.setCommissionFrozen(CurrencyUtil.add(distribution.getCommissionFrozen(), applyMoney));
distributionService.updateById(distribution);
//提现申请记录
DistributionCash distributionCash = new DistributionCash("D" + SnowFlake.getId(), distribution.getId(), applyMoney, distribution.getMemberName());

View File

@ -94,6 +94,9 @@ public class DistributionOrderServiceImpl extends ServiceImpl<DistributionOrderM
//循环店铺流水记录判断是否包含分销商品
//包含分销商品则进行记录分销订单计算分销总额
for (StoreFlow storeFlow : storeFlowList) {
if (storeFlow.getDistributionRebate() == null || storeFlow.getDistributionRebate() == 0) {
continue;
}
rebate = CurrencyUtil.add(rebate, storeFlow.getDistributionRebate());
DistributionOrder distributionOrder = new DistributionOrder(storeFlow);
distributionOrder.setDistributionId(order.getDistributionId());

View File

@ -0,0 +1,17 @@
package cn.lili.modules.file.entity.enums;
import com.aliyun.oss.OSS;
/**
* OssEnum
*
* @author Chopper
* @version v1.0
* 2022-06-06 11:23
*/
public enum OssEnum {
/**
*
*/
ALI_OSS, MINIO;
}

View File

@ -1,16 +1,23 @@
package cn.lili.modules.file.plugin;
import cn.lili.modules.file.entity.enums.OssEnum;
import java.io.InputStream;
import java.util.List;
/**
* 文件管理插件
* 文件插件接口
*
* @author Chopper
*/
public interface FileManagerPlugin {
public interface FilePlugin {
/**
* 插件名称
*/
OssEnum pluginName();
/**
* 文件路径上传
*

View File

@ -0,0 +1,59 @@
package cn.lili.modules.file.plugin;
import cn.hutool.json.JSONUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.file.entity.enums.OssEnum;
import cn.lili.modules.file.plugin.impl.AliFilePlugin;
import cn.lili.modules.file.plugin.impl.MinioFilePlugin;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OssSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 文件服务抽象工厂 直接返回操作类
*
* @author Chopper
* @version v1.0
* 2022-06-06 11:35
*/
@Component
public class FilePluginFactory {
@Autowired
private SettingService settingService;
/**
* 获取oss client
*
* @return
*/
public FilePlugin filePlugin() {
OssSetting ossSetting = null;
try {
Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
ossSetting = JSONUtil.toBean(setting.getSettingValue(), OssSetting.class);
switch (OssEnum.valueOf(ossSetting.getType())) {
case MINIO:
return new MinioFilePlugin(ossSetting);
case ALI_OSS:
return new AliFilePlugin(ossSetting);
default:
throw new ServiceException();
}
} catch (Exception e) {
throw new ServiceException();
}
}
}

View File

@ -1,23 +1,17 @@
package cn.lili.modules.file.plugin.impl;
import cn.hutool.core.util.StrUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.file.entity.enums.OssEnum;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.system.entity.dto.OssSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.InputStream;
@ -29,28 +23,19 @@ import java.util.List;
* @author Chopper
*/
@Component
@Slf4j
public class AliFileManagerPlugin implements FileManagerPlugin {
public class AliFilePlugin implements FilePlugin {
@Autowired
private SettingService settingService;
private OssSetting ossSetting;
/**
* 下一个初始化配置参数的时间
* 这里为了防止多次调用redis减少与redis的交互时间
*/
private static Long nextInitSetting;
public AliFilePlugin(OssSetting ossSetting) {
this.ossSetting = ossSetting;
}
/**
* 暂时设定3分账请求一次设置
*/
private static final Long INTERVAL = 60 * 3 * 1000L;
/**
* 静态设置最快三分钟更新一次
*/
private static OssSetting ossSetting;
@Override
public OssEnum pluginName() {
return OssEnum.ALI_OSS;
}
/**
* 获取oss client
@ -58,32 +43,12 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
* @return
*/
private OSS getOssClient() {
OssSetting ossSetting = getSetting();
return new OSSClientBuilder().build(
ossSetting.getEndPoint(),
ossSetting.getAccessKeyId(),
ossSetting.getAccessKeySecret());
}
/**
* 获取配置
*
* @return
*/
private OssSetting getSetting() {
//如果没有配置或者没有下次刷新时间或者下次刷新时间小于当前时间则从redis 更新一次
if (ossSetting == null || nextInitSetting == null || nextInitSetting < System.currentTimeMillis()) {
Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
if (setting == null || StrUtil.isBlank(setting.getSettingValue())) {
throw new ServiceException(ResultCode.OSS_NOT_EXIST);
}
nextInitSetting = System.currentTimeMillis() + INTERVAL;
ossSetting = new Gson().fromJson(setting.getSettingValue(), OssSetting.class);
return ossSetting;
}
return ossSetting;
}
/**
* 获取配置前缀
@ -91,7 +56,6 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
* @return
*/
private String getUrlPrefix() {
OssSetting ossSetting = getSetting();
return "https://" + ossSetting.getBucketName() + "." + ossSetting.getEndPoint() + "/";
}
@ -130,7 +94,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
try {
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("image/jpg");
ossClient.putObject(getSetting().getBucketName(), key, inputStream, meta);
ossClient.putObject(ossSetting.getBucketName(), key, inputStream, meta);
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
@ -161,7 +125,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
try {
ossClient.deleteObjects(
new DeleteObjectsRequest(getSetting().getBucketName()).withKeys(key));
new DeleteObjectsRequest(ossSetting.getBucketName()).withKeys(key));
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");

View File

@ -0,0 +1,165 @@
package cn.lili.modules.file.plugin.impl;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.file.entity.enums.OssEnum;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.system.entity.dto.OssSetting;
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.messages.DeleteObject;
import lombok.extern.slf4j.Slf4j;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* MINIO文件插件
*
* @author liushuai(liushuai711 @ gmail.com)
* @version v4.0
* @Description:
* @since 2022/6/6 17:45
*/
@Slf4j
public class MinioFilePlugin implements FilePlugin {
private OssSetting ossSetting;
public MinioFilePlugin(OssSetting ossSetting) {
this.ossSetting = ossSetting;
}
/**
* 桶占位符
*/
private static final String BUCKET_PARAM = "${bucket}";
/**
* bucket权限-只读
*/
private static final String READ_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
/**
* bucket权限-只读
*/
private static final String WRITE_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
/**
* bucket权限-读写
*/
private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
private MinioClient minioClient;
@Override
public OssEnum pluginName() {
return OssEnum.MINIO;
}
@Override
public String pathUpload(String filePath, String key) {
try {
return this.inputStreamUpload(new FileInputStream(filePath), key);
} catch (Exception e) {
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
}
@Override
public String inputStreamUpload(InputStream inputStream, String key) {
String bucket = "";
try {
MinioClient client = getOssClient();
bucket = ossSetting.getM_bucketName();
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucket).stream(inputStream, inputStream.available(), 5 * 1024 * 1024)
.object(key)
.contentType("image/png" )
.build();
client.putObject(putObjectArgs);
} catch (Exception e) {
log.error("上传失败2", e);
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
//拼接出可访问的url地址
return ossSetting.getM_frontUrl() + "/" + bucket + "/" + key;
}
@Override
public void deleteFile(List<String> key) {
if (key == null || key.isEmpty()) {
return;
}
MinioClient ossClient = getOssClient();
List<DeleteObject> objectList = key.stream().map(DeleteObject::new).collect(Collectors.toList());
ossClient.removeObjects(RemoveObjectsArgs.builder().objects(objectList).bucket(ossSetting.getM_bucketName()).build());
}
/**
* 获取oss client
*
* @return
*/
private MinioClient getOssClient() {
if (minioClient != null) {
return this.minioClient;
}
synchronized (this) {
if (minioClient == null) {
//创建客户端
this.minioClient = MinioClient.builder()
.endpoint(ossSetting.getM_endpoint())
.credentials(ossSetting.getM_accessKey(), ossSetting.getM_secretKey())
.build();
try {
//查看对应的bucket是否已经存在不存在则创建
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(ossSetting.getM_bucketName()).build())) {
//创建bucket
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(ossSetting.getM_bucketName()).build();
this.minioClient.makeBucket(makeBucketArgs);
setBucketPolicy(this.minioClient, ossSetting.getM_bucketName(), "read-write" );
log.info("创建minio桶成功{}", ossSetting.getM_bucketName());
}
} catch (Exception e) {
//晴空配置
minioClient = null;
log.error("创建[{}]bucket失败", ossSetting.getM_bucketName());
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
}
}
return minioClient;
}
/**
* 更新桶权限策略
*
* @param bucket
* @param policy 权限
*/
public static void setBucketPolicy(MinioClient client, String bucket, String policy) throws Exception {
switch (policy) {
case "read-only":
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
break;
case "write-only":
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
break;
case "read-write":
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).region("public" ).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
break;
case "none":
default:
break;
}
}
}

View File

@ -10,7 +10,8 @@ import cn.lili.common.vo.SearchVO;
import cn.lili.modules.file.entity.File;
import cn.lili.modules.file.entity.dto.FileOwnerDTO;
import cn.lili.modules.file.mapper.FileMapper;
import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.file.plugin.FilePluginFactory;
import cn.lili.modules.file.service.FileService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -31,7 +32,7 @@ import java.util.List;
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {
@Autowired
private FileManagerPlugin fileManagerPlugin;
private FilePluginFactory filePluginFactory;
@Override
public void batchDelete(List<String> ids) {
@ -42,7 +43,7 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements Fi
List<File> files = this.list(queryWrapper);
List<String> keys = new ArrayList<>();
files.forEach(item -> keys.add(item.getFileKey()));
fileManagerPlugin.deleteFile(keys);
filePluginFactory.filePlugin().deleteFile(keys);
this.remove(queryWrapper);
}
@ -68,7 +69,7 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements Fi
List<File> files = this.list(queryWrapper);
List<String> keys = new ArrayList<>();
files.forEach(item -> keys.add(item.getFileKey()));
fileManagerPlugin.deleteFile(keys);
filePluginFactory.filePlugin().deleteFile(keys);
this.remove(queryWrapper);
}

View File

@ -12,7 +12,6 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Max;
@ -114,6 +113,9 @@ public class DraftGoods extends BaseEntity {
@ApiModelProperty(value = "是否为推荐商品")
private boolean recommend;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
*/
@ApiModelProperty(value = "销售模式")
private String salesModel;

View File

@ -7,7 +7,8 @@ import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.GoodsOperationFuLuDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.enums.GoodsTypeEnum;
import cn.lili.mybatis.BaseEntity;
@ -108,6 +109,9 @@ public class Goods extends BaseEntity {
@ApiModelProperty(value = "运费模板id")
private String templateId;
/**
* @see GoodsAuthEnum
*/
@ApiModelProperty(value = "审核状态")
private String authFlag;
@ -130,6 +134,9 @@ public class Goods extends BaseEntity {
@ApiModelProperty(value = "是否为推荐商品", required = true)
private Boolean recommend;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
*/
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
@ -144,83 +151,15 @@ public class Goods extends BaseEntity {
@JsonIgnore
private String params;
//福禄所需参数
/**
* 商品编号
*/
@Length(max = 30, message = "商品规格编号太长不能超过30个字符")
@ApiModelProperty(value = "商品编号")
private String sn;
/**
* 重量
*/
@ApiModelProperty(value = "重量")
@Max(value = 99999999, message = "重量不能超过99999999")
private Double weight;
public Goods() {
}
/**
* 福禄
* @param goodsOperationDTO
*/
public Goods(GoodsOperationFuLuDTO goodsOperationDTO) {
this.goodsName = goodsOperationDTO.getGoodsName();
this.categoryPath = goodsOperationDTO.getCategoryPath();
this.storeCategoryPath = goodsOperationDTO.getStoreCategoryPath();
this.brandId = goodsOperationDTO.getBrandId();
this.sn = goodsOperationDTO.getSn();
this.price = goodsOperationDTO.getPrice();
this.weight = goodsOperationDTO.getWeight();
this.templateId = goodsOperationDTO.getTemplateId();
this.recommend = goodsOperationDTO.getRecommend();
this.sellingPoint = goodsOperationDTO.getSellingPoint();
this.salesModel = goodsOperationDTO.getSalesModel();
this.goodsUnit = goodsOperationDTO.getGoodsUnit();
this.intro = goodsOperationDTO.getIntro();
this.mobileIntro = goodsOperationDTO.getMobileIntro();
this.goodsVideo = goodsOperationDTO.getGoodsVideo();
this.price = goodsOperationDTO.getPrice();
if (goodsOperationDTO.getGoodsParamsDTOList() != null && goodsOperationDTO.getGoodsParamsDTOList().isEmpty()) {
this.params = JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsDTOList());
}
//如果立即上架则
this.marketEnable = Boolean.TRUE.equals(goodsOperationDTO.getRelease()) ? GoodsStatusEnum.UPPER.name() : GoodsStatusEnum.DOWN.name();
this.goodsType = goodsOperationDTO.getGoodsType();
this.grade = 100D;
//循环sku判定sku是否有效
for (Map<String, Object> sku : goodsOperationDTO.getSkuList()) {
//判定参数不能为空
if (!sku.containsKey("sn") || sku.get("sn") == null) {
throw new ServiceException(ResultCode.GOODS_SKU_SN_ERROR);
}
if (!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) {
throw new ServiceException(ResultCode.GOODS_SKU_PRICE_ERROR);
}
if (!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) {
throw new ServiceException(ResultCode.GOODS_SKU_COST_ERROR);
}
//虚拟商品没有重量字段
if (this.goodsType.equals(GoodsTypeEnum.PHYSICAL_GOODS.name()) && (!sku.containsKey("weight") || sku.containsKey("weight") && (StringUtil.isEmpty(sku.get("weight").toString()) || Convert.toDouble(sku.get("weight").toString()) < 0))) {
throw new ServiceException(ResultCode.GOODS_SKU_WEIGHT_ERROR);
}
if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) {
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR);
}
}
}
public Goods(GoodsOperationDTO goodsOperationDTO) {
this.goodsName = goodsOperationDTO.getGoodsName();
this.categoryPath = goodsOperationDTO.getCategoryPath();
this.storeCategoryPath = goodsOperationDTO.getStoreCategoryPath();
this.brandId = goodsOperationDTO.getBrandId();
this.price = goodsOperationDTO.getPrice();
this.templateId = goodsOperationDTO.getTemplateId();
this.recommend = goodsOperationDTO.getRecommend();
this.sellingPoint = goodsOperationDTO.getSellingPoint();
@ -244,10 +183,10 @@ public class Goods extends BaseEntity {
if (!sku.containsKey("sn") || sku.get("sn") == null) {
throw new ServiceException(ResultCode.GOODS_SKU_SN_ERROR);
}
if (!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) {
if ((!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) && !goodsOperationDTO.getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())) {
throw new ServiceException(ResultCode.GOODS_SKU_PRICE_ERROR);
}
if (!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) {
if ((!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) && !goodsOperationDTO.getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())) {
throw new ServiceException(ResultCode.GOODS_SKU_COST_ERROR);
}
//虚拟商品没有重量字段
@ -275,4 +214,4 @@ public class Goods extends BaseEntity {
return mobileIntro;
}
}
}

View File

@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Max;
@ -24,6 +25,7 @@ import java.util.Date;
@Data
@TableName("li_goods_sku")
@ApiModel(value = "商品sku对象")
@NoArgsConstructor
public class GoodsSku extends BaseEntity {
private static final long serialVersionUID = 4865908658161118934L;
@ -150,6 +152,9 @@ public class GoodsSku extends BaseEntity {
@ApiModelProperty(value = "是否为推荐商品", required = true)
private Boolean recommend;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
*/
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
/**
@ -166,11 +171,43 @@ public class GoodsSku extends BaseEntity {
}
@Override
public Date getUpdateTime() {
if (super.getUpdateTime() == null) {
public Date getCreateTime() {
if (super.getCreateTime() == null) {
return new Date(1593571928);
} else {
return super.getUpdateTime();
return super.getCreateTime();
}
}
/**
* 设置规格商品的基本商品信息
*
* @param goods 基本商品信息
*/
public GoodsSku(Goods goods) {
//商品基本信息
this.goodsId = goods.getId();
this.goodsName = goods.getGoodsName();
this.goodsType = goods.getGoodsType();
this.selfOperated = goods.getSelfOperated();
this.sellingPoint = goods.getSellingPoint();
this.categoryPath = goods.getCategoryPath();
this.brandId = goods.getBrandId();
this.marketEnable = goods.getMarketEnable();
this.intro = goods.getIntro();
this.mobileIntro = goods.getMobileIntro();
this.goodsUnit = goods.getGoodsUnit();
this.grade = 100D;
//商品状态
this.authFlag = goods.getAuthFlag();
this.salesModel = goods.getSalesModel();
//卖家信息
this.storeId = goods.getStoreId();
this.storeName = goods.getStoreName();
this.storeCategoryPath = goods.getStoreCategoryPath();
this.freightTemplateId = goods.getTemplateId();
this.recommend = goods.getRecommend();
}
}

View File

@ -1,5 +1,6 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.modules.goods.entity.enums.GoodsWordsTypeEnum;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
@ -41,7 +42,7 @@ public class GoodsWords extends BaseEntity {
private String abbreviate;
/**
* 类型
* @see GoodsWordsTypeEnum
*/
@ApiModelProperty(value = "类型")
private String type;

View File

@ -1,5 +1,6 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.modules.goods.entity.enums.StudioStatusEnum;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
@ -88,6 +89,9 @@ public class Studio extends BaseEntity {
@ApiModelProperty(value = "推荐直播间")
private boolean recommend;
/**
* @see StudioStatusEnum
*/
@ApiModelProperty(value = "直播间状态")
private String status;
}

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@ -15,11 +16,14 @@ import lombok.NoArgsConstructor;
* @since 2021/5/18 5:42 下午
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "直播间商品")
@TableName("li_studio_commodity")
@NoArgsConstructor
public class StudioCommodity extends BaseIdEntity {
private static final long serialVersionUID = 8383627725577840261L;
@ApiModelProperty(value = "房间ID")
private Integer roomId;

View File

@ -0,0 +1,30 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.mybatis.BaseIdEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author paulG
* @since 2022/5/20
**/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("li_wholesale")
@ApiModel(value = "批发商品")
public class Wholesale extends BaseIdEntity {
private static final long serialVersionUID = -6389806138583086068L;
@ApiModelProperty(value = "商品ID")
private String goodsId;
@ApiModelProperty(value = "SkuID")
private String skuId;
@ApiModelProperty(value = "数量")
private Integer num;
@ApiModelProperty(value = "金额")
private Double price;
}

View File

@ -13,7 +13,7 @@ import java.util.List;
import java.util.Map;
/**
* 商品编辑DTO
* 商品操作DTO
*
* @author pikachu
* @since 2020-02-24 19:27:20
@ -77,13 +77,12 @@ public class GoodsOperationDTO implements Serializable {
@Min(value = 0, message = "运费模板值不正确")
private String templateId;
@ApiModelProperty(value = "sku列表")
@Valid
private List<Map<String, Object>> skuList;
@ApiModelProperty(value = "卖点")
private String sellingPoint;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
*/
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
@ -112,6 +111,17 @@ public class GoodsOperationDTO implements Serializable {
@ApiModelProperty(value = "商品视频")
private String goodsVideo;
@ApiModelProperty(value = "sku列表")
@Valid
private List<Map<String, Object>> skuList;
/**
* 批发商品规则
*/
@ApiModelProperty(value = "批发商品规则")
private List<WholesaleDTO> wholesaleList;
public String getGoodsName() {
//对商品对名称做一个极限处理这里没有用xss过滤是因为xss过滤为全局过滤影响很大
// 业务中全局代码中只有商品名称不能拥有英文逗号是由于商品名称存在一个数据库联合查询结果要根据逗号分组

View File

@ -77,6 +77,12 @@ public class GoodsSearchParams extends PageVO {
@ApiModelProperty(value = "商品类型")
private String goodsType;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
*/
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
public <T> QueryWrapper<T> queryWrapper() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
if (CharSequenceUtil.isNotEmpty(goodsId)) {
@ -121,6 +127,9 @@ public class GoodsSearchParams extends PageVO {
if (CharSequenceUtil.isNotEmpty(goodsType)) {
queryWrapper.eq("goods_type", goodsType);
}
if (CharSequenceUtil.isNotEmpty(salesModel)) {
queryWrapper.eq("sales_model", salesModel);
}
queryWrapper.eq("delete_flag", false);
this.betweenWrapper(queryWrapper);

View File

@ -0,0 +1,25 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author paulG
* @since 2022/6/13
**/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class GoodsSkuDTO extends GoodsSku {
private static final long serialVersionUID = 6600436187015048097L;
@ApiModelProperty(value = "商品参数json")
private String params;
}

View File

@ -0,0 +1,16 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.Wholesale;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author paulG
* @since 2022/5/25
**/
@Data
@EqualsAndHashCode(callSuper = true)
public class WholesaleDTO extends Wholesale {
private static final long serialVersionUID = 853297561151783335L;
}

View File

@ -1,19 +1,14 @@
package cn.lili.modules.goods.entity.enums;
/**
* 商品审核
* 销售模式
*
* @author pikachu
* @since 2020-02-26 23:24:13
*/
public enum GoodsSalesModeEnum {
/**
* 需要审核 并且待审核
*/
RETAIL("零售"),
/**
* 审核通过
*/
WHOLESALE("批发");
private final String description;

View File

@ -5,6 +5,7 @@ import cn.lili.modules.goods.entity.dos.GoodsSku;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.List;
@ -16,6 +17,7 @@ import java.util.List;
* @since 2020-02-26 23:24:13
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class GoodsSkuVO extends GoodsSku {

View File

@ -1,9 +1,11 @@
package cn.lili.modules.goods.entity.vos;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@ -14,6 +16,7 @@ import java.util.List;
* @since 2020-02-26 23:24:13
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class GoodsVO extends Goods {
private static final long serialVersionUID = 6377623919990713567L;
@ -29,4 +32,7 @@ public class GoodsVO extends Goods {
@ApiModelProperty(value = "sku列表")
private List<GoodsSkuVO> skuList;
@ApiModelProperty(value = "批发商品消费规则列表")
private List<Wholesale> wholesaleList;
}

View File

@ -1,19 +0,0 @@
package cn.lili.modules.goods.event;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
/**
* @author paulG
* @since 2022/1/19
**/
@Data
public class GeneratorEsGoodsIndexEvent extends ApplicationEvent {
private String goodsId;
public GeneratorEsGoodsIndexEvent(Object source, String goodsId) {
super(source);
this.goodsId = goodsId;
}
}

View File

@ -1,38 +0,0 @@
package cn.lili.modules.goods.listener;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.modules.goods.event.GeneratorEsGoodsIndexEvent;
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
import cn.lili.rocketmq.tags.GoodsTagsEnum;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
/**
* @author paulG
* @since 2022/1/19
**/
@Component
public class GeneratorEsGoodsIndexListener {
/**
* rocketMq
*/
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* rocketMq配置
*/
@Autowired
private RocketmqCustomProperties rocketmqCustomProperties;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void generatorEsGoodsIndex(GeneratorEsGoodsIndexEvent esGoodsIndexEvent) {
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GENERATOR_GOODS_INDEX.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, esGoodsIndexEvent.getGoodsId(), RocketmqSendCallbackBuilder.commonCallback());
}
}

View File

@ -1,7 +1,13 @@
package cn.lili.modules.goods.mapper;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@ -23,4 +29,89 @@ public interface GoodsSkuMapper extends BaseMapper<GoodsSku> {
@Select("SELECT id FROM li_goods_sku WHERE goods_id = #{goodsId}")
List<String> getGoodsSkuIdByGoodsId(String goodsId);
@Insert("replace into li_goods_sku (\n" +
"\tid,\n" +
"\tgoods_id,\n" +
"\tspecs,\n" +
"\tsimple_specs,\n" +
"\tfreight_template_id,\n" +
"\tgoods_name,\n" +
"\tsn,\n" +
"\tbrand_id,\n" +
"\tcategory_path,\n" +
"\tgoods_unit,\n" +
"\tselling_point,\n" +
"\tweight,\n" +
"\tmarket_enable,\n" +
"\tintro,\n" +
"\tprice,\n" +
"\tcost,\n" +
"\tquantity,\n" +
"\tgrade,\n" +
"\tthumbnail,\n" +
"\tsmall,\n" +
"\tstore_category_path,\n" +
"\tstore_id,\n" +
"\tstore_name,\n" +
"\tauth_flag,\n" +
"\tself_operated,\n" +
"\tmobile_intro,\n" +
"\trecommend,\n" +
"\tsales_model,\n" +
"\tgoods_type,\n" +
"\tcreate_by,\n" +
"\tcreate_time,\n" +
"\tupdate_time,\n" +
"\tdelete_flag \n" +
")\n" +
" VALUES\n" +
"(\n" +
"\t#{goodsSku.id},\n" +
"\t#{goodsSku.goodsId},\n" +
"\t#{goodsSku.specs},\n" +
"\t#{goodsSku.simpleSpecs},\n" +
"\t#{goodsSku.freightTemplateId},\n" +
"\t#{goodsSku.goodsName},\n" +
"\t#{goodsSku.sn},\n" +
"\t#{goodsSku.brandId},\n" +
"\t#{goodsSku.categoryPath},\n" +
"\t#{goodsSku.goodsUnit},\n" +
"\t#{goodsSku.sellingPoint},\n" +
"\t#{goodsSku.weight},\n" +
"\t#{goodsSku.marketEnable},\n" +
"\t#{goodsSku.intro},\n" +
"\t#{goodsSku.price},\n" +
"\t#{goodsSku.cost},\n" +
"\t#{goodsSku.quantity},\n" +
"\t#{goodsSku.grade},\n" +
"\t#{goodsSku.thumbnail},\n" +
"\t#{goodsSku.small},\n" +
"\t#{goodsSku.storeCategoryPath},\n" +
"\t#{goodsSku.storeId},\n" +
"\t#{goodsSku.storeName},\n" +
"\t#{goodsSku.authFlag},\n" +
"\t#{goodsSku.selfOperated},\n" +
"\t#{goodsSku.mobileIntro},\n" +
"\t#{goodsSku.recommend},\n" +
"\t#{goodsSku.salesModel},\n" +
"\t#{goodsSku.goodsType},\n" +
"\t#{goodsSku.createBy},\n" +
"\t#{goodsSku.createTime},\n" +
"\t#{goodsSku.updateTime},\n" +
"\t#{goodsSku.deleteFlag}\n" +
")")
int replaceGoodsSku(@Param("goodsSku") GoodsSku goodsSku);
/**
* 分页查询商品skuDTO
*
* @param page 分页
* @param queryWrapper 查询条件
* @return 售后VO分页
*/
@Select("SELECT *,g.params as params FROM li_goods_sku gs inner join li_goods g on gs.goods_id = g.id ${ew.customSqlSegment}")
IPage<GoodsSkuDTO> queryByParams(IPage<GoodsSkuDTO> page, @Param(Constants.WRAPPER) Wrapper<GoodsSkuDTO> queryWrapper);
}

View File

@ -0,0 +1,11 @@
package cn.lili.modules.goods.mapper;
import cn.lili.modules.goods.entity.dos.Wholesale;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author paulG
* @since 2022/5/24
**/
public interface WholesaleMapper extends BaseMapper<Wholesale> {
}

View File

@ -4,9 +4,6 @@ package cn.lili.modules.goods.service;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.vos.CategoryVO;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import java.util.List;
@ -16,7 +13,6 @@ import java.util.List;
* @author pikachu
* @since 2020-03-02 16:44:56
*/
@CacheConfig(cacheNames = "{category}")
public interface CategoryService extends IService<Category> {
@ -35,7 +31,6 @@ public interface CategoryService extends IService<Category> {
* @param id
* @return
*/
@Cacheable(key = "#id")
Category getCategoryById(String id);
/**
@ -99,7 +94,6 @@ public interface CategoryService extends IService<Category> {
* @param category 商品分类信息
* @return 修改结果
*/
@CacheEvict(key = "#category.id")
void updateCategory(Category category);
/**

View File

@ -36,4 +36,11 @@ public interface GoodsGalleryService extends IService<GoodsGallery> {
*/
List<GoodsGallery> goodsGalleryList(String goodsId);
/**
* 根据商品 id删除商品相册缩略图
*
* @param goodsId 商品ID
*/
void removeByGoodsId(String goodsId);
}

View File

@ -129,6 +129,17 @@ public interface GoodsService extends IService<Goods> {
*/
Boolean updateGoodsMarketAble(List<String> goodsIds, GoodsStatusEnum goodsStatusEnum, String underReason);
/**
* 更新商品上架状态状态
*
* @param storeId 店铺ID
* @param goodsStatusEnum 更新的商品状态
* @param underReason 下架原因
* @return 更新结果
*/
Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason);
/**
* 更新商品上架状态状态
*

View File

@ -3,10 +3,14 @@ package cn.lili.modules.goods.service;
import cn.lili.cache.CachePrefix;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -43,19 +47,18 @@ public interface GoodsSkuService extends IService<GoodsSku> {
/**
* 添加商品sku
*
* @param skuList sku列表
* @param goods 商品信息
* @param goods 商品信息
* @param goodsOperationDTO 商品操作信息
*/
void add(List<Map<String, Object>> skuList, Goods goods);
void add(Goods goods, GoodsOperationDTO goodsOperationDTO);
/**
* 更新商品sku
*
* @param skuList sku列表
* @param goods 商品信息
* @param regeneratorSkuFlag 是否是否重新生成sku
* @param goods 商品信息
* @param goodsOperationDTO 商品操作信息
*/
void update(List<Map<String, Object>> skuList, Goods goods, Boolean regeneratorSkuFlag);
void update(Goods goods, GoodsOperationDTO goodsOperationDTO);
/**
* 更新商品sku
@ -79,6 +82,14 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
GoodsSku getGoodsSkuByIdFromCache(String id);
/**
* 从缓存中获取可参与促销商品
*
* @param skuId skuid
* @return 商品详情
*/
GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId);
/**
* 获取商品sku详情
*
@ -136,6 +147,16 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
IPage<GoodsSku> getGoodsSkuByPage(GoodsSearchParams searchParams);
/**
* 分页查询商品sku信息
*
* @param page 分页参数
* @param queryWrapper 查询参数
* @return 商品sku信息
*/
IPage<GoodsSkuDTO> getGoodsSkuDTOByPage(Page<GoodsSkuDTO> page, Wrapper<GoodsSkuDTO> queryWrapper);
/**
* 列表查询商品sku信息
*
@ -151,6 +172,15 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
void updateGoodsSkuStatus(Goods goods);
/**
* 更新商品sku状态根据店铺id
*
* @param storeId 店铺id
* @param marketEnable 市场启用状态
* @param authFlag 审核状态
*/
void updateGoodsSkuStatusByStoreId(String storeId, String marketEnable, String authFlag);
/**
* 发送生成ES商品索引
*
@ -202,4 +232,20 @@ public interface GoodsSkuService extends IService<GoodsSku> {
* @return 全部skuId的集合
*/
List<String> getSkuIdsByGoodsId(String goodsId);
/**
* 删除并且新增sku即覆盖之前信息
*
* @param goodsSkus 商品sku集合
* @return
*/
boolean deleteAndInsertGoodsSkus(List<GoodsSku> goodsSkus);
/**
* 统计sku总数
*
* @param storeId 店铺id
* @return sku总数
*/
Long countSkuNum(String storeId);
}

View File

@ -70,7 +70,7 @@ public interface StudioService extends IService<Studio> {
* @param status 直播间状态
* @return 直播间分页
*/
IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status);
IPage<StudioVO> studioList(PageVO pageVO, Integer recommend, String status);
/**
* 修改直播间状态

View File

@ -0,0 +1,28 @@
package cn.lili.modules.goods.service;
import cn.lili.modules.goods.entity.dos.Wholesale;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @author paulG
* @since 2022/5/24
**/
public interface WholesaleService extends IService<Wholesale> {
List<Wholesale> findByGoodsId(String goodsId);
Boolean removeByGoodsId(String goodsId);
/**
* 匹配批发规则
*
* @param goodsId 商品规则
* @param num 数量
* @return 批发规则
*/
Wholesale match(String goodsId, Integer num);
}

View File

@ -19,6 +19,9 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -36,6 +39,7 @@ import java.util.stream.Collectors;
* @since 2020-02-23 15:18:56
*/
@Service
@CacheConfig(cacheNames = "{CATEGORY}")
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
private static final String DELETE_FLAG_COLUMN = "delete_flag";
@ -60,6 +64,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
}
@Override
@Cacheable(key = "#id")
public Category getCategoryById(String id) {
return this.getById(id);
}
@ -216,6 +221,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
}
@Override
@CacheEvict(key = "#category.id")
@Transactional(rollbackFor = Exception.class)
public void updateCategory(Category category) {
//判断分类佣金是否正确
@ -242,6 +248,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
@Override
@CacheEvict(key = "#id")
@Transactional(rollbackFor = Exception.class)
public void delete(String id) {
this.removeById(id);
@ -253,6 +260,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
}
@Override
@CacheEvict(key = "#categoryId")
@Transactional(rollbackFor = Exception.class)
public void updateCategoryStatus(String categoryId, Boolean enableOperations) {
//禁用子分类
@ -335,7 +343,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
return item.getChildren();
}
if (item.getChildren() != null && !item.getChildren().isEmpty()) {
return getChildren(parentId, categoryVOList);
return getChildren(parentId, item.getChildren());
}
}
return categoryVOList;
@ -346,5 +354,6 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
*/
private void removeCache() {
cache.remove(CachePrefix.CATEGORY.getPrefix());
cache.remove(CachePrefix.CATEGORY_ARRAY.getPrefix());
}
}

View File

@ -75,4 +75,14 @@ public class GoodsGalleryServiceImpl extends ServiceImpl<GoodsGalleryMapper, Goo
//根据商品id查询商品相册
return this.baseMapper.selectList(new QueryWrapper<GoodsGallery>().eq("goods_id", goodsId));
}
/**
* 根据商品 id删除商品相册缩略图
*
* @param goodsId 商品ID
*/
@Override
public void removeByGoodsId(String goodsId) {
this.baseMapper.delete(new UpdateWrapper<GoodsGallery>().eq("goods_id", goodsId));
}
}

View File

@ -1,5 +1,6 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
@ -14,6 +15,7 @@ import cn.lili.common.security.enums.UserEnums;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsGallery;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.GoodsOperationFuLuDTO;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
@ -23,10 +25,7 @@ import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
import cn.lili.modules.goods.entity.vos.GoodsVO;
import cn.lili.modules.goods.mapper.GoodsMapper;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsGalleryService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.goods.service.*;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
import cn.lili.modules.member.service.MemberEvaluationService;
@ -111,6 +110,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Autowired
private FreightTemplateService freightTemplateService;
@Autowired
private WholesaleService wholesaleService;
@Autowired
private Cache<GoodsVO> cache;
@ -171,7 +173,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
//添加商品
this.save(goods);
//添加商品sku信息
this.goodsSkuService.add(goodsOperationDTO.getSkuList(), goods);
this.goodsSkuService.add(goods, goodsOperationDTO);
//添加相册
if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
@ -220,7 +222,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
//修改商品
this.updateById(goods);
//修改商品sku信息
this.goodsSkuService.update(goodsOperationDTO.getSkuList(), goods, goodsOperationDTO.getRegeneratorSkuFlag());
this.goodsSkuService.update(goods, goodsOperationDTO);
//添加相册
if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
@ -302,6 +304,12 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
if (CharSequenceUtil.isNotEmpty(goods.getParams())) {
goodsVO.setGoodsParamsDTOList(JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class));
}
List<Wholesale> wholesaleList = wholesaleService.findByGoodsId(goodsId);
if (CollUtil.isNotEmpty(wholesaleList)) {
goodsVO.setWholesaleList(wholesaleList);
}
cache.put(CachePrefix.GOODS.getPrefix() + goodsId, goodsVO);
return goodsVO;
}
@ -325,6 +333,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Override
@Transactional(rollbackFor = Exception.class)
public boolean auditGoods(List<String> goodsIds, GoodsAuthEnum goodsAuthEnum) {
List<String> goodsCacheKeys = new ArrayList<>();
boolean result = false;
for (String goodsId : goodsIds) {
Goods goods = this.checkExist(goodsId);
@ -332,12 +341,13 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
result = this.updateById(goods);
goodsSkuService.updateGoodsSkuStatus(goods);
//删除之前的缓存
cache.remove(CachePrefix.GOODS.getPrefix() + goodsId);
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goodsId);
//商品审核消息
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_AUDIT.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goods), RocketmqSendCallbackBuilder.commonCallback());
}
cache.multiDel(goodsCacheKeys);
return result;
}
@ -361,13 +371,30 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
LambdaQueryWrapper<Goods> queryWrapper = this.getQueryWrapperByStoreAuthority();
queryWrapper.in(Goods::getId, goodsIds);
List<Goods> goodsList = this.list(queryWrapper);
for (Goods goods : goodsList) {
goodsSkuService.updateGoodsSkuStatus(goods);
}
this.updateGoodsStatus(goodsIds, goodsStatusEnum, goodsList);
return result;
}
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
this.deleteEsGoods(goodsIds);
}
/**
* 更新商品上架状态状态
*
* @param storeId 店铺ID
* @param goodsStatusEnum 更新的商品状态
* @param underReason 下架原因
* @return 更新结果
*/
@Override
public Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason) {
boolean result;
LambdaUpdateWrapper<Goods> updateWrapper = this.getUpdateWrapperByStoreAuthority();
updateWrapper.set(Goods::getMarketEnable, goodsStatusEnum.name());
updateWrapper.set(Goods::getUnderMessage, underReason);
updateWrapper.eq(Goods::getStoreId, storeId);
result = this.update(updateWrapper);
//修改规格商品
this.goodsSkuService.updateGoodsSkuStatusByStoreId(storeId, goodsStatusEnum.name(), null);
return result;
}
@ -394,12 +421,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Goods::getId, goodsIds);
List<Goods> goodsList = this.list(queryWrapper);
for (Goods goods : goodsList) {
goodsSkuService.updateGoodsSkuStatus(goods);
}
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
this.deleteEsGoods(goodsIds);
}
this.updateGoodsStatus(goodsIds, goodsStatusEnum, goodsList);
return result;
}
@ -417,13 +439,15 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
LambdaQueryWrapper<Goods> queryWrapper = this.getQueryWrapperByStoreAuthority();
queryWrapper.in(Goods::getId, goodsIds);
List<Goods> goodsList = this.list(queryWrapper);
List<String> goodsCacheKeys = new ArrayList<>();
for (Goods goods : goodsList) {
//修改SKU状态
goodsSkuService.updateGoodsSkuStatus(goods);
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goods.getId());
}
//删除缓存
cache.multiDel(goodsCacheKeys);
this.deleteEsGoods(goodsIds);
return true;
}
@ -503,11 +527,43 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
return this.count(
new LambdaQueryWrapper<Goods>()
.eq(Goods::getStoreId, storeId)
.eq(Goods::getDeleteFlag, Boolean.FALSE)
.eq(Goods::getAuthFlag, GoodsAuthEnum.PASS.name())
.eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name()));
}
/**
* 更新店铺商品数量
*
* @param storeId 信息体
*/
void updateGoodsNum(String storeId) {
Long num = goodsSkuService.countSkuNum(storeId);
storeService.updateStoreGoodsNum(storeId, num);
}
/**
* 更新商品状态
*
* @param goodsIds 商品ID
* @param goodsStatusEnum 商品状态
* @param goodsList 商品列表
*/
private void updateGoodsStatus(List<String> goodsIds, GoodsStatusEnum goodsStatusEnum, List<Goods> goodsList) {
List<String> goodsCacheKeys = new ArrayList<>();
for (Goods goods : goodsList) {
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goods.getId());
goodsSkuService.updateGoodsSkuStatus(goods);
}
cache.multiDel(goodsCacheKeys);
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
this.deleteEsGoods(goodsIds);
}
}
/**
* 发送删除es索引的信息
*

View File

@ -1,6 +1,5 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
@ -10,25 +9,29 @@ import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.SnowFlake;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsGallery;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.vos.GoodsSkuSpecVO;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
import cn.lili.modules.goods.entity.vos.GoodsVO;
import cn.lili.modules.goods.entity.vos.SpecValueVO;
import cn.lili.modules.goods.event.GeneratorEsGoodsIndexEvent;
import cn.lili.modules.goods.mapper.GoodsSkuMapper;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsGalleryService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.goods.service.*;
import cn.lili.modules.goods.sku.GoodsSkuBuilder;
import cn.lili.modules.goods.sku.render.SalesModelRender;
import cn.lili.modules.member.entity.dos.FootPrint;
import cn.lili.modules.member.entity.dto.EvaluationQueryParams;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
@ -37,16 +40,17 @@ import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams;
import cn.lili.modules.promotion.entity.enums.CouponGetEnum;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.search.entity.dos.EsGoodsAttribute;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.search.utils.EsIndexUtil;
import cn.lili.mybatis.util.PageUtil;
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
import cn.lili.rocketmq.tags.GoodsTagsEnum;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
@ -113,35 +117,42 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private WholesaleService wholesaleService;
@Autowired
private List<SalesModelRender> salesModelRenders;
@Override
@Transactional(rollbackFor = Exception.class)
public void add(List<Map<String, Object>> skuList, Goods goods) {
// 检查是否需要生成索引
List<GoodsSku> newSkuList;
//如果有规格
if (skuList != null && !skuList.isEmpty()) {
// 添加商品sku
newSkuList = this.addGoodsSku(skuList, goods);
} else {
public void add(Goods goods, GoodsOperationDTO goodsOperationDTO) {
// 是否存在规格
if (goodsOperationDTO.getSkuList() == null || goodsOperationDTO.getSkuList().isEmpty()) {
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
}
// 检查是否需要生成索引
List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
renderGoodsSkuList(goodsSkus, goodsOperationDTO);
this.updateStock(newSkuList);
if (!newSkuList.isEmpty()) {
generateEs(goods);
if (!goodsSkus.isEmpty()) {
this.saveOrUpdateBatch(goodsSkus);
this.updateStock(goodsSkus);
this.generateEs(goods);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(List<Map<String, Object>> skuList, Goods goods, Boolean regeneratorSkuFlag) {
public void update(Goods goods, GoodsOperationDTO goodsOperationDTO) {
// 是否存在规格
if (skuList == null || skuList.isEmpty()) {
if (goodsOperationDTO.getSkuList() == null || goodsOperationDTO.getSkuList().isEmpty()) {
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
}
List<GoodsSku> newSkuList;
List<GoodsSku> skuList;
//删除旧的sku信息
if (Boolean.TRUE.equals(regeneratorSkuFlag)) {
if (Boolean.TRUE.equals(goodsOperationDTO.getRegeneratorSkuFlag())) {
skuList = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
renderGoodsSkuList(skuList, goodsOperationDTO);
List<GoodsSkuVO> goodsListByGoodsId = getGoodsListByGoodsId(goods.getId());
List<String> oldSkuIds = new ArrayList<>();
//删除旧索引
@ -149,36 +160,32 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
oldSkuIds.add(goodsSkuVO.getId());
cache.remove(GoodsSkuService.getCacheKeys(goodsSkuVO.getId()));
}
goodsIndexService.deleteIndexByIds(oldSkuIds);
this.removeByIds(oldSkuIds);
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
//删除sku相册
goodsGalleryService.removeByIds(oldSkuIds);
// 添加商品sku
newSkuList = this.addGoodsSku(skuList, goods);
goodsGalleryService.removeByGoodsId(goods.getId());
//发送mq消息
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.SKU_DELETE.name();
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(oldSkuIds), RocketmqSendCallbackBuilder.commonCallback());
} else {
newSkuList = new ArrayList<>();
for (Map<String, Object> map : skuList) {
GoodsSku sku = new GoodsSku();
//设置商品信息
goodsInfo(sku, goods);
//设置商品规格信息
skuInfo(sku, goods, map, null);
newSkuList.add(sku);
skuList = new ArrayList<>();
for (Map<String, Object> map : goodsOperationDTO.getSkuList()) {
GoodsSku sku = GoodsSkuBuilder.build(goods, map, goodsOperationDTO);
renderGoodsSku(sku, goodsOperationDTO);
skuList.add(sku);
//如果商品状态值不对则es索引移除
if (goods.getAuthFlag().equals(GoodsAuthEnum.PASS.name()) && goods.getMarketEnable().equals(GoodsStatusEnum.UPPER.name())) {
goodsIndexService.deleteIndexById(sku.getId());
this.clearCache(sku.getId());
}
}
this.updateBatchById(newSkuList);
}
this.updateStock(newSkuList);
if (GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag()) && !newSkuList.isEmpty()) {
generateEs(goods);
if (!skuList.isEmpty()) {
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
this.saveOrUpdateBatch(skuList);
this.updateStock(skuList);
this.generateEs(goods);
}
}
@ -231,6 +238,15 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
return goodsSku;
}
@Override
public GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId) {
GoodsSku goodsSku = this.getGoodsSkuByIdFromCache(skuId);
if (goodsSku != null && GoodsSalesModeEnum.WHOLESALE.name().equals(goodsSku.getSalesModel())) {
throw new ServiceException(ResultCode.PROMOTION_GOODS_DO_NOT_JOIN_WHOLESALE, goodsSku.getGoodsName());
}
return goodsSku;
}
@Override
public Map<String, Object> getGoodsSkuDetail(String goodsId, String skuId) {
Map<String, Object> map = new HashMap<>(16);
@ -244,13 +260,16 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
GoodsSku goodsSku = this.getGoodsSkuByIdFromCache(skuId);
//如果使用商品ID无法查询SKU则返回错误
if (goodsVO == null || goodsSku == null) {
//发送mq消息
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name();
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback());
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
}
//商品下架||商品未审核通过||商品删除则提示商品已下架
if (GoodsStatusEnum.DOWN.name().equals(goodsVO.getMarketEnable())
|| !GoodsAuthEnum.PASS.name().equals(goodsVO.getAuthFlag())
|| Boolean.TRUE.equals(goodsVO.getDeleteFlag())) {
if (GoodsStatusEnum.DOWN.name().equals(goodsVO.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goodsVO.getAuthFlag()) || Boolean.TRUE.equals(goodsVO.getDeleteFlag())) {
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name();
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback());
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
}
@ -269,13 +288,10 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
promotionMap = promotionMap.entrySet().stream().parallel().filter(i -> {
JSONObject jsonObject = JSONUtil.parseObj(i.getValue());
// 过滤活动赠送优惠券和无效时间的活动
return (jsonObject.get("getType") == null || jsonObject.get("getType", String.class).equals(CouponGetEnum.FREE.name())) &&
(jsonObject.get("startTime") != null && jsonObject.get("startTime", Date.class).getTime() <= System.currentTimeMillis()) &&
(jsonObject.get("endTime") == null || jsonObject.get("endTime", Date.class).getTime() >= System.currentTimeMillis());
return (jsonObject.get("getType") == null || jsonObject.get("getType", String.class).equals(CouponGetEnum.FREE.name())) && (jsonObject.get("startTime") != null && jsonObject.get("startTime", Date.class).getTime() <= System.currentTimeMillis()) && (jsonObject.get("endTime") == null || jsonObject.get("endTime", Date.class).getTime() >= System.currentTimeMillis());
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Optional<Map.Entry<String, Object>> containsPromotion = promotionMap.entrySet().stream().filter(i ->
i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst();
Optional<Map.Entry<String, Object>> containsPromotion = promotionMap.entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst();
if (containsPromotion.isPresent()) {
JSONObject jsonObject = JSONUtil.parseObj(containsPromotion.get().getValue());
PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams();
@ -296,6 +312,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//获取分类
String[] split = goodsSkuDetail.getCategoryPath().split(",");
map.put("wholesaleList", wholesaleService.findByGoodsId(goodsSkuDetail.getGoodsId()));
map.put("categoryName", categoryService.getCategoryNameByIds(Arrays.asList(split)));
//获取规格信息
@ -325,7 +342,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Transactional(rollbackFor = Exception.class)
public void updateGoodsSkuStatus(Goods goods) {
LambdaUpdateWrapper<GoodsSku> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(GoodsSku::getGoodsId, goods.getId());
updateWrapper.eq(CharSequenceUtil.isNotEmpty(goods.getId()), GoodsSku::getGoodsId, goods.getId());
updateWrapper.eq(CharSequenceUtil.isNotEmpty(goods.getStoreId()), GoodsSku::getStoreId, goods.getStoreId());
updateWrapper.set(GoodsSku::getMarketEnable, goods.getMarketEnable());
updateWrapper.set(GoodsSku::getAuthFlag, goods.getAuthFlag());
updateWrapper.set(GoodsSku::getDeleteFlag, goods.getDeleteFlag());
@ -337,7 +355,32 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
cache.put(GoodsSkuService.getCacheKeys(sku.getId()), sku);
}
if (!goodsSkus.isEmpty()) {
generateEs(goods);
this.generateEs(goods);
}
}
}
/**
* 更新商品sku状态根据店铺id
*
* @param storeId 店铺id
* @param marketEnable 市场启用状态
* @param authFlag 审核状态
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateGoodsSkuStatusByStoreId(String storeId, String marketEnable, String authFlag) {
LambdaUpdateWrapper<GoodsSku> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(GoodsSku::getStoreId, storeId);
updateWrapper.set(CharSequenceUtil.isNotEmpty(marketEnable), GoodsSku::getMarketEnable, marketEnable);
updateWrapper.set(CharSequenceUtil.isNotEmpty(authFlag), GoodsSku::getAuthFlag, authFlag);
boolean update = this.update(updateWrapper);
if (Boolean.TRUE.equals(update)) {
if (GoodsStatusEnum.UPPER.name().equals(marketEnable)) {
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_STORE_GOODS_INDEX.name(), storeId));
} else if (GoodsStatusEnum.DOWN.name().equals(marketEnable)) {
cache.vagueDel(CachePrefix.GOODS_SKU.getPrefix());
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.STORE_GOODS_DELETE.name(), storeId));
}
}
}
@ -362,7 +405,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Override
public List<GoodsSkuVO> getGoodsListByGoodsId(String goodsId) {
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId));
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId).orderByAsc(GoodsSku::getGoodsName));
return this.getGoodsSkuVOList(list);
}
@ -423,6 +466,11 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
return this.page(PageUtil.initPage(searchParams), searchParams.queryWrapper());
}
@Override
public IPage<GoodsSkuDTO> getGoodsSkuDTOByPage(Page<GoodsSkuDTO> page, Wrapper<GoodsSkuDTO> queryWrapper) {
return this.baseMapper.queryByParams(page, queryWrapper);
}
/**
* 列表查询商品sku信息
*
@ -481,18 +529,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Override
@Transactional(rollbackFor = Exception.class)
public void updateGoodsStuck(List<GoodsSku> goodsSkus) {
//商品id集合 hashset 去重复
Set<String> goodsIds = new HashSet<>();
for (GoodsSku sku : goodsSkus) {
goodsIds.add(sku.getGoodsId());
}
Map<String, List<GoodsSku>> groupByGoodsIds = goodsSkus.stream().collect(Collectors.groupingBy(GoodsSku::getGoodsId));
//获取相关的sku集合
LambdaQueryWrapper<GoodsSku> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(GoodsSku::getGoodsId, goodsIds);
lambdaQueryWrapper.in(GoodsSku::getGoodsId, groupByGoodsIds.keySet());
List<GoodsSku> goodsSkuList = this.list(lambdaQueryWrapper);
//统计每个商品的库存
for (String goodsId : goodsIds) {
for (String goodsId : groupByGoodsIds.keySet()) {
//库存
Integer quantity = 0;
for (GoodsSku goodsSku : goodsSkuList) {
@ -530,10 +574,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//修改规格索引,发送mq消息
Map<String, Object> updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(
MapUtil.builder(new HashMap<String, Object>()).put("id", goodsSku.getId()).build(),
MapUtil.builder(new HashMap<String, Object>()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum)
.put("grade", grade).build());
Map<String, Object> updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(MapUtil.builder(new HashMap<String, Object>()).put("id", goodsSku.getId()).build(), MapUtil.builder(new HashMap<String, Object>()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum).put("grade", grade).build());
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_FIELD.name();
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(updateIndexFieldsMap), RocketmqSendCallbackBuilder.commonCallback());
@ -558,12 +599,38 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
* @param goods 商品信息
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void generateEs(Goods goods) {
// 不生成没有审核通过且没有上架的商品
if (!GoodsStatusEnum.UPPER.name().equals(goods.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) {
return;
}
applicationEventPublisher.publishEvent(new GeneratorEsGoodsIndexEvent("生成商品索引事件", goods.getId()));
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_GOODS_INDEX.name(), goods.getId()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteAndInsertGoodsSkus(List<GoodsSku> goodsSkus) {
int count = 0;
for (GoodsSku skus : goodsSkus) {
if (CharSequenceUtil.isEmpty(skus.getId())) {
skus.setId(SnowFlake.getIdStr());
}
count = this.baseMapper.replaceGoodsSku(skus);
}
return count > 0;
}
@Override
public Long countSkuNum(String storeId) {
LambdaQueryWrapper<GoodsSku> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(GoodsSku::getStoreId, storeId)
.eq(GoodsSku::getDeleteFlag, Boolean.FALSE)
.eq(GoodsSku::getAuthFlag, GoodsAuthEnum.PASS.name())
.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
return this.count(queryWrapper);
}
/**
@ -584,152 +651,64 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
/**
* 增加sku集合
* 批量渲染商品sku
*
* @param skuList sku列表
* @param goods 商品信息
* @param goodsSkuList sku集合
* @param goodsOperationDTO 商品操作DTO
*/
List<GoodsSku> addGoodsSku(List<Map<String, Object>> skuList, Goods goods) {
List<GoodsSku> skus = new ArrayList<>();
for (Map<String, Object> skuVO : skuList) {
Map<String, Object> resultMap = this.add(skuVO, goods);
GoodsSku goodsSku = (GoodsSku) resultMap.get("goodsSku");
if (goods.getSelfOperated() != null) {
goodsSku.setSelfOperated(goods.getSelfOperated());
}
goodsSku.setGoodsType(goods.getGoodsType());
skus.add(goodsSku);
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
void renderGoodsSkuList(List<GoodsSku> goodsSkuList, GoodsOperationDTO goodsOperationDTO) {
// 商品销售模式渲染器
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderBatch(goodsSkuList, goodsOperationDTO));
for (GoodsSku goodsSku : goodsSkuList) {
extendOldSkuValue(goodsSku);
this.renderImages(goodsSku);
}
this.saveBatch(skus);
return skus;
}
/**
* 添加商品规格
* 渲染商品sku
*
* @param map 规格属性
* @param goods 商品
* @return 规格商品
* @param goodsSku sku
* @param goodsOperationDTO 商品操作DTO
*/
private Map<String, Object> add(Map<String, Object> map, Goods goods) {
Map<String, Object> resultMap = new HashMap<>(2);
GoodsSku sku = new GoodsSku();
//商品索引
EsGoodsIndex esGoodsIndex = new EsGoodsIndex();
//设置商品信息
goodsInfo(sku, goods);
//设置商品规格信息
skuInfo(sku, goods, map, esGoodsIndex);
esGoodsIndex.setGoodsSku(sku);
resultMap.put("goodsSku", sku);
resultMap.put("goodsIndex", esGoodsIndex);
return resultMap;
void renderGoodsSku(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
extendOldSkuValue(goodsSku);
// 商品销售模式渲染器
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderSingle(goodsSku, goodsOperationDTO));
this.renderImages(goodsSku);
}
/**
* 设置规格商品的商品信息
* 将原sku的一些不会直接传递的值放到新的sku中
*
* @param sku 规格
* @param goods 商品
* @param goodsSku 商品sku
*/
private void goodsInfo(GoodsSku sku, Goods goods) {
//商品基本信息
sku.setGoodsId(goods.getId());
sku.setSellingPoint(goods.getSellingPoint());
sku.setCategoryPath(goods.getCategoryPath());
sku.setBrandId(goods.getBrandId());
sku.setMarketEnable(goods.getMarketEnable());
sku.setIntro(goods.getIntro());
sku.setMobileIntro(goods.getMobileIntro());
sku.setGoodsUnit(goods.getGoodsUnit());
sku.setGrade(100D);
//商品状态
sku.setAuthFlag(goods.getAuthFlag());
sku.setSalesModel(goods.getSalesModel());
//卖家信息
sku.setStoreId(goods.getStoreId());
sku.setStoreName(goods.getStoreName());
sku.setStoreCategoryPath(goods.getStoreCategoryPath());
sku.setFreightTemplateId(goods.getTemplateId());
sku.setRecommend(goods.getRecommend());
}
/**
* 设置商品规格信息
*
* @param sku 规格商品
* @param goods 商品
* @param map 规格信息
* @param esGoodsIndex 商品索引
*/
private void skuInfo(GoodsSku sku, Goods goods, Map<String, Object> map, EsGoodsIndex esGoodsIndex) {
//规格简短信息
StringBuilder simpleSpecs = new StringBuilder();
//商品名称
StringBuilder goodsName = new StringBuilder(goods.getGoodsName());
//规格商品缩略图
String thumbnail = "";
String small = "";
//规格值
Map<String, Object> specMap = new HashMap<>(16);
//商品属性
List<EsGoodsAttribute> attributes = new ArrayList<>();
//获取规格信息
for (Map.Entry<String, Object> spec : map.entrySet()) {
//保存规格信息
if (("id").equals(spec.getKey()) || ("sn").equals(spec.getKey()) || ("cost").equals(spec.getKey())
|| ("price").equals(spec.getKey()) || ("quantity").equals(spec.getKey())
|| ("weight").equals(spec.getKey())) {
continue;
} else {
specMap.put(spec.getKey(), spec.getValue());
if (("images").equals(spec.getKey())) {
//设置规格商品缩略图
List<Map<String, String>> images = (List<Map<String, String>>) spec.getValue();
if (images == null || images.isEmpty()) {
continue;
}
//设置规格商品缩略图
//如果规格没有图片则用商品图片复盖有则增加规格图片放在商品图片集合之前
if (CharSequenceUtil.isNotEmpty(spec.getValue().toString())) {
thumbnail = goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getThumbnail();
small = goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getSmall();
}
} else {
if (spec.getValue() != null) {
//设置商品名称
goodsName.append(" ").append(spec.getValue());
//规格简短信息
simpleSpecs.append(" ").append(spec.getValue());
}
}
private void extendOldSkuValue(GoodsSku goodsSku) {
if (CharSequenceUtil.isNotEmpty(goodsSku.getGoodsId())) {
GoodsSku oldSku = this.getGoodsSkuByIdFromCache(goodsSku.getId());
if (oldSku != null) {
goodsSku.setCommentNum(oldSku.getCommentNum());
goodsSku.setViewCount(oldSku.getViewCount());
goodsSku.setBuyCount(oldSku.getBuyCount());
goodsSku.setGrade(oldSku.getGrade());
}
}
//设置规格信息
sku.setGoodsName(goodsName.toString());
sku.setThumbnail(thumbnail);
sku.setSmall(small);
}
//规格信息
sku.setId(Convert.toStr(map.get("id"), ""));
sku.setSn(Convert.toStr(map.get("sn")));
sku.setWeight(Convert.toDouble(map.get("weight"), 0D));
sku.setPrice(Convert.toDouble(map.get("price"), 0D));
sku.setCost(Convert.toDouble(map.get("cost"), 0D));
sku.setQuantity(Convert.toInt(map.get("quantity"), 0));
sku.setSpecs(JSONUtil.toJsonStr(specMap));
sku.setSimpleSpecs(simpleSpecs.toString());
if (esGoodsIndex != null) {
//商品索引
esGoodsIndex.setAttrList(attributes);
/**
* 渲染sku图片
*
* @param goodsSku sku
*/
void renderImages(GoodsSku goodsSku) {
JSONObject jsonObject = JSONUtil.parseObj(goodsSku.getSpecs());
List<Map<String, String>> images = jsonObject.get("images", List.class);
if (images != null && !images.isEmpty()) {
GoodsGallery goodsGallery = goodsGalleryService.getGoodsGallery(images.get(0).get("url"));
goodsSku.setBig(goodsGallery.getOriginal());
goodsSku.setOriginal(goodsGallery.getOriginal());
goodsSku.setThumbnail(goodsGallery.getThumbnail());
goodsSku.setSmall(goodsGallery.getSmall());
}
}

View File

@ -56,7 +56,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
StoreGoodsLabelVO storeGoodsLabelVO = new StoreGoodsLabelVO(storeGoodsLabel.getId(), storeGoodsLabel.getLabelName(), storeGoodsLabel.getLevel(), storeGoodsLabel.getSortOrder());
List<StoreGoodsLabelVO> storeGoodsLabelVOChildList = new ArrayList<>();
list.stream()
.filter(label -> label.getParentId().equals(storeGoodsLabel.getId()))
.filter(label -> label.getParentId() != null && label.getParentId().equals(storeGoodsLabel.getId()))
.forEach(storeGoodsLabelChild -> storeGoodsLabelVOChildList.add(new StoreGoodsLabelVO(storeGoodsLabelChild.getId(), storeGoodsLabelChild.getLabelName(), storeGoodsLabelChild.getLevel(), storeGoodsLabelChild.getSortOrder())));
storeGoodsLabelVO.setChildren(storeGoodsLabelVOChildList);
storeGoodsLabelVOList.add(storeGoodsLabelVO);
@ -66,7 +66,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
storeGoodsLabelVOList.sort(Comparator.comparing(StoreGoodsLabelVO::getSortOrder));
if (!storeGoodsLabelVOList.isEmpty()) {
cache.put(CachePrefix.CATEGORY.getPrefix() + storeId + "tree", storeGoodsLabelVOList);
cache.put(CachePrefix.CATEGORY.getPrefix() + storeId, storeGoodsLabelVOList);
}
return storeGoodsLabelVOList;
}

View File

@ -1,6 +1,7 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
@ -32,12 +33,15 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -117,7 +121,7 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
rocketmqCustomProperties.getPromotionTopic());
//直播间结束
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.START.name());
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.END.name());
this.timeTrigger.edit(
TimeExecuteConstant.BROADCAST_EXECUTOR,
broadcastMessage,
@ -209,15 +213,27 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
}
@Override
public IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status) {
public IPage<StudioVO> studioList(PageVO pageVO, Integer recommend, String status) {
QueryWrapper queryWrapper = new QueryWrapper<Studio>()
.eq(recommend != null, "recommend", true)
.eq(status != null, "status", status)
.eq(CharSequenceUtil.isNotEmpty(status), "status", status)
.orderByDesc("create_time");
if (UserContext.getCurrentUser() != null && UserContext.getCurrentUser().getRole().equals(UserEnums.STORE)) {
queryWrapper.eq("store_id", UserContext.getCurrentUser().getStoreId());
}
return this.page(PageUtil.initPage(pageVO), queryWrapper);
Page page = this.page(PageUtil.initPage(pageVO), queryWrapper);
List<Studio> records = page.getRecords();
List<StudioVO> studioVOS = new ArrayList<>();
for (Studio record : records) {
StudioVO studioVO = new StudioVO();
//获取直播间信息
BeanUtil.copyProperties(record, studioVO);
//获取直播间商品信息
studioVO.setCommodityList(commodityMapper.getCommodityByRoomId(studioVO.getRoomId()));
studioVOS.add(studioVO);
}
page.setRecords(studioVOS);
return page;
}

View File

@ -0,0 +1,65 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.collection.CollUtil;
import cn.lili.cache.Cache;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.mapper.WholesaleMapper;
import cn.lili.modules.goods.service.WholesaleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author paulG
* @since 2022/5/24
**/
@Service
@CacheConfig(cacheNames = "{wholesale}_")
public class WholesaleServiceImpl extends ServiceImpl<WholesaleMapper, Wholesale> implements WholesaleService {
@Autowired
private Cache<List<Wholesale>> cache;
@Override
@Cacheable(key = "#goodsId")
public List<Wholesale> findByGoodsId(String goodsId) {
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Wholesale::getGoodsId, goodsId);
return this.list(queryWrapper).stream().sorted(Comparator.comparing(Wholesale::getNum)).collect(Collectors.toList());
}
@Override
@CacheEvict(key = "#goodsId")
public Boolean removeByGoodsId(String goodsId) {
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Wholesale::getGoodsId, goodsId);
cache.remove("{wholesale}_" + goodsId);
return this.remove(queryWrapper);
}
@Override
public Wholesale match(String goodsId, Integer num) {
List<Wholesale> wholesaleList = cache.get("{wholesale}_" + goodsId);
if (wholesaleList == null) {
wholesaleList = this.findByGoodsId(goodsId);
cache.put("{wholesale}_" + goodsId, wholesaleList);
}
List<Wholesale> matchList = wholesaleList.stream()
.filter(wholesale -> wholesale.getNum() <= num)
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(matchList)) {
return matchList.get(matchList.size() - 1);
} else if (CollUtil.isNotEmpty(wholesaleList) && CollUtil.isEmpty(matchList)) {
return wholesaleList.get(0);
}
return null;
}
}

View File

@ -0,0 +1,116 @@
package cn.lili.modules.goods.sku;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @author paulG
* @since 2022/5/20
**/
@Component
public class GoodsSkuBuilder {
private static final String IMAGES_KEY = "images";
/**
* 构建商品sku
*
* @param goods 商品
* @param skuInfo sku信息列表
* @param goodsOperationDTO 商品操作信息如需处理额外信息传递不需可传空
* @return 商品sku
*/
public static GoodsSku build(Goods goods, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
GoodsSku goodsSku = new GoodsSku(goods);
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
return goodsSku;
}
/**
* 批量构建商品sku
*
* @param goods 商品
* @param goodsOperationDTO 商品操作信息
* @return 商品sku
*/
public static List<GoodsSku> buildBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
return builderBatch(goods, goodsOperationDTO);
}
/**
* 从已有的商品sku中构建商品sku
*
* @param goodsSku 原商品sku
* @param skuInfo sku信息列表
* @param goodsOperationDTO 商品操作信息如需处理额外信息传递不需可传空
* @return 商品sku
*/
public static GoodsSku build(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
return goodsSku;
}
private static void builderSingle(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
Assert.notNull(goodsSku, "goodsSku不能为空");
Assert.notEmpty(skuInfo, "skuInfo不能为空");
//规格简短信息
StringBuilder simpleSpecs = new StringBuilder();
//商品名称
StringBuilder goodsName = new StringBuilder(goodsOperationDTO.getGoodsName());
//规格值
Map<String, Object> specMap = new HashMap<>(16);
// 原始规格项
String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight"};
//获取规格信息
for (Map.Entry<String, Object> spec : skuInfo.entrySet()) {
//保存新增规格信息
if (!CollUtil.contains(Arrays.asList(ignoreOriginKeys), spec.getKey()) && spec.getValue() != null) {
specMap.put(spec.getKey(), spec.getValue());
if (!spec.getKey().equals(IMAGES_KEY)) {
//设置商品名称
goodsName.append(" ").append(spec.getValue());
//规格简短信息
simpleSpecs.append(" ").append(spec.getValue());
}
}
}
//设置规格信息
goodsSku.setGoodsName(goodsName.toString());
//规格信息
goodsSku.setId(Convert.toStr(skuInfo.get("id"), ""));
goodsSku.setSn(Convert.toStr(skuInfo.get("sn")));
goodsSku.setWeight(Convert.toDouble(skuInfo.get("weight"), 0D));
goodsSku.setPrice(Convert.toDouble(skuInfo.get("price"), 0D));
goodsSku.setCost(Convert.toDouble(skuInfo.get("cost"), 0D));
goodsSku.setQuantity(Convert.toInt(skuInfo.get("quantity"), 0));
goodsSku.setSpecs(JSONUtil.toJsonStr(specMap));
goodsSku.setSimpleSpecs(simpleSpecs.toString());
}
private static List<GoodsSku> builderBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
Assert.notEmpty(goodsOperationDTO.getSkuList(), "goodsOperationDTO.getSkuList()不能为空");
Assert.notNull(goods, "goods不能为空");
List<GoodsSku> goodsSkus = new ArrayList<>();
for (Map<String, Object> skuInfo : goodsOperationDTO.getSkuList()) {
GoodsSku goodsSku = new GoodsSku(goods);
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
goodsSkus.add(goodsSku);
}
return goodsSkus;
}
}

View File

@ -0,0 +1,23 @@
package cn.lili.modules.goods.sku.render;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import java.util.List;
/**
* 根据商品销售模型渲染商品sku
*
* @author paulG
* @since 2022/5/20
**/
public interface SalesModelRender {
String getSalesMode();
void renderSingle(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO);
void renderBatch(List<GoodsSku> goodsSkus, GoodsOperationDTO goodsOperationDTO);
}

View File

@ -0,0 +1,81 @@
package cn.lili.modules.goods.sku.render.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.WholesaleDTO;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
import cn.lili.modules.goods.service.WholesaleService;
import cn.lili.modules.goods.sku.render.SalesModelRender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author paulG
* @since 2022/5/24
**/
@Component
public class WholesaleSaleModelRenderImpl implements SalesModelRender {
/**
* 批发商品
*/
@Autowired
private WholesaleService wholesaleService;
@Override
@Transactional(rollbackFor = Exception.class)
public void renderSingle(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
Assert.notEmpty(goodsOperationDTO.getWholesaleList(), "批发规则不能为空");
this.checkWholesaleList(goodsOperationDTO.getWholesaleList(), goodsSku);
List<Wholesale> collect = goodsOperationDTO.getWholesaleList().stream().sorted(Comparator.comparing(Wholesale::getPrice)).collect(Collectors.toList());
wholesaleService.removeByGoodsId(goodsSku.getGoodsId());
wholesaleService.saveOrUpdateBatch(collect);
goodsSku.setPrice(collect.get(0).getPrice());
goodsSku.setCost(collect.get(0).getPrice());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void renderBatch(List<GoodsSku> goodsSkus, GoodsOperationDTO goodsOperationDTO) {
Assert.notEmpty(goodsOperationDTO.getWholesaleList(), "批发规则不能为空");
this.checkWholesaleList(goodsOperationDTO.getWholesaleList(), goodsSkus.get(0));
List<Wholesale> collect = goodsOperationDTO.getWholesaleList().stream().sorted(Comparator.comparing(Wholesale::getPrice)).collect(Collectors.toList());
for (GoodsSku skus : goodsSkus) {
skus.setPrice(collect.get(0).getPrice());
skus.setCost(collect.get(0).getPrice());
}
wholesaleService.removeByGoodsId(goodsSkus.get(0).getGoodsId());
wholesaleService.saveOrUpdateBatch(collect);
}
private void checkWholesaleList(List<WholesaleDTO> wholesaleList, GoodsSku goodsSku) {
if (CollUtil.isEmpty(wholesaleList)) {
throw new ServiceException(ResultCode.MUST_HAVE_SALES_MODEL);
}
for (WholesaleDTO wholesaleDTO : wholesaleList) {
if (wholesaleDTO.getPrice() == null || wholesaleDTO.getPrice() <= 0 || wholesaleDTO.getNum() == null || wholesaleDTO.getNum() <= 0) {
throw new ServiceException(ResultCode.HAVE_INVALID_SALES_MODEL);
}
if (CharSequenceUtil.isEmpty(wholesaleDTO.getGoodsId())) {
wholesaleDTO.setGoodsId(goodsSku.getGoodsId());
}
}
}
@Override
public String getSalesMode() {
return GoodsSalesModeEnum.WHOLESALE.name();
}
}

View File

@ -42,4 +42,8 @@ public class MemberSign extends BaseIdEntity {
@ApiModelProperty(value = "连续签到天数")
private Integer signDay;
@ApiModelProperty(value = "签到日 为数字 从现在减去19700101 的日期")
private Integer day;
}

View File

@ -21,9 +21,8 @@ import java.util.Date;
@Data
public class ManagerMemberEditDTO {
@ApiModelProperty(value = "会员用户名,用户名不能进行修改", required = true)
@NotNull(message = "会员用户名不能为空")
private String username;
@NotNull(message = "用户ID不能为空")
private String id;
@ApiModelProperty(value = "会员密码")
private String password;
@ -45,7 +44,7 @@ public class ManagerMemberEditDTO {
private Integer sex;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "会员生日")
private Date birthday;

View File

@ -12,7 +12,7 @@ import lombok.Data;
@Data
public class EvaluationNumberVO {
@ApiModelProperty(value = "全部商品")
@ApiModelProperty(value = "全部评价")
private Integer all;
@ApiModelProperty(value = "好评数量")

View File

@ -18,17 +18,6 @@ import java.util.List;
* @since 2020-02-25 14:10:16
*/
public interface FootprintMapper extends BaseMapper<FootPrint> {
/**
* 获取用户足迹的SkuId分页
*
* @param page 分页
* @param queryWrapper 查询条件
* @return 用户足迹的SkuId分页
*/
@Select("select sku_id from li_foot_print ${ew.customSqlSegment} ")
List<String> footprintSkuIdList(IPage<String> page, @Param(Constants.WRAPPER) Wrapper<FootPrint> queryWrapper);
/**
* 删除超过100条后的记录
*

View File

@ -38,7 +38,7 @@ public interface MemberEvaluationMapper extends BaseMapper<MemberEvaluation> {
* @param goodsId 商品ID
* @return 会员评价
*/
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} and status='OPEN' GROUP BY grade")
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} and status='OPEN' and delete_flag = false GROUP BY grade")
List<Map<String, Object>> getEvaluationNumber(String goodsId);
/**

View File

@ -3,6 +3,7 @@ package cn.lili.modules.member.service;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.member.entity.dos.FootPrint;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -44,7 +45,7 @@ public interface FootprintService extends IService<FootPrint> {
* @param pageVO 分页
* @return 会员浏览历史列表
*/
List<EsGoodsIndex> footPrintPage(PageVO pageVO);
IPage<EsGoodsIndex> footPrintPage(PageVO pageVO);
/**
* 获取当前会员的浏览记录数量

View File

@ -25,6 +25,11 @@ import java.util.Map;
*/
public interface MemberService extends IService<Member> {
/**
* 默认密码
*/
static String DEFAULT_PASSWORD = "111111";
/**
* 获取当前登录的用户信息
*
@ -92,6 +97,29 @@ public interface MemberService extends IService<Member> {
*/
Member modifyPass(String memberId, String oldPassword, String newPassword);
/**
* 是否可以初始化密码
*
* @return
*/
boolean canInitPass();
/**
* 初始化密码
*
* @param password 密码
* @return 操作结果
*/
void initPass(String password);
/**
* 注销账号
*
* @param password 密码
* @return 操作结果
*/
void cancellation(String password);
/**
* 注册会员
*
@ -257,6 +285,7 @@ public interface MemberService extends IService<Member> {
/**
* 获取用户VO
*
* @param id 会员id
* @return 用户VO
*/

View File

@ -9,16 +9,18 @@ import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsSearchService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 会员浏览历史业务层实现
@ -29,9 +31,7 @@ import java.util.Objects;
@Service
public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, FootPrint> implements FootprintService {
/**
* es商品业务层
*/
@Autowired
private EsGoodsSearchService esGoodsSearchService;
@ -74,20 +74,33 @@ public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, FootPrint
}
@Override
public List<EsGoodsIndex> footPrintPage(PageVO pageVO) {
public IPage<EsGoodsIndex> footPrintPage(PageVO pageVO) {
LambdaQueryWrapper<FootPrint> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(FootPrint::getMemberId, UserContext.getCurrentUser().getId());
lambdaQueryWrapper.eq(FootPrint::getDeleteFlag, false);
lambdaQueryWrapper.orderByDesc(FootPrint::getUpdateTime);
List<String> skuIdList = this.baseMapper.footprintSkuIdList(PageUtil.initPage(pageVO), lambdaQueryWrapper);
if (!skuIdList.isEmpty()) {
List<EsGoodsIndex> list = esGoodsSearchService.getEsGoodsBySkuIds(skuIdList);
lambdaQueryWrapper.orderByDesc(FootPrint::getCreateTime);
IPage<FootPrint> footPrintPages = this.page(PageUtil.initPage(pageVO), lambdaQueryWrapper);
//定义结果
IPage<EsGoodsIndex> esGoodsIndexIPage = new Page<>();
if (footPrintPages.getRecords() == null || footPrintPages.getRecords().isEmpty()) {
return esGoodsIndexIPage;
} else {
List<EsGoodsIndex> list = esGoodsSearchService.getEsGoodsBySkuIds(
footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()));
//去除为空的商品数据
list.removeIf(Objects::isNull);
return list;
esGoodsIndexIPage.setPages(footPrintPages.getPages());
esGoodsIndexIPage.setRecords(list);
esGoodsIndexIPage.setTotal(footPrintPages.getTotal());
esGoodsIndexIPage.setSize(footPrintPages.getSize());
esGoodsIndexIPage.setCurrent(footPrintPages.getCurrent());
return esGoodsIndexIPage;
}
return Collections.emptyList();
}
@Override

Some files were not shown because too many files have changed in this diff Show More