diff --git a/DB/version4.2.3to4.2.4.sql b/DB/version4.2.3to4.2.4.sql index 78764222..c34d6097 100644 --- a/DB/version4.2.3to4.2.4.sql +++ b/DB/version4.2.3to4.2.4.sql @@ -1,2 +1,64 @@ /** 新增已退货数量 **/ -ALTER TABLE li_order_item ADD return_goods_number int DEFAULT 0 COMMENT '退货数量 '; \ No newline at end of file +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'; \ No newline at end of file diff --git a/DB/version4.2.3toMASTER.sql b/DB/version4.2.3toMASTER.sql deleted file mode 100644 index 1773b4ba..00000000 --- a/DB/version4.2.3toMASTER.sql +++ /dev/null @@ -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; - - diff --git a/DB/version4.2.4toMASTER.sql b/DB/version4.2.4toMASTER.sql new file mode 100644 index 00000000..c243f814 --- /dev/null +++ b/DB/version4.2.4toMASTER.sql @@ -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 '批发规则表'; + diff --git a/README.md b/README.md index 7eabf5b1..73b3619b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ ## Lilishop B2B2C商城系统 -##### 开源不易,如有帮助请点Star - - - -#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,进群先看文档后提问) +#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,其他问题先看文档后提问) <<<<<<< HEAD ##### 交流 qq 1群 961316482(已满) @@ -16,12 +12,17 @@ ##### 交流 qq 1群 961316482(已满) Lilishop交流群点击快捷加群 -##### 交流 qq 2群 875294241 +##### 交流 qq 2群 875294241(已满) Lilishop交流群2群点击快捷加群 >>>>>>> ae0c4aea12996d3d72eca7c6ccdc97922373e4d7 +##### 交流 qq 3群 263785057 + +Lilishop交流群3群点击快捷加群 + + ##### 体验 公众号/小程序/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 diff --git a/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java index 92f8838d..fc5a5f0d 100644 --- a/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java @@ -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> getGoodsHotWords(Integer count) { - List hotWords = goodsSearchService.getHotWords(count); + List hotWords = hotWordsService.getHotWords(count); return ResultUtil.data(hotWords); } diff --git a/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java b/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java index 256603f9..e5de7c6b 100644 --- a/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java +++ b/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java @@ -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> getByPage(PageVO page) { + public ResultMessage> getByPage(PageVO page) { return ResultUtil.data(footprintService.footPrintPage(page)); } diff --git a/buyer-api/src/main/java/cn/lili/controller/member/MemberEvaluationBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/member/MemberEvaluationBuyerController.java index e33524f8..26285f54 100644 --- a/buyer-api/src/main/java/cn/lili/controller/member/MemberEvaluationBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/member/MemberEvaluationBuyerController.java @@ -48,7 +48,7 @@ public class MemberEvaluationBuyerController { @ApiOperation(value = "查看会员评价详情") @ApiImplicitParam(name = "id", value = "评价ID", required = true, paramType = "path") @GetMapping(value = "/get/{id}") - public ResultMessage save(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) { + public ResultMessage get(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) { return ResultUtil.data(memberEvaluationService.queryById(id)); } diff --git a/buyer-api/src/main/java/cn/lili/controller/member/MemberSignBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/member/MemberSignBuyerController.java index 758f60cf..ea358e94 100644 --- a/buyer-api/src/main/java/cn/lili/controller/member/MemberSignBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/member/MemberSignBuyerController.java @@ -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; diff --git a/buyer-api/src/main/java/cn/lili/controller/order/OrderComplaintBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/order/OrderComplaintBuyerController.java index f348c882..1d26fef2 100644 --- a/buyer-api/src/main/java/cn/lili/controller/order/OrderComplaintBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/order/OrderComplaintBuyerController.java @@ -82,7 +82,7 @@ public class OrderComplaintBuyerController { @PostMapping("/communication") public ResultMessage 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); } diff --git a/buyer-api/src/main/java/cn/lili/controller/other/broadcast/StudioController.java b/buyer-api/src/main/java/cn/lili/controller/other/broadcast/StudioController.java index d161e5c1..1c03c9e9 100644 --- a/buyer-api/src/main/java/cn/lili/controller/other/broadcast/StudioController.java +++ b/buyer-api/src/main/java/cn/lili/controller/other/broadcast/StudioController.java @@ -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> page(PageVO pageVO, Integer recommend, String status) { + public ResultMessage> page(PageVO pageVO, Integer recommend, String status) { return ResultUtil.data(studioService.studioList(pageVO, recommend, status)); } diff --git a/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java index c04a4628..744dc660 100644 --- a/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java @@ -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 canInitPassword() { + return ResultUtil.data(memberService.canInitPass()); + } + + @ApiOperation(value = "初始设置密码") + @ApiImplicitParams({ + @ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query") + }) + @PutMapping("/initPassword") + public ResultMessage 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 cancellation(@NotNull(message = "密码不能为空") @RequestParam String password) { + memberService.cancellation(password); + return ResultUtil.success(); + } @ApiOperation(value = "刷新token") @GetMapping("/refresh/{refreshToken}") diff --git a/buyer-api/src/main/java/cn/lili/init/EsGoodsIndexInitRunner.java b/buyer-api/src/main/java/cn/lili/init/EsGoodsIndexInitRunner.java new file mode 100644 index 00000000..8b3e9952 --- /dev/null +++ b/buyer-api/src/main/java/cn/lili/init/EsGoodsIndexInitRunner.java @@ -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); + } + } +} diff --git a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java b/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java index 1ccf3cff..b7907bca 100644 --- a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java +++ b/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java @@ -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; diff --git a/common-api/src/main/java/cn/lili/controller/common/RegionController.java b/common-api/src/main/java/cn/lili/controller/common/RegionController.java index f951f058..9abcfce3 100644 --- a/common-api/src/main/java/cn/lili/controller/common/RegionController.java +++ b/common-api/src/main/java/cn/lili/controller/common/RegionController.java @@ -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 getItemByLastName(String lastName) { + return ResultUtil.data(regionService.getItemByLastName(lastName)); + } @GetMapping(value = "/item/{id}") @ApiImplicitParam(name = "id", value = "地区ID", required = true, dataType = "String", paramType = "path") diff --git a/common-api/src/main/java/cn/lili/controller/common/SiteController.java b/common-api/src/main/java/cn/lili/controller/common/SiteController.java index e6a5e8b6..70b32328 100644 --- a/common-api/src/main/java/cn/lili/controller/common/SiteController.java +++ b/common-api/src/main/java/cn/lili/controller/common/SiteController.java @@ -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 diff --git a/common-api/src/main/java/cn/lili/controller/common/UploadController.java b/common-api/src/main/java/cn/lili/controller/common/UploadController.java index 8febcb49..d97fa40c 100644 --- a/common-api/src/main/java/cn/lili/controller/common/UploadController.java +++ b/common-api/src/main/java/cn/lili/controller/common/UploadController.java @@ -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()); diff --git a/common-api/src/main/java/cn/lili/controller/security/CommonSecurityConfig.java b/common-api/src/main/java/cn/lili/controller/security/CommonSecurityConfig.java index 8fa1f8c2..5ad1d4a2 100644 --- a/common-api/src/main/java/cn/lili/controller/security/CommonSecurityConfig.java +++ b/common-api/src/main/java/cn/lili/controller/security/CommonSecurityConfig.java @@ -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 cache; - @Autowired private CorsConfigurationSource corsConfigurationSource; @Override diff --git a/common-api/src/main/resources/application.yml b/common-api/src/main/resources/application.yml index a914b499..eadf556f 100644 --- a/common-api/src/main/resources/application.yml +++ b/common-api/src/main/resources/application.yml @@ -121,6 +121,8 @@ ignored: - /source/** - /common/common/slider/** - /common/common/sms/** + - /common/common/logo + - /common/common/site - /druid/** - /swagger-ui.html - /doc.html diff --git a/config/application.yml b/config/application.yml index 04384a73..03a5a775 100644 --- a/config/application.yml +++ b/config/application.yml @@ -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: diff --git a/consumer/src/main/java/cn/lili/event/impl/FullDiscountExecute.java b/consumer/src/main/java/cn/lili/event/impl/FullDiscountExecute.java index a3507d83..86a08cbb 100644 --- a/consumer/src/main/java/cn/lili/event/impl/FullDiscountExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/FullDiscountExecute.java @@ -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 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()); diff --git a/consumer/src/main/java/cn/lili/event/impl/PaymentExecute.java b/consumer/src/main/java/cn/lili/event/impl/PaymentExecute.java index 6889c867..deb3fa65 100644 --- a/consumer/src/main/java/cn/lili/event/impl/PaymentExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/PaymentExecute.java @@ -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); } - - } - - } diff --git a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java index 77806014..ceee4a1a 100644 --- a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java @@ -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 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); } //批量获取商品库存 diff --git a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java index 8f9d2ed4..367c7425 100644 --- a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java @@ -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 { */ @Autowired private EsGoodsIndexService goodsIndexService; - /** - * 店铺 - */ - @Autowired - private StoreService storeService; /** * 商品 */ @@ -121,6 +117,7 @@ public class GoodsMessageListener implements RocketMQListener { private PromotionGoodsService promotionGoodsService; @Override + @RetryOperation public void onMessage(MessageExt messageExt) { switch (GoodsTagsEnum.valueOf(messageExt.getTags())) { @@ -135,20 +132,32 @@ public class GoodsMessageListener implements RocketMQListener { 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 { List 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 { Map 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 { List 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 { 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 skuIdsByGoodsId = this.goodsSkuService.getSkuIdsByGoodsId(goodsId); - if (skuIdsByGoodsId != null && !skuIdsByGoodsId.isEmpty()) { - this.goodsIndexService.deleteIndexByIds(skuIdsByGoodsId); - } - } + goodsIndexService.deleteIndex(MapUtil.builder(new HashMap()).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 { List 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()).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 { 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 promotionGoodsList = this.promotionGoodsService.listFindAll(searchParams); List 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 goodsSkuByList = this.goodsSkuService.getGoodsSkuByList(searchParams); List 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 { 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 { */ private void generatorGoodsIndex(Goods goods, List goodsSkuList) { int skuSource = 100; + List 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()).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 { } } - if (goodsIndex.getPromotionMap() == null || goodsIndex.getPromotionMap().isEmpty()) { + if (goodsIndex.getOriginPromotionMap() == null || goodsIndex.getOriginPromotionMap().isEmpty()) { Map goodsCurrentPromotionMap = promotionService.getGoodsSkuPromotionMap(goodsIndex.getStoreId(), goodsIndex.getId()); goodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(goodsCurrentPromotionMap)); } @@ -421,21 +449,6 @@ public class GoodsMessageListener implements RocketMQListener { } } - /** - * 修改商品数量 - * - * @param goods 信息体 - */ - private void updateGoodsNum(Goods goods) { - try { - //更新店铺商品数量 - assert goods != null; - storeService.updateStoreGoodsNum(goods.getStoreId()); - } catch (Exception e) { - log.error("修改商品数量错误"); - } - } - /** * 商品购买完成 * 1.更新商品购买数量 diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java index 613380d6..acb0503c 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java @@ -34,7 +34,7 @@ public class CouponExecute implements EveryDayExecute { */ @Override public void execute() { - //将过期优惠券变更为过期状体 + //将过期优惠券变更为过期状态 LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() .eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()) .le(MemberCoupon::getEndTime, new Date()) diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java index a6e99c32..ecf63d58 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java @@ -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 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 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 hotWordsSettingItems = hotWordsSetting.getHotWordsSettingItems(); + if (hotWordsSettingItems != null && !hotWordsSettingItems.isEmpty()) { + for (HotWordsSettingItem hotWordsSettingItem : hotWordsSettingItems) { + cache.zAdd(CachePrefix.HOT_WORD.getPrefix(), hotWordsSettingItem.getScore(), hotWordsSettingItem.getKeywords()); + } + } } } diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/order/OrderEveryDayTaskExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/order/OrderEveryDayTaskExecute.java index f0b8a077..ade5ea90 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/order/OrderEveryDayTaskExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/order/OrderEveryDayTaskExecute.java @@ -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(); diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/statistics/OnlineMemberStatistics.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/statistics/OnlineMemberStatistics.java index e2aee5e3..db9797b0 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/statistics/OnlineMemberStatistics.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/statistics/OnlineMemberStatistics.java @@ -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 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); diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreExecute.java new file mode 100644 index 00000000..283a1552 --- /dev/null +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreExecute.java @@ -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 storeList = storeService.list(new LambdaQueryWrapper().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); + } + } + + + } +} diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/storerating/StoreRatingExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreRatingExecute.java similarity index 97% rename from consumer/src/main/java/cn/lili/timetask/handler/impl/storerating/StoreRatingExecute.java rename to consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreRatingExecute.java index 90ba815e..269ab947 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/storerating/StoreRatingExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/store/StoreRatingExecute.java @@ -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; diff --git a/consumer/src/main/resources/application.yml b/consumer/src/main/resources/application.yml index 8304cf32..ae49a9b8 100644 --- a/consumer/src/main/resources/application.yml +++ b/consumer/src/main/resources/application.yml @@ -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 diff --git a/deploy-api.yml b/deploy-api.yml new file mode 100644 index 00000000..baecfc31 --- /dev/null +++ b/deploy-api.yml @@ -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 \ No newline at end of file diff --git a/framework/pom.xml b/framework/pom.xml index 7b75487f..da681cb3 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -132,6 +132,7 @@ mysql mysql-connector-java + 8.0.29 @@ -143,6 +144,12 @@ org.redisson redisson ${redisson} + + + slf4j-api + org.slf4j + + @@ -422,6 +429,13 @@ + + io.minio + minio + ${minio.version} + + + diff --git a/framework/src/main/java/cn/lili/cache/CachePrefix.java b/framework/src/main/java/cn/lili/cache/CachePrefix.java index b7eb68bd..b2b77006 100644 --- a/framework/src/main/java/cn/lili/cache/CachePrefix.java +++ b/framework/src/main/java/cn/lili/cache/CachePrefix.java @@ -465,16 +465,19 @@ public enum CachePrefix { */ INIT_INDEX_FLAG, + /** + * 店铺 + */ + STORE, /** * 店铺分类 */ STORE_CATEGORY, /** * 用户菜单 - */ - MENU_USER_ID, - /** - * 用户菜单 + *

+ * 这个缓存并非永久缓存,而是300秒缓存,也就是说修改用户关联的部门,关联的角色, + * 部门关联的角色,角色关联的菜单等等,最多需要5分钟才能生效 */ STORE_MENU_USER_ID, /** diff --git a/framework/src/main/java/cn/lili/cache/config/redis/FastJsonRedisSerializer.java b/framework/src/main/java/cn/lili/cache/config/redis/FastJsonRedisSerializer.java index d59e29cf..f0071468 100644 --- a/framework/src/main/java/cn/lili/cache/config/redis/FastJsonRedisSerializer.java +++ b/framework/src/main/java/cn/lili/cache/config/redis/FastJsonRedisSerializer.java @@ -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 implements RedisSerializer { - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - private Class clazz; + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private final Class clazz; public FastJsonRedisSerializer(Class clazz) { super(); @@ -26,7 +27,10 @@ public class FastJsonRedisSerializer implements RedisSerializer { 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 diff --git a/framework/src/main/java/cn/lili/cache/config/redis/RedisConfig.java b/framework/src/main/java/cn/lili/cache/config/redis/RedisConfig.java index 659c1ece..8af75596 100644 --- a/framework/src/main/java/cn/lili/cache/config/redis/RedisConfig.java +++ b/framework/src/main/java/cn/lili/cache/config/redis/RedisConfig.java @@ -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 redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { RedisTemplate template = new RedisTemplate<>(); //使用fastjson序列化 - FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); + FastJsonRedisSerializer 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 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 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); diff --git a/framework/src/main/java/cn/lili/common/aop/annotation/RetryOperation.java b/framework/src/main/java/cn/lili/common/aop/annotation/RetryOperation.java new file mode 100644 index 00000000..d12ab403 --- /dev/null +++ b/framework/src/main/java/cn/lili/common/aop/annotation/RetryOperation.java @@ -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; +} diff --git a/framework/src/main/java/cn/lili/common/aop/interceptor/PreventDuplicateSubmissionsInterceptor.java b/framework/src/main/java/cn/lili/common/aop/interceptor/PreventDuplicateSubmissionsInterceptor.java index 263cf18f..8f6decfe 100644 --- a/framework/src/main/java/cn/lili/common/aop/interceptor/PreventDuplicateSubmissionsInterceptor.java +++ b/framework/src/main/java/cn/lili/common/aop/interceptor/PreventDuplicateSubmissionsInterceptor.java @@ -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); } } diff --git a/framework/src/main/java/cn/lili/common/aop/interceptor/RetryAspect.java b/framework/src/main/java/cn/lili/common/aop/interceptor/RetryAspect.java new file mode 100644 index 00000000..bc9173b6 --- /dev/null +++ b/framework/src/main/java/cn/lili/common/aop/interceptor/RetryAspect.java @@ -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; + } + +} diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index d60a61c6..de63e2b9 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -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, "当前优惠券不允许主动领取"), /** * 拼团 diff --git a/framework/src/main/java/cn/lili/common/event/TransactionCommitSendMQEvent.java b/framework/src/main/java/cn/lili/common/event/TransactionCommitSendMQEvent.java new file mode 100644 index 00000000..7b3d2e73 --- /dev/null +++ b/framework/src/main/java/cn/lili/common/event/TransactionCommitSendMQEvent.java @@ -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; + } +} diff --git a/framework/src/main/java/cn/lili/common/exception/RetryException.java b/framework/src/main/java/cn/lili/common/exception/RetryException.java new file mode 100644 index 00000000..97ccb522 --- /dev/null +++ b/framework/src/main/java/cn/lili/common/exception/RetryException.java @@ -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); + } +} diff --git a/framework/src/main/java/cn/lili/common/listener/TransactionCommitSendMQListener.java b/framework/src/main/java/cn/lili/common/listener/TransactionCommitSendMQListener.java new file mode 100644 index 00000000..c709df75 --- /dev/null +++ b/framework/src/main/java/cn/lili/common/listener/TransactionCommitSendMQListener.java @@ -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()); + } + + +} diff --git a/framework/src/main/java/cn/lili/common/utils/CommonUtil.java b/framework/src/main/java/cn/lili/common/utils/CommonUtil.java index 65c82bc8..61e7ebe9 100644 --- a/framework/src/main/java/cn/lili/common/utils/CommonUtil.java +++ b/framework/src/main/java/cn/lili/common/utils/CommonUtil.java @@ -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(); } } diff --git a/framework/src/main/java/cn/lili/common/utils/DateUtil.java b/framework/src/main/java/cn/lili/common/utils/DateUtil.java index b07f0bde..ec6c5ef4 100644 --- a/framework/src/main/java/cn/lili/common/utils/DateUtil.java +++ b/framework/src/main/java/cn/lili/common/utils/DateUtil.java @@ -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); + } + /** * 当天的开始时间 * diff --git a/framework/src/main/java/cn/lili/common/utils/StringUtils.java b/framework/src/main/java/cn/lili/common/utils/StringUtils.java index f3ae80e1..bf9df5b6 100644 --- a/framework/src/main/java/cn/lili/common/utils/StringUtils.java +++ b/framework/src/main/java/cn/lili/common/utils/StringUtils.java @@ -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); + } + /** * 过滤特殊字符串 * diff --git a/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java b/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java index a090cc35..9929ff20 100644 --- a/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java +++ b/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java @@ -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 response = new AtomicReference<>(); client.indices().putMappingAsync( request, RequestOptions.DEFAULT, new ActionListener() { @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); diff --git a/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java b/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java index 38b63496..b80da178 100644 --- a/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java +++ b/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java @@ -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 clusterNodes = elasticsearchProperties.getClusterNodes(); HttpHost[] httpHosts = new HttpHost[clusterNodes.size()]; diff --git a/framework/src/main/java/cn/lili/modules/connect/service/ConnectService.java b/framework/src/main/java/cn/lili/modules/connect/service/ConnectService.java index 6df3b143..9aef44aa 100644 --- a/framework/src/main/java/cn/lili/modules/connect/service/ConnectService.java +++ b/framework/src/main/java/cn/lili/modules/connect/service/ConnectService.java @@ -112,4 +112,11 @@ public interface ConnectService extends IService { * @return */ Connect queryConnect(ConnectQueryDTO connectQueryDTO); + + /** + * 根据会员id删除记录 + * + * @param userId 会员id + */ + void deleteByMemberId(String userId); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java index f7a98a6b..942bf897 100644 --- a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java @@ -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 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 impl } return memberTokenGenerate.createToken(member, longTerm); } catch (NoPermissionException e) { + log.error("联合登陆失败:", e); throw e; } } @@ -121,7 +134,7 @@ public class ConnectServiceImpl extends ServiceImpl 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 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 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 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 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 impl return this.getOne(queryWrapper); } + @Override + public void deleteByMemberId(String userId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Connect::getUserId, userId); + this.remove(queryWrapper); + } + /** * 会员绑定 绑定微信小程序 *

@@ -252,9 +276,9 @@ public class ConnectServiceImpl extends ServiceImpl impl * 这样,微信小程序注册之后,其他app 公众号页面,都可以实现绑定自动登录功能 *

* - * @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 impl lambdaQueryWrapper.eq(Connect::getUnionId, unionId); lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT.name()); List 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 impl } }//如果openid 不为空 则为账号绑定openid if (CharSequenceUtil.isNotEmpty(openId)) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper(); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(Connect::getUnionId, openId); lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT_MP_OPEN_ID.name()); List connects = this.list(lambdaQueryWrapper); diff --git a/framework/src/main/java/cn/lili/modules/distribution/entity/dos/DistributionOrder.java b/framework/src/main/java/cn/lili/modules/distribution/entity/dos/DistributionOrder.java index 491a8faf..fc760ac4 100644 --- a/framework/src/main/java/cn/lili/modules/distribution/entity/dos/DistributionOrder.java +++ b/framework/src/main/java/cn/lili/modules/distribution/entity/dos/DistributionOrder.java @@ -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 = "提成金额") diff --git a/framework/src/main/java/cn/lili/modules/distribution/serviceimpl/DistributionCashServiceImpl.java b/framework/src/main/java/cn/lili/modules/distribution/serviceimpl/DistributionCashServiceImpl.java index 805fc9db..8f3e18cc 100644 --- a/framework/src/main/java/cn/lili/modules/distribution/serviceimpl/DistributionCashServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/distribution/serviceimpl/DistributionCashServiceImpl.java @@ -73,6 +73,7 @@ public class DistributionCashServiceImpl extends ServiceImpl key) { + if (key == null || key.isEmpty()) { + return; + } + MinioClient ossClient = getOssClient(); + List 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; + } + } + + +} diff --git a/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java b/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java index fa608502..11068e7d 100644 --- a/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java @@ -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 implements FileService { @Autowired - private FileManagerPlugin fileManagerPlugin; + private FilePluginFactory filePluginFactory; @Override public void batchDelete(List ids) { @@ -42,7 +43,7 @@ public class FileServiceImpl extends ServiceImpl implements Fi List files = this.list(queryWrapper); List 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 implements Fi List files = this.list(queryWrapper); List keys = new ArrayList<>(); files.forEach(item -> keys.add(item.getFileKey())); - fileManagerPlugin.deleteFile(keys); + filePluginFactory.filePlugin().deleteFile(keys); this.remove(queryWrapper); } diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/DraftGoods.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/DraftGoods.java index 03652d78..da2dbed2 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/DraftGoods.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/DraftGoods.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java index 0bb3ed17..7a079046 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java @@ -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 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; } -} +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java index 767fd0bb..0c89fdc1 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java @@ -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(); + } + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsWords.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsWords.java index eff94046..d6890ec9 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsWords.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsWords.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Studio.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Studio.java index b049b84e..b9913804 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Studio.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Studio.java @@ -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; } diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/StudioCommodity.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/StudioCommodity.java index 1b6e90d7..061dac65 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/StudioCommodity.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/StudioCommodity.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Wholesale.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Wholesale.java new file mode 100644 index 00000000..1838d006 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Wholesale.java @@ -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; +} diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java index 497bc349..6981372e 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java @@ -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> 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> skuList; + + /** + * 批发商品规则 + */ + @ApiModelProperty(value = "批发商品规则") + private List wholesaleList; + public String getGoodsName() { //对商品对名称做一个极限处理。这里没有用xss过滤是因为xss过滤为全局过滤,影响很大。 // 业务中,全局代码中只有商品名称不能拥有英文逗号,是由于商品名称存在一个数据库联合查询,结果要根据逗号分组 diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSearchParams.java b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSearchParams.java index db523f1d..679c03d8 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSearchParams.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSearchParams.java @@ -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 QueryWrapper queryWrapper() { QueryWrapper 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); diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSkuDTO.java b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSkuDTO.java new file mode 100644 index 00000000..a93db09f --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsSkuDTO.java @@ -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; + +} diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dto/WholesaleDTO.java b/framework/src/main/java/cn/lili/modules/goods/entity/dto/WholesaleDTO.java new file mode 100644 index 00000000..31cbd0bb --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/entity/dto/WholesaleDTO.java @@ -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; + +} diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/enums/GoodsSalesModeEnum.java b/framework/src/main/java/cn/lili/modules/goods/entity/enums/GoodsSalesModeEnum.java index 2cabe2c7..b6d03aa5 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/enums/GoodsSalesModeEnum.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/enums/GoodsSalesModeEnum.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsSkuVO.java b/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsSkuVO.java index 32f3a030..4721a4c9 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsSkuVO.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsSkuVO.java @@ -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 { diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsVO.java b/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsVO.java index 804940a3..bf62838f 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsVO.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/vos/GoodsVO.java @@ -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 skuList; + + @ApiModelProperty(value = "批发商品消费规则列表") + private List wholesaleList; } diff --git a/framework/src/main/java/cn/lili/modules/goods/event/GeneratorEsGoodsIndexEvent.java b/framework/src/main/java/cn/lili/modules/goods/event/GeneratorEsGoodsIndexEvent.java deleted file mode 100644 index ff5da90f..00000000 --- a/framework/src/main/java/cn/lili/modules/goods/event/GeneratorEsGoodsIndexEvent.java +++ /dev/null @@ -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; - } -} diff --git a/framework/src/main/java/cn/lili/modules/goods/listener/GeneratorEsGoodsIndexListener.java b/framework/src/main/java/cn/lili/modules/goods/listener/GeneratorEsGoodsIndexListener.java deleted file mode 100644 index 7c5b95ba..00000000 --- a/framework/src/main/java/cn/lili/modules/goods/listener/GeneratorEsGoodsIndexListener.java +++ /dev/null @@ -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()); - } - -} diff --git a/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java b/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java index 62f65589..e17f6d41 100644 --- a/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java +++ b/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java @@ -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 { @Select("SELECT id FROM li_goods_sku WHERE goods_id = #{goodsId}") List 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 queryByParams(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/mapper/WholesaleMapper.java b/framework/src/main/java/cn/lili/modules/goods/mapper/WholesaleMapper.java new file mode 100644 index 00000000..372d4d43 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/mapper/WholesaleMapper.java @@ -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 { +} diff --git a/framework/src/main/java/cn/lili/modules/goods/service/CategoryService.java b/framework/src/main/java/cn/lili/modules/goods/service/CategoryService.java index 86888589..1941fe40 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/CategoryService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/CategoryService.java @@ -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 { @@ -35,7 +31,6 @@ public interface CategoryService extends IService { * @param id * @return */ - @Cacheable(key = "#id") Category getCategoryById(String id); /** @@ -99,7 +94,6 @@ public interface CategoryService extends IService { * @param category 商品分类信息 * @return 修改结果 */ - @CacheEvict(key = "#category.id") void updateCategory(Category category); /** diff --git a/framework/src/main/java/cn/lili/modules/goods/service/GoodsGalleryService.java b/framework/src/main/java/cn/lili/modules/goods/service/GoodsGalleryService.java index 501e22f1..65592834 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/GoodsGalleryService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/GoodsGalleryService.java @@ -36,4 +36,11 @@ public interface GoodsGalleryService extends IService { */ List goodsGalleryList(String goodsId); + /** + * 根据商品 id删除商品相册缩略图 + * + * @param goodsId 商品ID + */ + void removeByGoodsId(String goodsId); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/service/GoodsService.java b/framework/src/main/java/cn/lili/modules/goods/service/GoodsService.java index aea28e71..1232cff6 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/GoodsService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/GoodsService.java @@ -129,6 +129,17 @@ public interface GoodsService extends IService { */ Boolean updateGoodsMarketAble(List goodsIds, GoodsStatusEnum goodsStatusEnum, String underReason); + + /** + * 更新商品上架状态状态 + * + * @param storeId 店铺ID + * @param goodsStatusEnum 更新的商品状态 + * @param underReason 下架原因 + * @return 更新结果 + */ + Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason); + /** * 更新商品上架状态状态 * diff --git a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java index 40c25077..a78f9bb0 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java @@ -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 { /** * 添加商品sku * - * @param skuList sku列表 - * @param goods 商品信息 + * @param goods 商品信息 + * @param goodsOperationDTO 商品操作信息 */ - void add(List> 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> skuList, Goods goods, Boolean regeneratorSkuFlag); + void update(Goods goods, GoodsOperationDTO goodsOperationDTO); /** * 更新商品sku @@ -79,6 +82,14 @@ public interface GoodsSkuService extends IService { */ GoodsSku getGoodsSkuByIdFromCache(String id); + /** + * 从缓存中获取可参与促销商品 + * + * @param skuId skuid + * @return 商品详情 + */ + GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId); + /** * 获取商品sku详情 * @@ -136,6 +147,16 @@ public interface GoodsSkuService extends IService { */ IPage getGoodsSkuByPage(GoodsSearchParams searchParams); + + /** + * 分页查询商品sku信息 + * + * @param page 分页参数 + * @param queryWrapper 查询参数 + * @return 商品sku信息 + */ + IPage getGoodsSkuDTOByPage(Page page, Wrapper queryWrapper); + /** * 列表查询商品sku信息 * @@ -151,6 +172,15 @@ public interface GoodsSkuService extends IService { */ 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 { * @return 全部skuId的集合 */ List getSkuIdsByGoodsId(String goodsId); + + /** + * 删除并且新增sku,即覆盖之前信息 + * + * @param goodsSkus 商品sku集合 + * @return + */ + boolean deleteAndInsertGoodsSkus(List goodsSkus); + + /** + * 统计sku总数 + * + * @param storeId 店铺id + * @return sku总数 + */ + Long countSkuNum(String storeId); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/service/StudioService.java b/framework/src/main/java/cn/lili/modules/goods/service/StudioService.java index 40d273af..906c3696 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/StudioService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/StudioService.java @@ -70,7 +70,7 @@ public interface StudioService extends IService { * @param status 直播间状态 * @return 直播间分页 */ - IPage studioList(PageVO pageVO, Integer recommend, String status); + IPage studioList(PageVO pageVO, Integer recommend, String status); /** * 修改直播间状态 diff --git a/framework/src/main/java/cn/lili/modules/goods/service/WholesaleService.java b/framework/src/main/java/cn/lili/modules/goods/service/WholesaleService.java new file mode 100644 index 00000000..37346af0 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/service/WholesaleService.java @@ -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 { + + + List findByGoodsId(String goodsId); + + Boolean removeByGoodsId(String goodsId); + + /** + * 匹配批发规则 + * + * @param goodsId 商品规则 + * @param num 数量 + * @return 批发规则 + */ + Wholesale match(String goodsId, Integer num); + +} diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java index c08865d9..c262f9ff 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java @@ -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 implements CategoryService { private static final String DELETE_FLAG_COLUMN = "delete_flag"; @@ -60,6 +64,7 @@ public class CategoryServiceImpl extends ServiceImpl i } @Override + @Cacheable(key = "#id") public Category getCategoryById(String id) { return this.getById(id); } @@ -216,6 +221,7 @@ public class CategoryServiceImpl extends ServiceImpl i } @Override + @CacheEvict(key = "#category.id") @Transactional(rollbackFor = Exception.class) public void updateCategory(Category category) { //判断分类佣金是否正确 @@ -242,6 +248,7 @@ public class CategoryServiceImpl extends ServiceImpl 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 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 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 i */ private void removeCache() { cache.remove(CachePrefix.CATEGORY.getPrefix()); + cache.remove(CachePrefix.CATEGORY_ARRAY.getPrefix()); } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsGalleryServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsGalleryServiceImpl.java index 5e4577d7..a6493be4 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsGalleryServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsGalleryServiceImpl.java @@ -75,4 +75,14 @@ public class GoodsGalleryServiceImpl extends ServiceImpl().eq("goods_id", goodsId)); } + + /** + * 根据商品 id删除商品相册缩略图 + * + * @param goodsId 商品ID + */ + @Override + public void removeByGoodsId(String goodsId) { + this.baseMapper.delete(new UpdateWrapper().eq("goods_id", goodsId)); + } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java index a898c2e9..f4045f16 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java @@ -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 implements @Autowired private FreightTemplateService freightTemplateService; + @Autowired + private WholesaleService wholesaleService; + @Autowired private Cache cache; @@ -171,7 +173,7 @@ public class GoodsServiceImpl extends ServiceImpl 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 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 implements if (CharSequenceUtil.isNotEmpty(goods.getParams())) { goodsVO.setGoodsParamsDTOList(JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class)); } + + List 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 implements @Override @Transactional(rollbackFor = Exception.class) public boolean auditGoods(List goodsIds, GoodsAuthEnum goodsAuthEnum) { + List goodsCacheKeys = new ArrayList<>(); boolean result = false; for (String goodsId : goodsIds) { Goods goods = this.checkExist(goodsId); @@ -332,12 +341,13 @@ public class GoodsServiceImpl extends ServiceImpl 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 implements LambdaQueryWrapper queryWrapper = this.getQueryWrapperByStoreAuthority(); queryWrapper.in(Goods::getId, goodsIds); List 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 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 implements LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(Goods::getId, goodsIds); List 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 implements LambdaQueryWrapper queryWrapper = this.getQueryWrapperByStoreAuthority(); queryWrapper.in(Goods::getId, goodsIds); List goodsList = this.list(queryWrapper); + List 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 implements return this.count( new LambdaQueryWrapper() .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 goodsIds, GoodsStatusEnum goodsStatusEnum, List goodsList) { + List 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索引的信息 * diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java index f7a5932f..5438ae95 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java @@ -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 i @Autowired private ApplicationEventPublisher applicationEventPublisher; + @Autowired + private WholesaleService wholesaleService; + + @Autowired + private List salesModelRenders; + @Override @Transactional(rollbackFor = Exception.class) - public void add(List> skuList, Goods goods) { - // 检查是否需要生成索引 - List 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 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> 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 newSkuList; + List skuList; //删除旧的sku信息 - if (Boolean.TRUE.equals(regeneratorSkuFlag)) { + if (Boolean.TRUE.equals(goodsOperationDTO.getRegeneratorSkuFlag())) { + skuList = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO); + renderGoodsSkuList(skuList, goodsOperationDTO); List goodsListByGoodsId = getGoodsListByGoodsId(goods.getId()); List oldSkuIds = new ArrayList<>(); //删除旧索引 @@ -149,36 +160,32 @@ public class GoodsSkuServiceImpl extends ServiceImpl i oldSkuIds.add(goodsSkuVO.getId()); cache.remove(GoodsSkuService.getCacheKeys(goodsSkuVO.getId())); } - goodsIndexService.deleteIndexByIds(oldSkuIds); - this.removeByIds(oldSkuIds); + + this.remove(new LambdaQueryWrapper().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 map : skuList) { - GoodsSku sku = new GoodsSku(); - //设置商品信息 - goodsInfo(sku, goods); - //设置商品规格信息 - skuInfo(sku, goods, map, null); - newSkuList.add(sku); + skuList = new ArrayList<>(); + for (Map 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().eq(GoodsSku::getGoodsId, goods.getId())); + this.saveOrUpdateBatch(skuList); + this.updateStock(skuList); + this.generateEs(goods); } } @@ -231,6 +238,15 @@ public class GoodsSkuServiceImpl extends ServiceImpl 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 getGoodsSkuDetail(String goodsId, String skuId) { Map map = new HashMap<>(16); @@ -244,13 +260,16 @@ public class GoodsSkuServiceImpl extends ServiceImpl 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 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> containsPromotion = promotionMap.entrySet().stream().filter(i -> - i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); + Optional> 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 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 i @Transactional(rollbackFor = Exception.class) public void updateGoodsSkuStatus(Goods goods) { LambdaUpdateWrapper 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 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 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 i @Override public List getGoodsListByGoodsId(String goodsId) { - List list = this.list(new LambdaQueryWrapper().eq(GoodsSku::getGoodsId, goodsId)); + List list = this.list(new LambdaQueryWrapper().eq(GoodsSku::getGoodsId, goodsId).orderByAsc(GoodsSku::getGoodsName)); return this.getGoodsSkuVOList(list); } @@ -423,6 +466,11 @@ public class GoodsSkuServiceImpl extends ServiceImpl i return this.page(PageUtil.initPage(searchParams), searchParams.queryWrapper()); } + @Override + public IPage getGoodsSkuDTOByPage(Page page, Wrapper queryWrapper) { + return this.baseMapper.queryByParams(page, queryWrapper); + } + /** * 列表查询商品sku信息 * @@ -481,18 +529,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public void updateGoodsStuck(List goodsSkus) { - //商品id集合 hashset 去重复 - Set goodsIds = new HashSet<>(); - for (GoodsSku sku : goodsSkus) { - goodsIds.add(sku.getGoodsId()); - } + Map> groupByGoodsIds = goodsSkus.stream().collect(Collectors.groupingBy(GoodsSku::getGoodsId)); //获取相关的sku集合 LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.in(GoodsSku::getGoodsId, goodsIds); + lambdaQueryWrapper.in(GoodsSku::getGoodsId, groupByGoodsIds.keySet()); List 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 i //修改规格索引,发送mq消息 - Map updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap( - MapUtil.builder(new HashMap()).put("id", goodsSku.getId()).build(), - MapUtil.builder(new HashMap()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum) - .put("grade", grade).build()); + Map updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(MapUtil.builder(new HashMap()).put("id", goodsSku.getId()).build(), MapUtil.builder(new HashMap()).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 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 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 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 i /** - * 增加sku集合 + * 批量渲染商品sku * - * @param skuList sku列表 - * @param goods 商品信息 + * @param goodsSkuList sku集合 + * @param goodsOperationDTO 商品操作DTO */ - List addGoodsSku(List> skuList, Goods goods) { - List skus = new ArrayList<>(); - for (Map skuVO : skuList) { - Map 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 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 add(Map map, Goods goods) { - Map 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 map, EsGoodsIndex esGoodsIndex) { - - //规格简短信息 - StringBuilder simpleSpecs = new StringBuilder(); - //商品名称 - StringBuilder goodsName = new StringBuilder(goods.getGoodsName()); - //规格商品缩略图 - String thumbnail = ""; - String small = ""; - //规格值 - Map specMap = new HashMap<>(16); - //商品属性 - List attributes = new ArrayList<>(); - - //获取规格信息 - for (Map.Entry 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> images = (List>) 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> 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()); } } diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/StoreGoodsLabelServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/StoreGoodsLabelServiceImpl.java index 99801a9d..6d5f9a0e 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/StoreGoodsLabelServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/StoreGoodsLabelServiceImpl.java @@ -56,7 +56,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl 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 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 impleme } @Override - public IPage studioList(PageVO pageVO, Integer recommend, String status) { + public IPage studioList(PageVO pageVO, Integer recommend, String status) { QueryWrapper queryWrapper = new QueryWrapper() .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 records = page.getRecords(); + List 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; } diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/WholesaleServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/WholesaleServiceImpl.java new file mode 100644 index 00000000..d8c2b98c --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/WholesaleServiceImpl.java @@ -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 implements WholesaleService { + + @Autowired + private Cache> cache; + + @Override + @Cacheable(key = "#goodsId") + public List findByGoodsId(String goodsId) { + LambdaQueryWrapper 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 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 wholesaleList = cache.get("{wholesale}_" + goodsId); + if (wholesaleList == null) { + wholesaleList = this.findByGoodsId(goodsId); + cache.put("{wholesale}_" + goodsId, wholesaleList); + } + List 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; + } +} diff --git a/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java b/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java new file mode 100644 index 00000000..cc86a43f --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java @@ -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 skuInfo, GoodsOperationDTO goodsOperationDTO) { + GoodsSku goodsSku = new GoodsSku(goods); + builderSingle(goodsSku, skuInfo, goodsOperationDTO); + return goodsSku; + } + + /** + * 批量构建商品sku + * + * @param goods 商品 + * @param goodsOperationDTO 商品操作信息 + * @return 商品sku + */ + public static List 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 skuInfo, GoodsOperationDTO goodsOperationDTO) { + builderSingle(goodsSku, skuInfo, goodsOperationDTO); + return goodsSku; + } + + private static void builderSingle(GoodsSku goodsSku, Map skuInfo, GoodsOperationDTO goodsOperationDTO) { + Assert.notNull(goodsSku, "goodsSku不能为空"); + Assert.notEmpty(skuInfo, "skuInfo不能为空"); + //规格简短信息 + StringBuilder simpleSpecs = new StringBuilder(); + //商品名称 + StringBuilder goodsName = new StringBuilder(goodsOperationDTO.getGoodsName()); + //规格值 + Map specMap = new HashMap<>(16); + + // 原始规格项 + String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight"}; + //获取规格信息 + for (Map.Entry 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 builderBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) { + Assert.notEmpty(goodsOperationDTO.getSkuList(), "goodsOperationDTO.getSkuList()不能为空"); + Assert.notNull(goods, "goods不能为空"); + List goodsSkus = new ArrayList<>(); + for (Map skuInfo : goodsOperationDTO.getSkuList()) { + GoodsSku goodsSku = new GoodsSku(goods); + builderSingle(goodsSku, skuInfo, goodsOperationDTO); + goodsSkus.add(goodsSku); + } + return goodsSkus; + } + + +} diff --git a/framework/src/main/java/cn/lili/modules/goods/sku/render/SalesModelRender.java b/framework/src/main/java/cn/lili/modules/goods/sku/render/SalesModelRender.java new file mode 100644 index 00000000..cc1f4591 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/sku/render/SalesModelRender.java @@ -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 goodsSkus, GoodsOperationDTO goodsOperationDTO); + +} diff --git a/framework/src/main/java/cn/lili/modules/goods/sku/render/impl/WholesaleSaleModelRenderImpl.java b/framework/src/main/java/cn/lili/modules/goods/sku/render/impl/WholesaleSaleModelRenderImpl.java new file mode 100644 index 00000000..93337ce0 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/goods/sku/render/impl/WholesaleSaleModelRenderImpl.java @@ -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 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 goodsSkus, GoodsOperationDTO goodsOperationDTO) { + Assert.notEmpty(goodsOperationDTO.getWholesaleList(), "批发规则不能为空"); + this.checkWholesaleList(goodsOperationDTO.getWholesaleList(), goodsSkus.get(0)); + List 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 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(); + } +} diff --git a/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberSign.java b/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberSign.java index adec8b76..504975ca 100644 --- a/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberSign.java +++ b/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberSign.java @@ -42,4 +42,8 @@ public class MemberSign extends BaseIdEntity { @ApiModelProperty(value = "连续签到天数") private Integer signDay; + + @ApiModelProperty(value = "签到日 为数字 从现在减去19700101 的日期") + private Integer day; + } diff --git a/framework/src/main/java/cn/lili/modules/member/entity/dto/ManagerMemberEditDTO.java b/framework/src/main/java/cn/lili/modules/member/entity/dto/ManagerMemberEditDTO.java index 6b021869..2f83b11f 100644 --- a/framework/src/main/java/cn/lili/modules/member/entity/dto/ManagerMemberEditDTO.java +++ b/framework/src/main/java/cn/lili/modules/member/entity/dto/ManagerMemberEditDTO.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/member/entity/vo/EvaluationNumberVO.java b/framework/src/main/java/cn/lili/modules/member/entity/vo/EvaluationNumberVO.java index 92084f43..52d8b772 100644 --- a/framework/src/main/java/cn/lili/modules/member/entity/vo/EvaluationNumberVO.java +++ b/framework/src/main/java/cn/lili/modules/member/entity/vo/EvaluationNumberVO.java @@ -12,7 +12,7 @@ import lombok.Data; @Data public class EvaluationNumberVO { - @ApiModelProperty(value = "全部商品") + @ApiModelProperty(value = "全部评价") private Integer all; @ApiModelProperty(value = "好评数量") diff --git a/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java b/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java index f829eacc..cdde3b9f 100644 --- a/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java +++ b/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java @@ -18,17 +18,6 @@ import java.util.List; * @since 2020-02-25 14:10:16 */ public interface FootprintMapper extends BaseMapper { - - /** - * 获取用户足迹的SkuId分页 - * - * @param page 分页 - * @param queryWrapper 查询条件 - * @return 用户足迹的SkuId分页 - */ - @Select("select sku_id from li_foot_print ${ew.customSqlSegment} ") - List footprintSkuIdList(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - /** * 删除超过100条后的记录 * diff --git a/framework/src/main/java/cn/lili/modules/member/mapper/MemberEvaluationMapper.java b/framework/src/main/java/cn/lili/modules/member/mapper/MemberEvaluationMapper.java index f6b88ce2..3806ea47 100644 --- a/framework/src/main/java/cn/lili/modules/member/mapper/MemberEvaluationMapper.java +++ b/framework/src/main/java/cn/lili/modules/member/mapper/MemberEvaluationMapper.java @@ -38,7 +38,7 @@ public interface MemberEvaluationMapper extends BaseMapper { * @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> getEvaluationNumber(String goodsId); /** diff --git a/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java b/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java index fc5d8ca3..3005ce96 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java @@ -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 { * @param pageVO 分页 * @return 会员浏览历史列表 */ - List footPrintPage(PageVO pageVO); + IPage footPrintPage(PageVO pageVO); /** * 获取当前会员的浏览记录数量 diff --git a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java index 91ed53b9..3dc81232 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java @@ -25,6 +25,11 @@ import java.util.Map; */ public interface MemberService extends IService { + /** + * 默认密码 + */ + static String DEFAULT_PASSWORD = "111111"; + /** * 获取当前登录的用户信息 * @@ -92,6 +97,29 @@ public interface MemberService extends IService { */ 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 { /** * 获取用户VO + * * @param id 会员id * @return 用户VO */ diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java index 0fea8a25..41e4b815 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java @@ -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 implements FootprintService { - /** - * es商品业务层 - */ + @Autowired private EsGoodsSearchService esGoodsSearchService; @@ -74,20 +74,33 @@ public class FootprintServiceImpl extends ServiceImpl footPrintPage(PageVO pageVO) { + public IPage footPrintPage(PageVO pageVO) { LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.eq(FootPrint::getMemberId, UserContext.getCurrentUser().getId()); lambdaQueryWrapper.eq(FootPrint::getDeleteFlag, false); - lambdaQueryWrapper.orderByDesc(FootPrint::getUpdateTime); - List skuIdList = this.baseMapper.footprintSkuIdList(PageUtil.initPage(pageVO), lambdaQueryWrapper); - if (!skuIdList.isEmpty()) { - List list = esGoodsSearchService.getEsGoodsBySkuIds(skuIdList); + lambdaQueryWrapper.orderByDesc(FootPrint::getCreateTime); + IPage footPrintPages = this.page(PageUtil.initPage(pageVO), lambdaQueryWrapper); + + + //定义结果 + IPage esGoodsIndexIPage = new Page<>(); + + if (footPrintPages.getRecords() == null || footPrintPages.getRecords().isEmpty()) { + return esGoodsIndexIPage; + } else { + List 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 diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberEvaluationServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberEvaluationServiceImpl.java index 393a2339..1a56ed86 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberEvaluationServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberEvaluationServiceImpl.java @@ -113,13 +113,15 @@ public class MemberEvaluationServiceImpl extends ServiceImpl impleme */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; - /** - * RocketMQ - */ + @Autowired - private RocketMQTemplate rocketMQTemplate; + private ApplicationEventPublisher applicationEventPublisher; /** * 缓存 */ @@ -121,12 +116,17 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override - public Member findByMobile(String mobile) { + public boolean findByMobile(String uuid, String mobile) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mobile", mobile); - return this.baseMapper.selectOne(queryWrapper); - } + Member member = this.baseMapper.selectOne(queryWrapper); + if (member == null) { + throw new ServiceException(ResultCode.USER_NOT_PHONE); + } + cache.put(CachePrefix.FIND_MOBILE + uuid, mobile, 300L); + return true; + } @Override public Token usernameLogin(String username, String password) { @@ -181,6 +181,7 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override + @Transactional public Token autoRegister(ConnectAuthUser authUser) { if (CharSequenceUtil.isEmpty(authUser.getNickname())) { @@ -194,11 +195,12 @@ public class MemberServiceImpl extends ServiceImpl impleme Member member = new Member(username, UuidUtils.getUUID(), authUser.getAvatar(), authUser.getNickname(), authUser.getGender() != null ? Convert.toInt(authUser.getGender().getCode()) : 0); registerHandler(member); + member.setPassword(DEFAULT_PASSWORD); //绑定登录方式 loginBindUser(member, authUser.getUuid(), authUser.getSource()); return memberTokenGenerate.createToken(member, false); } catch (ServiceException e) { - log.error("自动注册服务泡出异常:", e); + log.error("自动注册服务抛出异常:", e); throw e; } catch (Exception e) { log.error("自动注册异常:", e); @@ -223,6 +225,7 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override + @Transactional public Token mobilePhoneLogin(String mobilePhone) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mobile", mobilePhone); @@ -241,12 +244,13 @@ public class MemberServiceImpl extends ServiceImpl impleme * * @param member */ - private void registerHandler(Member member) { + @Transactional + public void registerHandler(Member member) { member.setId(SnowFlake.getIdStr()); //保存会员 this.save(member); - String destination = rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_REGISTER.name(); - rocketMQTemplate.asyncSend(destination, member, RocketmqSendCallbackBuilder.commonCallback()); + // 发送会员注册信息 + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), member)); } @Override @@ -261,8 +265,13 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override - public Member modifyPass(String memberId, String oldPassword, String newPassword) { - Member member = this.getById(memberId); + @DemoSite + public Member modifyPass(String oldPassword, String newPassword) { + AuthUser tokenUser = UserContext.getCurrentUser(); + if (tokenUser == null) { + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + Member member = this.getById(tokenUser.getId()); //判断旧密码输入是否正确 if (!new BCryptPasswordEncoder().matches(oldPassword, member.getPassword())) { throw new ServiceException(ResultCode.USER_OLD_PASSWORD_ERROR); @@ -276,6 +285,65 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override + public boolean canInitPass() { + AuthUser tokenUser = UserContext.getCurrentUser(); + if (tokenUser == null) { + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + Member member = this.getById(tokenUser.getId()); + return member.getPassword().equals(DEFAULT_PASSWORD); + + } + + @Override + public void initPass(String password) { + AuthUser tokenUser = UserContext.getCurrentUser(); + if (tokenUser == null) { + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + Member member = this.getById(tokenUser.getId()); + if (member.getPassword().equals(DEFAULT_PASSWORD)) { + //修改会员密码 + LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); + lambdaUpdateWrapper.eq(Member::getId, member.getId()); + lambdaUpdateWrapper.set(Member::getPassword, new BCryptPasswordEncoder().encode(password)); + this.update(lambdaUpdateWrapper); + } + throw new ServiceException(ResultCode.UNINITIALIZED_PASSWORD); + + } + + @Override + public void cancellation(String password) { + + AuthUser tokenUser = UserContext.getCurrentUser(); + if (tokenUser == null) { + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + Member member = this.getById(tokenUser.getId()); + if (member.getPassword().equals(new BCryptPasswordEncoder().encode(password))) { + //删除联合登录 + connectService.deleteByMemberId(member.getId()); + //混淆用户信息 + this.confusionMember(member); + } + } + + /** + * 混淆之前的会员信息 + * + * @param member + */ + private void confusionMember(Member member) { + member.setUsername(UuidUtils.getUUID()); + member.setMobile(UuidUtils.getUUID() + member.getMobile()); + member.setNickName("用户已注销"); + member.setDisabled(false); + this.updateById(member); + } + + @Override + @Transactional public Token register(String userName, String password, String mobilePhone) { //检测会员信息 checkMember(userName, mobilePhone); @@ -283,8 +351,7 @@ public class MemberServiceImpl extends ServiceImpl impleme Member member = new Member(userName, new BCryptPasswordEncoder().encode(password), mobilePhone); //注册成功后用户自动登录 registerHandler(member); - Token token = memberTokenGenerate.createToken(member, false); - return token; + return memberTokenGenerate.createToken(member, false); } @Override @@ -321,6 +388,7 @@ public class MemberServiceImpl extends ServiceImpl impleme } @Override + @Transactional public Member addMember(MemberAddDTO memberAddDTO) { //检测会员信息 @@ -334,21 +402,16 @@ public class MemberServiceImpl extends ServiceImpl impleme @Override public Member updateMember(ManagerMemberEditDTO managerMemberEditDTO) { - //判断是否用户登录并且会员ID为当前登录会员ID - AuthUser tokenUser = UserContext.getCurrentUser(); - if (tokenUser == null) { - throw new ServiceException(ResultCode.USER_NOT_LOGIN); - } //过滤会员昵称敏感词 - if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(managerMemberEditDTO.getNickName())) { + if (StringUtils.isNotBlank(managerMemberEditDTO.getNickName())) { managerMemberEditDTO.setNickName(SensitiveWordsFilter.filter(managerMemberEditDTO.getNickName())); } //如果密码不为空则加密密码 - if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(managerMemberEditDTO.getPassword())) { + if (StringUtils.isNotBlank(managerMemberEditDTO.getPassword())) { managerMemberEditDTO.setPassword(new BCryptPasswordEncoder().encode(managerMemberEditDTO.getPassword())); } //查询会员信息 - Member member = this.findByUsername(managerMemberEditDTO.getUsername()); + Member member = this.getById(managerMemberEditDTO.getId()); //传递修改会员信息 BeanUtil.copyProperties(managerMemberEditDTO, member); this.updateById(member); @@ -401,8 +464,7 @@ public class MemberServiceImpl extends ServiceImpl impleme memberPointMessage.setPoint(point); memberPointMessage.setType(type); memberPointMessage.setMemberId(memberId); - String destination = rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_POINT_CHANGE.name(); - rocketMQTemplate.asyncSend(destination, memberPointMessage, RocketmqSendCallbackBuilder.commonCallback()); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("update member point", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_POINT_CHANGE.name(), memberPointMessage)); return true; } return false; @@ -426,10 +488,10 @@ public class MemberServiceImpl extends ServiceImpl impleme * @param mobilePhone 手机号 * @return 会员 */ - private Long findMember(String userName,String mobilePhone) { + private Long findMember(String mobilePhone, String userName) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mobile", mobilePhone) - .eq("username", userName); + .or().eq("username", userName); return this.baseMapper.selectCount(queryWrapper); } @@ -579,31 +641,6 @@ public class MemberServiceImpl extends ServiceImpl impleme } } - @Override - public void updateHaveShop(Boolean haveStore, String storeId, List memberIds) { - List members = this.baseMapper.selectBatchIds(memberIds); - if (members.size() > 0) { - members.forEach(member -> { - member.setHaveStore(haveStore); - if (haveStore) { - member.setStoreId(storeId); - } else { - member.setStoreId(null); - } - }); - this.updateBatchById(members); - } - } - - @Override - public void resetPassword(List ids) { - String password = new BCryptPasswordEncoder().encode(StringUtils.md5("123456")); - LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); - lambdaUpdateWrapper.in(Member::getId, ids); - lambdaUpdateWrapper.set(Member::getPassword, password); - this.update(lambdaUpdateWrapper); - } - /** * 获取所有会员的手机号 * @@ -641,9 +678,8 @@ public class MemberServiceImpl extends ServiceImpl impleme */ private void checkMember(String userName, String mobilePhone) { //判断手机号是否存在 - if (findMember(userName, mobilePhone) > 0) { + if (findMember(mobilePhone, userName) > 0) { throw new ServiceException(ResultCode.USER_EXIST); } } - } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java index fbac26ba..c25f4145 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java @@ -77,8 +77,8 @@ public class MemberSignServiceImpl extends ServiceImpl storeCollection(PageVO pageVo) { - QueryWrapper queryWrapper = new QueryWrapper(); + QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("sc.member_id", UserContext.getCurrentUser().getId()); queryWrapper.orderByDesc("sc.create_time"); return this.baseMapper.storeCollectionVOList(PageUtil.initPage(pageVo), queryWrapper); @@ -44,10 +44,10 @@ public class StoreCollectionServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper(); + QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("member_id", UserContext.getCurrentUser().getId()); queryWrapper.eq("store_id", storeId); - return Optional.ofNullable(this.getOne(queryWrapper)).isPresent(); + return Optional.ofNullable(this.getOne(queryWrapper, false)).isPresent(); } @Override @@ -67,7 +67,7 @@ public class StoreCollectionServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper(); + QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("member_id", UserContext.getCurrentUser().getId()); queryWrapper.eq("store_id", storeId); storeService.updateStoreCollectionNum(new CollectionDTO(storeId, -1)); diff --git a/framework/src/main/java/cn/lili/modules/message/entity/enums/NoticeMessageParameterEnum.java b/framework/src/main/java/cn/lili/modules/message/entity/enums/NoticeMessageParameterEnum.java index 97f2a085..1e28ee15 100644 --- a/framework/src/main/java/cn/lili/modules/message/entity/enums/NoticeMessageParameterEnum.java +++ b/framework/src/main/java/cn/lili/modules/message/entity/enums/NoticeMessageParameterEnum.java @@ -37,7 +37,7 @@ public enum NoticeMessageParameterEnum { */ CANCEL_REASON("cancel_reason", "取消原因"), /** - * 取消原因 + * 金额 */ PRICE("price", "金额"); diff --git a/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java index fa73ff32..768a6e94 100644 --- a/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java @@ -126,8 +126,9 @@ public class AfterSaleServiceImpl extends ServiceImpl(); + this.cantUseCoupons = new ArrayList<>(); + } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java b/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java index 59f2e7ea..1dcffeeb 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java @@ -6,6 +6,7 @@ import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; import cn.lili.modules.promotion.tools.PromotionTools; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import java.io.Serializable; @@ -19,6 +20,7 @@ import java.util.Map; */ @Data @NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class CartSkuVO extends CartBase implements Serializable { @@ -117,4 +119,8 @@ public class CartSkuVO extends CartBase implements Serializable { public Map getPromotionMap() { return PromotionTools.filterInvalidPromotionsMap(this.promotionMap); } + + public Map getNotFilterPromotionMap() { + return this.promotionMap; + } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java index 58ca809d..c85cfbbd 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java @@ -1,5 +1,6 @@ package cn.lili.modules.order.cart.render.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; @@ -7,10 +8,14 @@ import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.context.UserContext; +import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.goods.entity.dos.GoodsSku; +import cn.lili.modules.goods.entity.dos.Wholesale; 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.service.GoodsSkuService; +import cn.lili.modules.goods.service.WholesaleService; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.TradeDTO; @@ -26,6 +31,7 @@ import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.entity.dos.Pintuan; import cn.lili.modules.promotion.entity.dos.PointsGoods; import cn.lili.modules.promotion.entity.vos.CouponVO; +import cn.lili.modules.promotion.service.PromotionGoodsService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -55,6 +61,14 @@ public class CheckDataRender implements CartRenderStep { @Autowired private MemberService memberService; + @Autowired + private WholesaleService wholesaleService; + + /** + * 商品索引 + */ + @Autowired + private PromotionGoodsService promotionGoodsService; @Override public RenderStepEnums step() { @@ -69,6 +83,7 @@ public class CheckDataRender implements CartRenderStep { //校验商品有效性 checkData(tradeDTO); + preSaleModel(tradeDTO); //店铺分组数据初始化 groupStore(tradeDTO); @@ -92,7 +107,7 @@ public class CheckDataRender implements CartRenderStep { //缓存中的商品信息 GoodsSku dataSku = goodsSkuService.getGoodsSkuByIdFromCache(cartSkuVO.getGoodsSku().getId()); //商品有效性判定 - if (dataSku == null || dataSku.getUpdateTime().before(cartSkuVO.getGoodsSku().getUpdateTime())) { + if (dataSku == null || dataSku.getCreateTime().after(cartSkuVO.getGoodsSku().getCreateTime())) { //设置购物车未选中 cartSkuVO.setChecked(false); //设置购物车此sku商品已失效 @@ -118,6 +133,17 @@ public class CheckDataRender implements CartRenderStep { //设置失效消息 cartSkuVO.setErrorMessage("商品库存不足,现有库存数量[" + dataSku.getQuantity() + "]"); } + //如果存在商品促销活动,则判定商品促销状态 + if (!cartSkuVO.getCartType().equals(CartTypeEnum.POINTS) && (CollUtil.isNotEmpty(cartSkuVO.getNotFilterPromotionMap()) || Boolean.TRUE.equals(cartSkuVO.getGoodsSku().getPromotionFlag()))) { + //获取当前最新的促销信息 + cartSkuVO.setPromotionMap(this.promotionGoodsService.getCurrentGoodsPromotion(cartSkuVO.getGoodsSku(), tradeDTO.getCartTypeEnum().name())); + //设定商品价格 + Double goodsPrice = cartSkuVO.getGoodsSku().getPromotionFlag() != null && cartSkuVO.getGoodsSku().getPromotionFlag() ? cartSkuVO.getGoodsSku().getPromotionPrice() : cartSkuVO.getGoodsSku().getPrice(); + cartSkuVO.setPurchasePrice(goodsPrice); + cartSkuVO.setUtilPrice(goodsPrice); + cartSkuVO.setSubTotal(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); + } + } } @@ -142,10 +168,12 @@ public class CheckDataRender implements CartRenderStep { try { //筛选属于当前店铺的优惠券 storeCart.getValue().forEach(i -> i.getPromotionMap().forEach((key, value) -> { - JSONObject promotionsObj = JSONUtil.parseObj(value); - Coupon coupon = JSONUtil.toBean(promotionsObj, Coupon.class); - if (key.contains(PromotionTypeEnum.COUPON.name()) && coupon.getStoreId().equals(storeCart.getKey())) { - cartVO.getCanReceiveCoupon().add(new CouponVO(coupon)); + if (key.contains(PromotionTypeEnum.COUPON.name())) { + JSONObject promotionsObj = JSONUtil.parseObj(value); + Coupon coupon = JSONUtil.toBean(promotionsObj, Coupon.class); + if (key.contains(PromotionTypeEnum.COUPON.name()) && coupon.getStoreId().equals(storeCart.getKey())) { + cartVO.getCanReceiveCoupon().add(new CouponVO(coupon)); + } } })); } catch (Exception e) { @@ -212,4 +240,41 @@ public class CheckDataRender implements CartRenderStep { } + + /** + * 商品销售模式特殊处理 + * + * @param tradeDTO 交易信息 + */ + private void preSaleModel(TradeDTO tradeDTO) { + // 寻找同goods下销售模式为批发的商品 + Map> goodsGroup = tradeDTO.getSkuList().stream().filter(i -> i.getGoodsSku().getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())).collect(Collectors.groupingBy(i -> i.getGoodsSku().getGoodsId())); + if (CollUtil.isNotEmpty(goodsGroup)) { + goodsGroup.forEach((k, v) -> { + // 获取购买总数 + int sum = v.stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).mapToInt(CartSkuVO::getNum).sum(); + int fSum = v.stream().filter(i -> Boolean.FALSE.equals(i.getChecked())).mapToInt(CartSkuVO::getNum).sum(); + // 匹配符合的批发规则 + Wholesale match = wholesaleService.match(k, sum); + if (match != null) { + v.forEach(i -> { + // 将符合规则的商品设置批发价格 + if (Boolean.TRUE.equals(i.getChecked())) { + i.setPurchasePrice(match.getPrice()); + i.getGoodsSku().setPrice(match.getPrice()); + i.getGoodsSku().setCost(match.getPrice()); + i.setUtilPrice(match.getPrice()); + i.setSubTotal(CurrencyUtil.mul(i.getPurchasePrice(), i.getNum())); + } else { + i.setPurchasePrice(wholesaleService.match(k, fSum).getPrice()); + i.getGoodsSku().setPrice(i.getPurchasePrice()); + i.getGoodsSku().setCost(i.getPurchasePrice()); + i.setUtilPrice(i.getPurchasePrice()); + i.setSubTotal(CurrencyUtil.mul(i.getPurchasePrice(), i.getNum())); + } + }); + } + }); + } + } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java index f7e7bf55..8d35dbaf 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java @@ -4,6 +4,7 @@ import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.lili.common.enums.PromotionTypeEnum; +import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.goods.service.CategoryService; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; @@ -85,7 +86,7 @@ public class CommissionRender implements CartRenderStep { if (kanjiaPromotions.isPresent()) { JSONObject promotionsObj = JSONUtil.parseObj(kanjiaPromotions.get().getValue()); KanjiaActivityGoods kanjiaActivityGoods = JSONUtil.toBean(promotionsObj, KanjiaActivityGoods.class); - priceDetailDTO.setSettlementPrice(kanjiaActivityGoods.getSettlementPrice()); + priceDetailDTO.setSettlementPrice(CurrencyUtil.add(kanjiaActivityGoods.getSettlementPrice(),priceDetailDTO.getBillPrice())); } } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java index f06633e7..549dbd04 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java @@ -19,10 +19,7 @@ import cn.lili.modules.promotion.service.MemberCouponService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -60,8 +57,16 @@ public class CouponRender implements CartRenderStep { * @param tradeDTO 交易dto */ private void renderCouponRule(TradeDTO tradeDTO) { + // 清除之前的优惠券 + tradeDTO.removeCoupon(); + List memberCouponList = memberCouponService.getMemberCoupons(tradeDTO.getMemberId()); + //获取最新优惠券 + memberCouponList = memberCouponList.stream() + .filter(item -> item.getStartTime().before(new Date()) && item.getEndTime().after(new Date())) + .collect(Collectors.toList()); + if (!memberCouponList.isEmpty()) { this.checkMemberExistCoupon(tradeDTO, memberCouponList); } else { diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java index d0b0e672..799c62b8 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java @@ -15,7 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * sku 运费计算 @@ -43,31 +46,35 @@ public class SkuFreightRender implements CartRenderStep { if (memberAddress == null) { return; } - //循环渲染购物车商品运费价格 - forSku: - for (CartSkuVO cartSkuVO : cartSkuVOS) { - //获取sku运费模版 - String freightTemplateId = cartSkuVO.getGoodsSku().getFreightTemplateId(); - //免运费则跳出运费计算 - if (Boolean.TRUE.equals(cartSkuVO.getIsFreeFreight()) || freightTemplateId == null) { - continue; - } + //运费分组信息 + Map> freightGroups = freightTemplateGrouping(cartSkuVOS); + + //循环运费模版 + for (Map.Entry> freightTemplateGroup : freightGroups.entrySet()) { + + //商品id列表 + List skuIds = freightTemplateGroup.getValue(); + + //当前购物车商品列表 + List currentCartSkus = cartSkuVOS.stream().filter(item -> skuIds.contains(item.getGoodsSku().getId())).collect(Collectors.toList()); + //寻找对应对商品运费计算模版 - FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateId); + FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateGroup.getKey()); if (freightTemplate != null && freightTemplate.getFreightTemplateChildList() != null && !freightTemplate.getFreightTemplateChildList().isEmpty()) { - //店铺支付运费则跳过 + //店铺模版免运费则跳过 if (freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())) { break; } + + //运费模版 FreightTemplateChild freightTemplateChild = null; - //获取市级别id + //获取市级别id匹配运费模版 String addressId = memberAddress.getConsigneeAddressIdPath().split(",")[1]; - //获取匹配的收货地址 for (FreightTemplateChild templateChild : freightTemplate.getFreightTemplateChildList()) { - //如果当前模版包含,则返回 + //模版匹配判定 if (templateChild.getAreaId().contains(addressId)) { freightTemplateChild = templateChild; break; @@ -78,28 +85,97 @@ public class SkuFreightRender implements CartRenderStep { if (tradeDTO.getNotSupportFreight() == null) { tradeDTO.setNotSupportFreight(new ArrayList<>()); } - tradeDTO.getNotSupportFreight().add(cartSkuVO); - continue forSku; + tradeDTO.getNotSupportFreight().addAll(currentCartSkus); + continue; } //物流规则模型创立 FreightTemplateChildDTO freightTemplateChildDTO = new FreightTemplateChildDTO(freightTemplateChild); - + //模型写入运费模版设置的计费方式 freightTemplateChildDTO.setPricingMethod(freightTemplate.getPricingMethod()); - //要计算的基数 数量/重量 - Double count = (freightTemplateChildDTO.getPricingMethod().equals(FreightTemplateEnum.NUM.name())) ? - cartSkuVO.getNum() : - cartSkuVO.getGoodsSku().getWeight() * cartSkuVO.getNum(); + //计算运费总数 + Double count = currentCartSkus.stream().mapToDouble(item -> + // 根据计费规则 累加计费基数 + freightTemplateChildDTO.getPricingMethod().equals(FreightTemplateEnum.NUM.name()) ? + item.getNum().doubleValue() : + CurrencyUtil.mul(item.getNum(), item.getGoodsSku().getWeight()) + ).sum(); //计算运费 Double countFreight = countFreight(count, freightTemplateChildDTO); + //写入SKU运费 - cartSkuVO.getPriceDetailDTO().setFreightPrice(countFreight); + resetFreightPrice(FreightTemplateEnum.valueOf(freightTemplateChildDTO.getPricingMethod()), count, countFreight, currentCartSkus); } } } + + /** + * sku运费写入 + * + * @param freightTemplateEnum 运费计算模式 + * @param count 计费基数总数 + * @param countFreight 总运费 + * @param cartSkuVOS 与运费相关的购物车商品 + */ + private void resetFreightPrice(FreightTemplateEnum freightTemplateEnum, Double count, Double countFreight, List cartSkuVOS) { + + //剩余运费 默认等于总运费 + Double surplusFreightPrice = countFreight; + + //当前下标 + int index = 1; + for (CartSkuVO cartSkuVO : cartSkuVOS) { + //如果是最后一个 则将剩余运费直接赋值 + //PS: 循环中避免百分比累加不等于100%,所以最后一个运费不以比例计算,直接将剩余运费赋值 + if (index == cartSkuVOS.size()) { + cartSkuVO.getPriceDetailDTO().setFreightPrice(surplusFreightPrice); + break; + } + + Double freightPrice = freightTemplateEnum == FreightTemplateEnum.NUM ? + CurrencyUtil.mul(countFreight, CurrencyUtil.div(cartSkuVO.getNum(), count)) : + CurrencyUtil.mul(countFreight, + CurrencyUtil.div(CurrencyUtil.mul(cartSkuVO.getNum(), cartSkuVO.getGoodsSku().getWeight()), count)); + + //剩余运费=总运费-当前循环的商品运费 + surplusFreightPrice = CurrencyUtil.sub(surplusFreightPrice, freightPrice); + + cartSkuVO.getPriceDetailDTO().setFreightPrice(freightPrice); + index++; + } + } + + /** + * 运费模版分组 + * + * @param cartSkuVOS 购物车商品 + * @return map<运费模版id , List < skuid>> + */ + private Map> freightTemplateGrouping(List cartSkuVOS) { + Map> map = new HashMap<>(); + //循环渲染购物车商品运费价格 + for (CartSkuVO cartSkuVO : cartSkuVOS) { + ////免运费判定 + String freightTemplateId = cartSkuVO.getGoodsSku().getFreightTemplateId(); + if (Boolean.TRUE.equals(cartSkuVO.getIsFreeFreight()) || freightTemplateId == null) { + continue; + } + //包含 则value值中写入sku标识,否则直接写入新的对象,key为模版id,value为new arraylist + if (map.containsKey(freightTemplateId)) { + map.get(freightTemplateId).add(cartSkuVO.getGoodsSku().getId()); + } else { + List skuIdsList = new ArrayList<>(); + skuIdsList.add(cartSkuVO.getGoodsSku().getId()); + map.put(freightTemplateId, skuIdsList); + } + } + return map; + } + + /** * 计算运费 * diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java index 82f3cde9..280082ed 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java @@ -74,7 +74,7 @@ public class SkuPromotionRender implements CartRenderStep { renderBasePrice(tradeDTO); //渲染单品促销 renderSkuPromotion(tradeDTO); - + //检查促销库存 checkPromotionQuantity(tradeDTO); @@ -186,7 +186,6 @@ public class SkuPromotionRender implements CartRenderStep { */ private void checkPromotionQuantity(TradeDTO tradeDTO) { for (CartSkuVO cartSkuVO : tradeDTO.getCheckedSkuList()) { - cartSkuVO.getPromotionMap(); List joinPromotion = cartSkuVO.getPriceDetailDTO().getJoinPromotion(); if (!joinPromotion.isEmpty()) { for (PromotionSkuVO promotionSkuVO : joinPromotion) { diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java index 01b3866d..d11d8aa8 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java @@ -95,13 +95,6 @@ public interface CartService { */ void clean(); - /** - * 清空购物车无效数据 - * - * @param way 购物车类型 - */ - void cleanChecked(CartTypeEnum way); - /** * 重新写入 * diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java index 1e8367ce..3fafa5be 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java @@ -1,5 +1,6 @@ package cn.lili.modules.order.cart.service; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; @@ -11,11 +12,12 @@ import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.goods.entity.dos.GoodsSku; +import cn.lili.modules.goods.entity.dos.Wholesale; 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.GoodsVO; -import cn.lili.modules.goods.service.GoodsService; import cn.lili.modules.goods.service.GoodsSkuService; +import cn.lili.modules.goods.service.WholesaleService; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.service.MemberAddressService; @@ -32,10 +34,8 @@ import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.vo.ReceiptVO; import cn.lili.modules.promotion.entity.dos.KanjiaActivity; import cn.lili.modules.promotion.entity.dos.MemberCoupon; -import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.dto.search.KanjiaActivitySearchParams; import cn.lili.modules.promotion.entity.dto.search.MemberCouponSearchParams; -import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams; import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum; import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum; import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum; @@ -45,7 +45,6 @@ import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.modules.promotion.service.PointsGoodsService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; -import cn.lili.modules.search.service.EsGoodsIndexService; import cn.lili.modules.search.service.EsGoodsSearchService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -97,16 +96,6 @@ public class CartServiceImpl implements CartService { */ @Autowired private EsGoodsSearchService esGoodsSearchService; - /** - * 商品索引 - */ - @Autowired - private EsGoodsIndexService goodsIndexService; - /** - * ES商品 - */ - @Autowired - private GoodsService goodsService; /** * 砍价 */ @@ -124,6 +113,9 @@ public class CartServiceImpl implements CartService { @Autowired private PromotionGoodsService promotionGoodsService; + @Autowired + private WholesaleService wholesaleService; + @Override public void add(String skuId, Integer num, String cartType, Boolean cover) { AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); @@ -132,7 +124,7 @@ public class CartServiceImpl implements CartService { } CartTypeEnum cartTypeEnum = getCartType(cartType); GoodsSku dataSku = checkGoods(skuId); - Map promotionMap = this.getCurrentGoodsPromotion(dataSku, cartType); + Map promotionMap = promotionGoodsService.getCurrentGoodsPromotion(dataSku, cartTypeEnum.name()); try { //购物车方式购买需要保存之前的选择,其他方式购买,则直接抹除掉之前的记录 @@ -146,7 +138,7 @@ public class CartServiceImpl implements CartService { //购物车中已经存在,更新数量 - if (cartSkuVO != null && dataSku.getUpdateTime().equals(cartSkuVO.getGoodsSku().getUpdateTime())) { + if (cartSkuVO != null && dataSku.getCreateTime().equals(cartSkuVO.getGoodsSku().getCreateTime())) { //如果覆盖购物车中商品数量 if (Boolean.TRUE.equals(cover)) { @@ -157,7 +149,7 @@ public class CartServiceImpl implements CartService { int newNum = oldNum + num; this.checkSetGoodsQuantity(cartSkuVO, skuId, newNum); } - + cartSkuVO.setPromotionMap(promotionMap); //计算购物车小计 cartSkuVO.setSubTotal(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); } else { @@ -185,7 +177,6 @@ public class CartServiceImpl implements CartService { //购物车中不存在此商品,则新建立一个 CartSkuVO cartSkuVO = new CartSkuVO(dataSku, promotionMap); - this.checkSetGoodsQuantity(cartSkuVO, skuId, num); cartSkuVO.setCartType(cartTypeEnum); //检测购物车数据 checkCart(cartTypeEnum, cartSkuVO, skuId, num); @@ -194,10 +185,11 @@ public class CartServiceImpl implements CartService { cartSkuVOS.add(cartSkuVO); } + this.checkGoodsSaleModel(dataSku, tradeDTO.getSkuList()); tradeDTO.setCartTypeEnum(cartTypeEnum); - //如购物车发生更改,则重置优惠券 - tradeDTO.setStoreCoupons(null); - tradeDTO.setPlatformCoupon(null); + + remoteCoupon(tradeDTO); + this.resetTradeDTO(tradeDTO); } catch (ServiceException serviceException) { throw serviceException; @@ -241,39 +233,59 @@ public class CartServiceImpl implements CartService { @Override public void checked(String skuId, boolean checked) { TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART); + + remoteCoupon(tradeDTO); + List cartSkuVOS = tradeDTO.getSkuList(); for (CartSkuVO cartSkuVO : cartSkuVOS) { if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { cartSkuVO.setChecked(checked); } } - cache.put(this.getOriginKey(CartTypeEnum.CART), tradeDTO); + + this.resetTradeDTO(tradeDTO); } @Override public void checkedStore(String storeId, boolean checked) { TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART); + + remoteCoupon(tradeDTO); + List cartSkuVOS = tradeDTO.getSkuList(); for (CartSkuVO cartSkuVO : cartSkuVOS) { if (cartSkuVO.getStoreId().equals(storeId)) { cartSkuVO.setChecked(checked); } } - cache.put(this.getOriginKey(CartTypeEnum.CART), tradeDTO); + + resetTradeDTO(tradeDTO); } @Override public void checkedAll(boolean checked) { TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART); + + remoteCoupon(tradeDTO); + List cartSkuVOS = tradeDTO.getSkuList(); for (CartSkuVO cartSkuVO : cartSkuVOS) { cartSkuVO.setChecked(checked); } - cache.put(this.getOriginKey(CartTypeEnum.CART), tradeDTO); + resetTradeDTO(tradeDTO); + } + + /** + * 当购物车商品发生变更时,取消已选择当优惠券 + * + * @param tradeDTO + */ + private void remoteCoupon(TradeDTO tradeDTO) { + tradeDTO.setPlatformCoupon(null); + tradeDTO.setStoreCoupons(new HashMap<>()); } @Override - @Transactional(rollbackFor = Exception.class) public void delete(String[] skuIds) { TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART); List cartSkuVOS = tradeDTO.getSkuList(); @@ -286,7 +298,7 @@ public class CartServiceImpl implements CartService { } } cartSkuVOS.removeAll(deleteVos); - cache.put(this.getOriginKey(CartTypeEnum.CART), tradeDTO); + resetTradeDTO(tradeDTO); } @Override @@ -308,17 +320,8 @@ public class CartServiceImpl implements CartService { tradeDTO.setStoreCoupons(null); //清除添加过的备注 tradeDTO.setStoreRemark(null); - cache.put(this.getOriginKey(tradeDTO.getCartTypeEnum()), tradeDTO); - } - @Override - public void cleanChecked(CartTypeEnum way) { - if (way.equals(CartTypeEnum.CART)) { - TradeDTO tradeDTO = this.readDTO(CartTypeEnum.CART); - this.cleanChecked(tradeDTO); - } else { - cache.remove(this.getOriginKey(way)); - } + resetTradeDTO(tradeDTO); } @Override @@ -415,7 +418,7 @@ public class CartServiceImpl implements CartService { cartSkuVO.setNum(num); } - if (cartSkuVO.getNum() > 99) { + if (cartSkuVO.getGoodsSku() != null && !GoodsSalesModeEnum.WHOLESALE.name().equals(cartSkuVO.getGoodsSku().getSalesModel()) && cartSkuVO.getNum() > 99) { cartSkuVO.setNum(99); } } @@ -504,6 +507,12 @@ public class CartServiceImpl implements CartService { AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); //获取购物车,然后重新写入优惠券 CartTypeEnum cartTypeEnum = getCartType(way); + + //积分商品不允许使用优惠券 + if (cartTypeEnum.equals(CartTypeEnum.POINTS)) { + throw new ServiceException(ResultCode.SPECIAL_CANT_USE); + } + TradeDTO tradeDTO = this.readDTO(cartTypeEnum); MemberCouponSearchParams searchParams = new MemberCouponSearchParams(); @@ -543,46 +552,10 @@ public class CartServiceImpl implements CartService { } //构建交易 Trade trade = tradeBuilder.createTrade(tradeDTO); - this.cleanChecked(tradeDTO); + this.cleanChecked(this.readDTO(cartTypeEnum)); return trade; } - private Map getCurrentGoodsPromotion(GoodsSku dataSku, String cartType) { - Map promotionMap; - EsGoodsIndex goodsIndex = goodsIndexService.findById(dataSku.getId()); - if (goodsIndex == null) { - GoodsVO goodsVO = this.goodsService.getGoodsVO(dataSku.getGoodsId()); - goodsIndex = goodsIndexService.getResetEsGoodsIndex(dataSku, goodsVO.getGoodsParamsDTOList()); - } - if (goodsIndex.getPromotionMap() != null && !goodsIndex.getPromotionMap().isEmpty()) { - if (goodsIndex.getPromotionMap().keySet().stream().anyMatch(i -> i.contains(PromotionTypeEnum.SECKILL.name())) || - (goodsIndex.getPromotionMap().keySet().stream().anyMatch(i -> i.contains(PromotionTypeEnum.PINTUAN.name())) - && CartTypeEnum.PINTUAN.name().equals(cartType))) { - - Optional> containsPromotion = goodsIndex.getPromotionMap().entrySet().stream().filter(i -> - i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); - if (containsPromotion.isPresent()) { - JSONObject promotionsObj = JSONUtil.parseObj(containsPromotion.get().getValue()); - PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams(); - searchParams.setSkuId(dataSku.getId()); - searchParams.setPromotionId(promotionsObj.get("id").toString()); - PromotionGoods promotionsGoods = promotionGoodsService.getPromotionsGoods(searchParams); - if (promotionsGoods != null && promotionsGoods.getPrice() != null) { - dataSku.setPromotionFlag(true); - dataSku.setPromotionPrice(promotionsGoods.getPrice()); - } else { - dataSku.setPromotionFlag(false); - dataSku.setPromotionPrice(null); - } - } - } - promotionMap = goodsIndex.getPromotionMap(); - } else { - promotionMap = null; - } - return promotionMap; - } - /** * 获取购物车类型 @@ -636,6 +609,9 @@ public class CartServiceImpl implements CartService { cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum())); skuPrice.put(cartSkuVO.getGoodsSku().getId(), CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum())); } + } else { + cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum())); + skuPrice.put(cartSkuVO.getGoodsSku().getId(), CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum())); } } @@ -710,6 +686,24 @@ public class CartServiceImpl implements CartService { } } + + private void checkGoodsSaleModel(GoodsSku dataSku, List cartSkuVOS) { + if (dataSku.getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())) { + int numSum = 0; + List sameGoodsIdSkuList = cartSkuVOS.stream().filter(i -> i.getGoodsSku().getGoodsId().equals(dataSku.getGoodsId())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(sameGoodsIdSkuList)) { + numSum += sameGoodsIdSkuList.stream().mapToInt(CartSkuVO::getNum).sum(); + } + Wholesale match = wholesaleService.match(dataSku.getGoodsId(), numSum); + if (match != null) { + sameGoodsIdSkuList.forEach(i -> { + i.setPurchasePrice(match.getPrice()); + i.setSubTotal(CurrencyUtil.mul(i.getPurchasePrice(), i.getNum())); + }); + } + } + } + /** * 校验拼团信息 * diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java index 865a70a9..28920de7 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java @@ -12,6 +12,7 @@ import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.order.entity.dto.PriceDetailDTO; import cn.lili.modules.order.order.entity.enums.*; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.mybatis.BaseEntity; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; @@ -78,6 +79,9 @@ public class Order extends BaseEntity { @ApiModelProperty(value = "第三方付款流水号") private String receivableNo; + /** + * @see PaymentMethodEnum + */ @ApiModelProperty(value = "支付方式") private String paymentMethod; @@ -181,7 +185,7 @@ public class Order extends BaseEntity { @ApiModelProperty(value = "订单促销类型") private String orderPromotionType; - @ApiModelProperty(value = "价格详情") + @ApiModelProperty(value = "价格价格详情") private String priceDetail; @ApiModelProperty(value = "订单是否支持原路退回") diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/StoreFlow.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/StoreFlow.java index 20ee09c9..8404acc9 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/StoreFlow.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/StoreFlow.java @@ -1,6 +1,14 @@ package cn.lili.modules.order.order.entity.dos; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONUtil; +import cn.lili.common.utils.BeanUtil; +import cn.lili.common.utils.CurrencyUtil; +import cn.lili.common.utils.SnowFlake; +import cn.lili.modules.order.order.entity.dto.PriceDetailDTO; import cn.lili.modules.order.order.entity.enums.FlowTypeEnum; +import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.mybatis.BaseIdEntity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; @@ -9,6 +17,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; import org.springframework.format.annotation.DateTimeFormat; @@ -23,6 +33,8 @@ import java.util.Date; @Data @TableName("li_store_flow") @ApiModel(value = "商家订单流水") +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class StoreFlow extends BaseIdEntity { private static final long serialVersionUID = -5998757398902747939L; @@ -92,10 +104,10 @@ public class StoreFlow extends BaseIdEntity { @ApiModelProperty(value = "平台优惠券 使用金额") private Double siteCouponPrice; - @ApiModelProperty(value = "站点优惠券佣金比例") + @ApiModelProperty(value = "站点优惠券补贴比例") private Double siteCouponPoint; - @ApiModelProperty(value = "站点优惠券佣金") + @ApiModelProperty(value = "站点优惠券补贴金额") private Double siteCouponCommission; @ApiModelProperty(value = "单品分销返现支出") @@ -113,6 +125,9 @@ public class StoreFlow extends BaseIdEntity { @ApiModelProperty(value = "第三方交易流水号") private String transactionId; + /** + * @see PaymentMethodEnum + */ @ApiModelProperty(value = "支付方式名称") private String paymentName; @@ -125,4 +140,62 @@ public class StoreFlow extends BaseIdEntity { @TableField(fill = FieldFill.INSERT) @ApiModelProperty(value = "创建时间", hidden = true) private Date createTime; + + + public StoreFlow(Order order, OrderItem item, FlowTypeEnum flowTypeEnum) { + //获取订单促销类型,如果为促销订单则获取促销商品并获取结算价 + String promotionType = order.getOrderPromotionType(); + BeanUtil.copyProperties(item, this); + + //去掉orderitem的时间。 + this.setCreateTime(null); + //入账 + this.setId(SnowFlake.getIdStr()); + this.setFlowType(flowTypeEnum.name()); + this.setSn(SnowFlake.createStr("SF")); + this.setOrderSn(item.getOrderSn()); + this.setOrderItemSn(item.getSn()); + this.setStoreId(order.getStoreId()); + this.setStoreName(order.getStoreName()); + this.setMemberId(order.getMemberId()); + this.setMemberName(order.getMemberName()); + this.setGoodsName(item.getGoodsName()); + this.setOrderPromotionType(item.getPromotionType()); + //格式化订单价格详情 + PriceDetailDTO priceDetailDTO = JSONUtil.toBean(item.getPriceDetail(), PriceDetailDTO.class); + //站点优惠券比例=最大比例(100)-店铺承担比例 + this.setSiteCouponPoint(CurrencyUtil.sub(100, priceDetailDTO.getSiteCouponPoint())); + //平台优惠券 使用金额 + this.setSiteCouponPrice(priceDetailDTO.getSiteCouponPrice()); + //站点优惠券佣金(站点优惠券承担金额=优惠券金额 * (站点承担比例/100)) + this.setSiteCouponCommission(CurrencyUtil.mul(this.getSiteCouponPrice(), CurrencyUtil.div(this.getSiteCouponPoint(), 100))); + + /** + * @TODO 计算平台佣金 + */ + //店铺流水金额=goodsPrice(商品总金额(商品原价))+ freightPrice(配送费) - discountPrice(优惠金额) - couponPrice(优惠券金额) + updatePrice(订单修改金额) + this.setFinalPrice(item.getPriceDetailDTO().getFlowPrice()); + //平台收取交易佣金=(flowPrice(流水金额) * platFormCommissionPoint(平台佣金比例))/100 + this.setCommissionPrice(item.getPriceDetailDTO().getPlatFormCommission()); + //单品分销返现支出 + this.setDistributionRebate(item.getPriceDetailDTO().getDistributionCommission()); + //最终结算金额=flowPrice(流水金额) - platFormCommission(平台收取交易佣金) - distributionCommission(单品分销返现支出) + this.setBillPrice(item.getPriceDetailDTO().getBillPrice()); + //兼容为空,以及普通订单操作 + if (CharSequenceUtil.isNotEmpty(promotionType)) { + //如果为砍价活动,填写砍价结算价 + if (promotionType.equals(OrderPromotionTypeEnum.KANJIA.name())) { + this.setKanjiaSettlementPrice(item.getPriceDetailDTO().getSettlementPrice()); + } + //如果为砍价活动,填写砍价结算价 + else if (promotionType.equals(OrderPromotionTypeEnum.POINTS.name())) { + this.setPointSettlementPrice(item.getPriceDetailDTO().getSettlementPrice()); + } + } + //添加支付方式 + this.setPaymentName(order.getPaymentMethod()); + //添加第三方支付流水号 + this.setTransactionId(order.getReceivableNo()); + + } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Trade.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Trade.java index 9edc785a..ed63df9b 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Trade.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Trade.java @@ -35,6 +35,9 @@ public class Trade extends BaseEntity { @ApiModelProperty(value = "买家用户名") private String memberName; + /** + * @see PayStatusEnum + */ @ApiModelProperty(value = "支付方式") private String paymentMethod; diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java index d9b25dab..0bae3935 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java @@ -121,7 +121,7 @@ public class OrderSearchParams extends PageVO { //关键字查询 if (CharSequenceUtil.isNotEmpty(keywords)) { - wrapper.like("o.sn", keywords).or().like("oi.goods_name", keywords); + wrapper.and(keyWrapper -> keyWrapper.like("o.sn", keywords).or().like("oi.goods_name", keywords)); } if (currentUser != null) { //按卖家查询 diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java index 67872901..edf3cfc9 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java @@ -57,7 +57,8 @@ public class PriceDetailDTO implements Serializable { @ApiModelProperty(value = "平台收取交易佣金比例") private Double platFormCommissionPoint; - @ApiModelProperty(value = "平台收取交易佣金") + + @ApiModelProperty(value = "平台收取交易佣金=(flowPrice(流水金额) * platFormCommissionPoint(平台佣金比例))/100") private Double platFormCommission; //=========end distribution========== @@ -82,13 +83,15 @@ public class PriceDetailDTO implements Serializable { //=========end update price========== - @ApiModelProperty(value = "流水金额(入账 出帐金额) = goodsPrice + freight - discountPrice - couponPrice + updatePrice") + @ApiModelProperty(value = "流水金额(入账 出帐金额) = " + + "goodsPrice(商品总金额(商品原价)) + freightPrice(配送费) - " + + "discountPrice(优惠金额) - couponPrice(优惠券金额) + updatePrice(订单修改金额)") private Double flowPrice; @ApiModelProperty(value = "结算价格 与 商家/供应商 结算价格(例如积分商品/砍价商品)") private Double settlementPrice; - @ApiModelProperty(value = "最终结算金额 = flowPrice - platFormCommission - distributionCommission") + @ApiModelProperty(value = "最终结算金额 = flowPrice(流水金额) - platFormCommission(平台收取交易佣金) - distributionCommission(单品分销返现支出)") private Double billPrice; /** diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderItemVO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderItemVO.java index 6d091159..5ab18dcf 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderItemVO.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderItemVO.java @@ -5,6 +5,7 @@ import cn.lili.modules.order.order.entity.enums.OrderComplaintStatusEnum; import cn.lili.modules.order.order.entity.enums.OrderItemAfterSaleStatusEnum; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.NoArgsConstructor; /** * 子订单VO @@ -13,6 +14,7 @@ import lombok.Data; * @since 2020-08-17 20:28 */ @Data +@NoArgsConstructor public class OrderItemVO { @ApiModelProperty(value = "编号") @@ -55,17 +57,39 @@ public class OrderItemVO { private String commentStatus; - public OrderItemVO(String sn, String goodsId, String skuId, String num, String image, String name, String afterSaleStatus, String complainStatus, String commentStatus, Double goodsPrice) { + public void setSn(String sn) { this.sn = sn; - this.goodsId = goodsId; + } + + public void setSkuId(String skuId) { this.skuId = skuId; + } + + public void setNum(String num) { this.num = num; + } + + public void setImage(String image) { this.image = image; + } + + public void setName(String name) { this.name = name; - this.afterSaleStatus = afterSaleStatus; - this.complainStatus = complainStatus; - this.commentStatus = commentStatus; + } + + public void setGoodsPrice(Double goodsPrice) { this.goodsPrice = goodsPrice; } + public void setAfterSaleStatus(String afterSaleStatus) { + this.afterSaleStatus = afterSaleStatus; + } + + public void setComplainStatus(String complainStatus) { + this.complainStatus = complainStatus; + } + + public void setCommentStatus(String commentStatus) { + this.commentStatus = commentStatus; + } } diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java index f44efa3d..711ffd92 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java @@ -1,8 +1,7 @@ package cn.lili.modules.order.order.entity.vo; +import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.enums.ClientTypeEnum; -import cn.lili.common.utils.StringUtils; -import cn.lili.modules.order.order.entity.enums.*; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -135,28 +134,54 @@ public class OrderSimpleVO { private String deliverStatus; public List getOrderItems() { - if (StringUtils.isEmpty(groupGoodsId)) { + if (CharSequenceUtil.isEmpty(groupGoodsId)) { return new ArrayList<>(); } List orderItemVOS = new ArrayList<>(); - String[] orderItemsSn = groupOrderItemsSn.split(","); + + String[] goodsId = groupGoodsId.split(","); - String[] skuId = groupSkuId.split(","); - String[] num = groupNum.split(","); - String[] image = groupImages.split(","); - String[] name = groupName.split(","); - String[] afterSaleStatus = groupAfterSaleStatus.split(","); - String[] complainStatus = groupComplainStatus.split(","); - String[] commentStatus = groupCommentStatus.split(","); - String[] goodsPrice = groupGoodsPrice.split(","); for (int i = 0; i < goodsId.length; i++) { - orderItemVOS.add(new OrderItemVO(orderItemsSn[i], goodsId[i], skuId[i], num[i], image[i], name[i], afterSaleStatus[i], complainStatus[i], commentStatus[i], Double.parseDouble(goodsPrice[i]))); + orderItemVOS.add(this.getOrderItemVO(i)); } return orderItemVOS; } + private OrderItemVO getOrderItemVO(int i) { + OrderItemVO orderItemVO = new OrderItemVO(); + orderItemVO.setGoodsId(groupGoodsId.split(",")[i]); + if (CharSequenceUtil.isNotEmpty(groupOrderItemsSn)) { + orderItemVO.setSn(groupOrderItemsSn.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupSkuId)) { + orderItemVO.setSkuId(groupSkuId.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupName)) { + orderItemVO.setName(groupName.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupNum) && groupNum.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setNum(groupNum.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupImages) && groupImages.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setImage(groupImages.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupAfterSaleStatus) && groupAfterSaleStatus.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setAfterSaleStatus(groupAfterSaleStatus.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupComplainStatus) && groupComplainStatus.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setComplainStatus(groupComplainStatus.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupCommentStatus) && groupCommentStatus.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setCommentStatus(groupCommentStatus.split(",")[i]); + } + if (CharSequenceUtil.isNotEmpty(groupGoodsPrice) && groupGoodsPrice.split(",").length == groupGoodsId.split(",").length) { + orderItemVO.setGoodsPrice(Double.parseDouble(groupGoodsPrice.split(",")[i])); + } + return orderItemVO; + } + /** * 初始化自身状态 */ diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java index bfa35704..01c61f60 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java @@ -10,16 +10,14 @@ import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.ExcelWriter; 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.fulu.core.utils.Test; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.OperationalJudgment; import cn.lili.common.security.context.UserContext; import cn.lili.common.security.enums.UserEnums; import cn.lili.common.utils.SnowFlake; -import cn.lili.modules.goods.entity.dos.Goods; import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage; -import cn.lili.modules.goods.service.GoodsService; import cn.lili.modules.member.entity.dto.MemberAddressDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.order.aop.OrderLogPoint; @@ -41,9 +39,6 @@ import cn.lili.modules.order.trade.service.OrderLogService; import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.modules.promotion.entity.dos.Pintuan; import cn.lili.modules.promotion.service.PintuanService; -import cn.lili.modules.store.entity.dos.StoreDetail; -import cn.lili.modules.store.entity.dto.FuLuConfigureDTO; -import cn.lili.modules.store.service.StoreDetailService; import cn.lili.modules.system.aspect.annotation.SystemLogPoint; import cn.lili.modules.system.entity.dos.Logistics; import cn.lili.modules.system.entity.vo.Traces; @@ -58,7 +53,6 @@ import cn.lili.trigger.message.PintuanOrderMessage; import cn.lili.trigger.model.TimeExecuteConstant; import cn.lili.trigger.model.TimeTriggerMsg; import cn.lili.trigger.util.DelayQueueTools; -import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -66,9 +60,11 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -88,6 +84,7 @@ import java.util.stream.Collectors; * @since 2020/11/17 7:38 下午 */ @Service +@Slf4j public class OrderServiceImpl extends ServiceImpl implements OrderService { private static final String ORDER_SN_COLUMN = "order_sn"; @@ -146,17 +143,9 @@ public class OrderServiceImpl extends ServiceImpl implements @Autowired private TradeService tradeService; - /** - * 商品 - */ - @Autowired - private GoodsService goodsService; - /** - * 商品 - */ @Autowired - private StoreDetailService storeDetailService; + private ApplicationEventPublisher applicationEventPublisher; @Override @Transactional(rollbackFor = Exception.class) @@ -313,6 +302,8 @@ public class OrderServiceImpl extends ServiceImpl implements order.setCancelReason(reason); //修改订单 this.updateById(order); + //生成店铺退款流水 + this.generatorStoreRefundFlow(order); orderStatusMessage(order); return order; } else { @@ -329,6 +320,8 @@ public class OrderServiceImpl extends ServiceImpl implements order.setOrderStatus(OrderStatusEnum.CANCELLED.name()); order.setCancelReason(reason); this.updateById(order); + //生成店铺退款流水 + this.generatorStoreRefundFlow(order); orderStatusMessage(order); } @@ -350,6 +343,7 @@ public class OrderServiceImpl extends ServiceImpl implements Order order = this.getBySn(orderSn); //如果订单已支付,就不能再次进行支付 if (order.getPayStatus().equals(PayStatusEnum.PAID.name())) { + log.error("订单[ {} ]检测到重复付款,请处理", orderSn); throw new ServiceException(ResultCode.PAY_DOUBLE_ERROR); } @@ -362,7 +356,7 @@ public class OrderServiceImpl extends ServiceImpl implements order.setCanReturn(!PaymentMethodEnum.BANK_TRANSFER.name().equals(order.getPaymentMethod())); this.updateById(order); - //记录订单流水 + //记录店铺订单支付流水 storeFlowService.payOrder(orderSn); //发送订单已付款消息 @@ -458,11 +452,13 @@ public class OrderServiceImpl extends ServiceImpl implements //获取订单信息 Order order = this.getBySn(orderSn); //获取踪迹信息 - return logisticsService.getLogistic(order.getLogisticsCode(), order.getLogisticsNo()); + String str = order.getConsigneeMobile(); + return logisticsService.getLogistic(order.getLogisticsCode(), order.getLogisticsNo(), str.substring(str.length() - 4)); } @Override @OrderLogPoint(description = "'订单['+#orderSn+']核销,核销码['+#verificationCode+']'", orderSn = "#orderSn") + @Transactional(rollbackFor = Exception.class) public Order take(String orderSn, String verificationCode) { //获取订单信息 @@ -507,7 +503,8 @@ public class OrderServiceImpl extends ServiceImpl implements * @param order 订单 * @param orderSn 订单编号 */ - private void complete(Order order, String orderSn) {//修改订单状态为完成 + @Transactional(rollbackFor = Exception.class) + public void complete(Order order, String orderSn) {//修改订单状态为完成 this.updateStatus(orderSn, OrderStatusEnum.COMPLETED); //修改订单货物可以进行评价 @@ -546,10 +543,9 @@ public class OrderServiceImpl extends ServiceImpl implements } @Override + @Transactional(rollbackFor = Exception.class) public void sendUpdateStatusMessage(OrderMessage orderMessage) { - String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.STATUS_CHANGE.name(); - //发送订单变更mq消息 - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(orderMessage), RocketmqSendCallbackBuilder.commonCallback()); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("发送订单变更mq消息", rocketmqCustomProperties.getOrderTopic(), OrderTagsEnum.STATUS_CHANGE.name(), JSONUtil.toJsonStr(orderMessage))); } @Override @@ -633,6 +629,7 @@ public class OrderServiceImpl extends ServiceImpl implements } @Override + @Transactional(rollbackFor = Exception.class) public void batchDeliver(MultipartFile files) { InputStream inputStream; @@ -721,6 +718,7 @@ public class OrderServiceImpl extends ServiceImpl implements * @return 是否成功 */ @Override + @Transactional(rollbackFor = Exception.class) public boolean checkFictitiousOrder(String pintuanId, Integer requiredNum, Boolean fictitious) { Map> collect = this.queryListByPromotion(pintuanId) .stream().collect(Collectors.groupingBy(Order::getParentOrderSn)); @@ -788,15 +786,35 @@ public class OrderServiceImpl extends ServiceImpl implements /** * 订单状态变更消息 * - * @param order + * @param order 订单信息 */ - private void orderStatusMessage(Order order) { + @Transactional(rollbackFor = Exception.class) + public void orderStatusMessage(Order order) { OrderMessage orderMessage = new OrderMessage(); orderMessage.setOrderSn(order.getSn()); orderMessage.setNewStatus(OrderStatusEnum.valueOf(order.getOrderStatus())); this.sendUpdateStatusMessage(orderMessage); } + /** + * 生成店铺退款流水 + * + * @param order 订单信息 + */ + private void generatorStoreRefundFlow(Order order) { + // 判断订单是否是付款 + if (!PayStatusEnum.PAID.name().equals((order.getPayStatus()))) { + return; + } + List items = orderItemService.getByOrderSn(order.getSn()); + List storeFlows = new ArrayList<>(); + for (OrderItem item : items) { + StoreFlow storeFlow = new StoreFlow(order, item, FlowTypeEnum.REFUND); + storeFlows.add(storeFlow); + } + storeFlowService.saveBatch(storeFlows); + } + /** * 此方法只提供内部调用,调用前应该做好权限处理 * 修改订单状态 @@ -822,11 +840,10 @@ public class OrderServiceImpl extends ServiceImpl implements List list = this.getPintuanOrder(pintuanId, parentOrderSn); int count = list.size(); if (count == 1) { - //如果为开团订单,则发布一个一小时的延时任务,时间到达后,如果未成团则自动结束(未开启虚拟成团的情况下) + //如果为开团订单,则发布一个24小时的延时任务,时间到达后,如果未成团则自动结束(未开启虚拟成团的情况下) PintuanOrderMessage pintuanOrderMessage = new PintuanOrderMessage(); //开团结束时间 -// long startTime = DateUtil.offsetHour(new Date(), 1).getTime(); - long startTime = DateUtil.offsetMinute(new Date(), 2).getTime(); + long startTime = DateUtil.offsetHour(new Date(), 24).getTime(); pintuanOrderMessage.setOrderSn(parentOrderSn); pintuanOrderMessage.setPintuanId(pintuanId); TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.PROMOTION_EXECUTOR, @@ -918,7 +935,8 @@ public class OrderServiceImpl extends ServiceImpl implements * * @param orderSn 订单编号 */ - private void normalOrderConfirm(String orderSn) { + @Transactional(rollbackFor = Exception.class) + public void normalOrderConfirm(String orderSn) { //修改订单 this.update(new LambdaUpdateWrapper() .eq(Order::getSn, orderSn) @@ -937,7 +955,8 @@ public class OrderServiceImpl extends ServiceImpl implements * * @param orderSn 订单编号 */ - private void virtualOrderConfirm(String orderSn) { + @Transactional(rollbackFor = Exception.class) + public void virtualOrderConfirm(String orderSn) { //修改订单 this.update(new LambdaUpdateWrapper() .eq(Order::getSn, orderSn) @@ -960,71 +979,16 @@ public class OrderServiceImpl extends ServiceImpl implements throw new ServiceException(ResultCode.ORDER_NOT_EXIST); } //判断是否为虚拟订单 - else if (!order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name())) { + if (!order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name())) { throw new ServiceException(ResultCode.ORDER_TAKE_ERROR); } //判断虚拟订单状态 - else if (!order.getOrderStatus().equals(OrderStatusEnum.TAKE.name())) { + if (!order.getOrderStatus().equals(OrderStatusEnum.TAKE.name())) { throw new ServiceException(ResultCode.ORDER_TAKE_ERROR); } //判断验证码是否正确 - else if (!verificationCode.equals(order.getVerificationCode())) { + if (!verificationCode.equals(order.getVerificationCode())) { throw new ServiceException(ResultCode.ORDER_TAKE_ERROR); } } - - - /** - * 获取订单 - * - * @param receivableNo 微信支付单号 - * @return 订单详情 - */ - @Override - public Order getOrderByReceivableNo(String receivableNo) { - return this.getOne(new LambdaQueryWrapper().eq(Order::getReceivableNo, receivableNo)); - } - - - /** - * 验证福禄订单进行处理 - * - * @param tradeNo 第三方流水 - */ - @Override - public void fuluOrder(String tradeNo) { - Order order = this.getOrderByReceivableNo(tradeNo); - if (order != null) { - List storeFlows = storeFlowService.list(new LambdaQueryWrapper().eq(StoreFlow::getOrderSn, order.getSn())); - if (storeFlows.size() > 0) { - Goods goods = goodsService.getById(storeFlows.get(0).getGoodsId()); - if (goods != null) { - FuLuConfigureDTO fuLuConfigureDTO = new FuLuConfigureDTO(); - StoreDetail storeDetail = storeDetailService.getOne( - new LambdaQueryWrapper() - .eq(StoreDetail::getStoreId, storeFlows.get(0).getStoreId()) - ); - - fuLuConfigureDTO.setAppSecretKey(storeDetail.getAppSecretKey()); - fuLuConfigureDTO.setMerchantNumber(storeDetail.getMerchantNumber()); - fuLuConfigureDTO.setAppMerchantKey(storeDetail.getAppMerchantKey()); - try { - if (goods.getBrandId().equals("1496301301183672321")) { - Map map1 = (Map) JSON.parse(Test.productInfoGetTest(fuLuConfigureDTO, goods.getSn()).get("result").toString()); - - if (map1.get("product_type").toString().equals("直充")) { - Test.directOrderAddTest(fuLuConfigureDTO, Integer.valueOf(goods.getSn()), order.getGoodsNum(), order.getQrCode(), order.getSn()); - } else if (map1.get("product_type").toString().equals("卡密")) { - Test.cardOrderAddTest(fuLuConfigureDTO, Integer.valueOf(goods.getSn()), order.getGoodsNum(), order.getSn()); - } else { - //不是直充也不是卡密需要修改代码 - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java index 6df5053f..2616b74c 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java @@ -1,7 +1,6 @@ package cn.lili.modules.order.order.serviceimpl; import cn.hutool.core.text.CharSequenceUtil; -import cn.lili.common.utils.BeanUtil; import cn.lili.common.utils.CurrencyUtil; import cn.lili.common.utils.SnowFlake; import cn.lili.common.vo.PageVO; @@ -11,8 +10,6 @@ import cn.lili.modules.order.order.entity.dos.OrderItem; import cn.lili.modules.order.order.entity.dos.StoreFlow; import cn.lili.modules.order.order.entity.dto.StoreFlowQueryDTO; import cn.lili.modules.order.order.entity.enums.FlowTypeEnum; -import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum; -import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.StoreFlowMapper; import cn.lili.modules.order.order.service.OrderItemService; import cn.lili.modules.order.order.service.OrderService; @@ -64,6 +61,11 @@ public class StoreFlowServiceImpl extends ServiceImpl().eq(StoreFlow::getOrderItemSn, afterSale.getOrderItemSn()) .eq(StoreFlow::getFlowType, FlowTypeEnum.PAY)); + //申请商品退款数量 storeFlow.setNum(afterSale.getNum()); + //分类ID storeFlow.setCategoryId(payStoreFlow.getCategoryId()); - //佣金 + //佣金 = (佣金/订单商品数量)* 售后商品数量 storeFlow.setCommissionPrice(CurrencyUtil.mul(CurrencyUtil.div(payStoreFlow.getCommissionPrice(), payStoreFlow.getNum()), afterSale.getNum())); - //分销佣金 + //分销佣金 =(分销佣金/订单商品数量)* 售后商品数量 storeFlow.setDistributionRebate(CurrencyUtil.mul(CurrencyUtil.div(payStoreFlow.getDistributionRebate(), payStoreFlow.getNum()), afterSale.getNum())); - //流水金额 - storeFlow.setFinalPrice(afterSale.getActualRefundPrice()); - //最终结算金额 - storeFlow.setBillPrice(CurrencyUtil.add(storeFlow.getFinalPrice(), storeFlow.getDistributionRebate(), storeFlow.getCommissionPrice())); - //获取第三方支付流水号 + //流水金额 = 支付最终结算金额 + storeFlow.setFinalPrice(payStoreFlow.getBillPrice()); + //最终结算金额 =实际退款金额 + storeFlow.setBillPrice(afterSale.getActualRefundPrice()); + //站点优惠券补贴返还金额=(站点优惠券补贴金额/购买商品数量)*退款商品数量 + storeFlow.setSiteCouponCommission(CurrencyUtil.mul(CurrencyUtil.div(payStoreFlow.getSiteCouponCommission(), payStoreFlow.getNum()), afterSale.getNum())); + //平台优惠券 使用金额 + storeFlow.setSiteCouponPrice(payStoreFlow.getSiteCouponPrice()); + //站点优惠券佣金比例 + storeFlow.setSiteCouponPoint(payStoreFlow.getSiteCouponPoint()); + //退款日志 RefundLog refundLog = refundLogService.queryByAfterSaleSn(afterSale.getSn()); + //第三方流水单号 storeFlow.setTransactionId(refundLog.getReceivableNo()); + //支付方式 storeFlow.setPaymentName(refundLog.getPaymentName()); this.save(storeFlow); } diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java index 5d28a5b1..6094598d 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java @@ -1 +1 @@ -package cn.lili.modules.order.order.serviceimpl; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; 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.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @since 2020/11/17 7:39 下午 */ @Service public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, JSONUtil.toJsonStr(tradeDTO)); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO 购物车视图 */ private void createTradeCheck(TradeDTO tradeDTO) { //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } //订单配送区域校验 if (tradeDTO.getNotSupportFreight() != null && !tradeDTO.getNotSupportFreight().isEmpty()) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> stringBuilder.append(sku.getGoodsSku().getGoodsName())); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO 购物车视图 */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(tradeDTO.getMemberId(), ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO 购物车视图 */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO 购物车视图 */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.endKanjiaActivity(kanjiaId); } } } \ No newline at end of file +package cn.lili.modules.order.order.serviceimpl; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; 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.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @since 2020/11/17 7:39 下午 */ @Service public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, JSONUtil.toJsonStr(tradeDTO)); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO 购物车视图 */ private void createTradeCheck(TradeDTO tradeDTO) { //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } //订单配送区域校验 if (tradeDTO.getNotSupportFreight() != null && !tradeDTO.getNotSupportFreight().isEmpty()) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> stringBuilder.append(sku.getGoodsSku().getGoodsName())); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } if (tradeDTO.getCartList().stream().noneMatch(CartVO::getChecked)) { throw new ServiceException(ResultCode.ORDER_NOT_EXIST_VALID); } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO 购物车视图 */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(tradeDTO.getMemberId(), ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO 购物车视图 */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO 购物车视图 */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.endKanjiaActivity(kanjiaId); } } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/page/service/ArticleService.java b/framework/src/main/java/cn/lili/modules/page/service/ArticleService.java index cd677a0b..67e97b56 100644 --- a/framework/src/main/java/cn/lili/modules/page/service/ArticleService.java +++ b/framework/src/main/java/cn/lili/modules/page/service/ArticleService.java @@ -53,7 +53,7 @@ public interface ArticleService extends IService
{ Article updateArticle(Article article); /** - * 删除文章 + * 删除文章--id * * @param id */ @@ -87,4 +87,12 @@ public interface ArticleService extends IService
{ */ @CacheEvict(key = "#id") Boolean updateArticleStatus(String id, boolean status); + + /** + * 修改文章--文章类型修改 + * @param article + * @return + */ + @CacheEvict(key = "#article.type") + Article updateArticleType(Article article); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/page/serviceimpl/ArticleServiceImpl.java b/framework/src/main/java/cn/lili/modules/page/serviceimpl/ArticleServiceImpl.java index 5c942301..77ddd2f8 100644 --- a/framework/src/main/java/cn/lili/modules/page/serviceimpl/ArticleServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/page/serviceimpl/ArticleServiceImpl.java @@ -91,4 +91,12 @@ public class ArticleServiceImpl extends ServiceImpl impl article.setOpenStatus(status); return this.updateById(article); } + + @Override + public Article updateArticleType(Article article) { + Article oldArticle = this.getById(article.getId()); + BeanUtil.copyProperties(article, oldArticle); + this.updateById(oldArticle); + return oldArticle; + } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java b/framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java index 6f7cf9b1..49fc3999 100644 --- a/framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java @@ -1,5 +1,6 @@ package cn.lili.modules.page.serviceimpl; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; import cn.lili.common.enums.ClientTypeEnum; @@ -82,12 +83,11 @@ public class PageDataServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public PageData updatePageData(PageData pageData) { - //如果页面为发布,则关闭其他页面,开启此页面 if (pageData.getPageShow() != null && pageData.getPageShow().equals(SwitchEnum.OPEN.name())) { LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); - lambdaUpdateWrapper.eq(PageData::getPageType, pageData.getPageType()); - lambdaUpdateWrapper.eq(PageData::getPageClientType, pageData.getPageClientType()); + lambdaUpdateWrapper.eq(CharSequenceUtil.isNotEmpty(pageData.getPageType()), PageData::getPageType, pageData.getPageType()); + lambdaUpdateWrapper.eq(CharSequenceUtil.isNotEmpty(pageData.getPageClientType()), PageData::getPageClientType, pageData.getPageClientType()); lambdaUpdateWrapper.set(PageData::getPageShow, SwitchEnum.CLOSE.name()); lambdaUpdateWrapper.set(StrUtil.isNotEmpty(pageData.getNum()), PageData::getNum, SwitchEnum.CLOSE.name()); this.update(lambdaUpdateWrapper); diff --git a/framework/src/main/java/cn/lili/modules/payment/entity/RefundLog.java b/framework/src/main/java/cn/lili/modules/payment/entity/RefundLog.java index 8309380c..c6a0663a 100644 --- a/framework/src/main/java/cn/lili/modules/payment/entity/RefundLog.java +++ b/framework/src/main/java/cn/lili/modules/payment/entity/RefundLog.java @@ -1,5 +1,6 @@ package cn.lili.modules.payment.entity; +import cn.lili.modules.payment.entity.enums.PaymentMethodEnum; import cn.lili.mybatis.BaseIdEntity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; @@ -48,6 +49,9 @@ public class RefundLog extends BaseIdEntity { @ApiModelProperty(value = "是否已退款") private Boolean isRefund; + /** + * @see PaymentMethodEnum + */ @ApiModelProperty(value = "退款方式") private String paymentName; diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/Payment.java b/framework/src/main/java/cn/lili/modules/payment/kit/Payment.java index 4046dc1a..f67c2619 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/Payment.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/Payment.java @@ -83,17 +83,6 @@ public interface Payment { throw new ServiceException(ResultCode.PAY_ERROR); } - - /** - * 取消支付订单 - * - * @param refundLog 支付参数 - */ - default void cancel(RefundLog refundLog) { - throw new ServiceException(ResultCode.PAY_ERROR); - } - - /** * 回调 * @@ -131,6 +120,7 @@ public interface Payment { default String callbackUrl(String api, PaymentMethodEnum paymentMethodEnum) { return api + "/buyer/payment/cashier/callback/" + paymentMethodEnum.name(); } + /** * 支付异步通知地址 * diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java b/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java index e8b75859..3e3d059e 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java @@ -75,7 +75,6 @@ public class RefundSupport { * * @return void * @Author ftyy - * @Description //TODO * @Date 17:33 2021/11/18 * @Param [afterSale] **/ @@ -89,31 +88,6 @@ public class RefundSupport { orderItemService.updateById(orderItem); } - /** - * 订单取消 - * - * @param afterSale - */ - public void cancel(AfterSale afterSale) { - - Order order = orderService.getBySn(afterSale.getOrderSn()); - RefundLog refundLog = RefundLog.builder() - .isRefund(false) - .totalAmount(afterSale.getActualRefundPrice()) - .payPrice(afterSale.getActualRefundPrice()) - .memberId(afterSale.getMemberId()) - .paymentName(order.getPaymentMethod()) - .afterSaleNo(afterSale.getSn()) - .paymentReceivableNo(order.getReceivableNo()) - .outOrderNo("AF" + SnowFlake.getIdStr()) - .orderSn(afterSale.getOrderSn()) - .refundReason(afterSale.getReason()) - .build(); - PaymentMethodEnum paymentMethodEnum = PaymentMethodEnum.paymentNameOf(order.getPaymentMethod()); - Payment payment = (Payment) SpringContextUtil.getBean(paymentMethodEnum.getPlugin()); - payment.refund(refundLog); - } - /** * 退款通知 diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/core/http/AbstractHttpDelegate.java b/framework/src/main/java/cn/lili/modules/payment/kit/core/http/AbstractHttpDelegate.java index efad726b..28bf2645 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/core/http/AbstractHttpDelegate.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/core/http/AbstractHttpDelegate.java @@ -1,10 +1,11 @@ package cn.lili.modules.payment.kit.core.http; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.net.SSLContextBuilder; +import cn.hutool.core.net.SSLProtocols; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; -import cn.hutool.http.ssl.SSLSocketFactoryBuilder; import cn.lili.modules.payment.kit.core.PaymentHttpResponse; import javax.net.ssl.KeyManager; @@ -235,12 +236,12 @@ public abstract class AbstractHttpDelegate { try { File file = FileUtil.newFile(filePath); return HttpRequest.post(url) - .setSSLSocketFactory(SSLSocketFactoryBuilder + .setSSLSocketFactory(SSLContextBuilder .create() .setProtocol(protocol) .setKeyManagers(getKeyManager(certPass, certPath, null)) .setSecureRandom(new SecureRandom()) - .build() + .build().getSocketFactory() ) .header("Content-Type", "multipart/form-data;boundary=\"boundary\"") .form("file", file) @@ -263,7 +264,7 @@ public abstract class AbstractHttpDelegate { * @return {@link String} 请求返回的结果 */ public String upload(String url, String data, String certPath, String certPass, String filePath) { - return upload(url, data, certPath, certPass, filePath, SSLSocketFactoryBuilder.TLSv1); + return upload(url, data, certPath, certPass, filePath, SSLProtocols.TLSv1); } /** @@ -279,12 +280,12 @@ public abstract class AbstractHttpDelegate { public String post(String url, String data, String certPath, String certPass, String protocol) { try { return HttpRequest.post(url) - .setSSLSocketFactory(SSLSocketFactoryBuilder + .setSSLSocketFactory(SSLContextBuilder .create() .setProtocol(protocol) .setKeyManagers(getKeyManager(certPass, certPath, null)) .setSecureRandom(new SecureRandom()) - .build() + .build().getSocketFactory() ) .body(data) .execute() @@ -304,7 +305,7 @@ public abstract class AbstractHttpDelegate { * @return {@link String} 请求返回的结果 */ public String post(String url, String data, String certPath, String certPass) { - return post(url, data, certPath, certPass, SSLSocketFactoryBuilder.TLSv1); + return post(url, data, certPath, certPass, SSLProtocols.TLSv1); } /** @@ -320,12 +321,12 @@ public abstract class AbstractHttpDelegate { public String post(String url, String data, InputStream certFile, String certPass, String protocol) { try { return HttpRequest.post(url) - .setSSLSocketFactory(SSLSocketFactoryBuilder + .setSSLSocketFactory(SSLContextBuilder .create() .setProtocol(protocol) .setKeyManagers(getKeyManager(certPass, null, certFile)) .setSecureRandom(new SecureRandom()) - .build() + .build().getSocketFactory() ) .body(data) .execute() @@ -345,7 +346,7 @@ public abstract class AbstractHttpDelegate { * @return {@link String} 请求返回的结果 */ public String post(String url, String data, InputStream certFile, String certPass) { - return post(url, data, certFile, certPass, SSLSocketFactoryBuilder.TLSv1); + return post(url, data, certFile, certPass, SSLProtocols.TLSv1); } /** diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/params/dto/CashierParam.java b/framework/src/main/java/cn/lili/modules/payment/kit/params/dto/CashierParam.java index 577cd13c..75bf50d2 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/params/dto/CashierParam.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/params/dto/CashierParam.java @@ -1,5 +1,6 @@ package cn.lili.modules.payment.kit.params.dto; +import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.utils.StringUtils; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -18,6 +19,8 @@ import java.util.List; @ToString public class CashierParam { + static final Long MAX_DETAIL_LENGTH = 30L; + @ApiModelProperty(value = "价格") private Double price; @@ -44,9 +47,9 @@ public class CashierParam { private Double walletValue; public String getDetail() { - if (StringUtils.isEmpty(detail)) { + if (CharSequenceUtil.isEmpty(detail)) { return "清单详细"; } - return StringUtils.filterSpecialChart(detail); + return StringUtils.filterSpecialChart(StringUtils.sub(detail, 30)); } } diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/alipay/AliPayPlugin.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/alipay/AliPayPlugin.java index b4a8a094..9641d751 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/alipay/AliPayPlugin.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/alipay/AliPayPlugin.java @@ -211,31 +211,6 @@ public class AliPayPlugin implements Payment { } - @Override - public void cancel(RefundLog refundLog) { - AlipayTradeCancelModel model = new AlipayTradeCancelModel(); - //这里取支付回调时返回的流水 - if (StringUtils.isNotEmpty(refundLog.getPaymentReceivableNo())) { - model.setTradeNo(refundLog.getPaymentReceivableNo()); - } else { - log.error("退款时,支付参数为空导致异常:{}", refundLog); - throw new ServiceException(ResultCode.ALIPAY_PARAMS_EXCEPTION); - } - try { - //与阿里进行交互 - AlipayTradeCancelResponse alipayTradeCancelResponse = AliPayApi.tradeCancelToResponse(model); - if (alipayTradeCancelResponse.isSuccess()) { - refundLog.setIsRefund(true); - refundLog.setReceivableNo(refundLog.getOutOrderNo()); - } else { - refundLog.setErrorMessage(String.format("错误码:%s,错误原因:%s", alipayTradeCancelResponse.getSubCode(), alipayTradeCancelResponse.getSubMsg())); - } - refundLogService.save(refundLog); - } catch (Exception e) { - log.error("支付宝退款异常", e); - } - } - @Override public void refundNotify(HttpServletRequest request) { //不需要实现 diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wallet/WalletPlugin.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wallet/WalletPlugin.java index 79245326..434085db 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wallet/WalletPlugin.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wallet/WalletPlugin.java @@ -96,21 +96,6 @@ public class WalletPlugin implements Payment { return ResultUtil.success(ResultCode.PAY_SUCCESS); } - @Override - public void cancel(RefundLog refundLog) { - - try { - memberWalletService.increase(new MemberWalletUpdateDTO(refundLog.getTotalAmount(), - refundLog.getMemberId(), - "取消[" + refundLog.getOrderSn() + "]订单,退还金额[" + refundLog.getTotalAmount() + "]", - DepositServiceTypeEnum.WALLET_REFUND.name())); - refundLog.setIsRefund(true); - refundLogService.save(refundLog); - } catch (Exception e) { - log.error("订单取消错误", e); - } - } - /** * 保存支付日志 * @@ -124,8 +109,6 @@ public class WalletPlugin implements Payment { //获取支付收银参数 CashierParam cashierParam = cashierSupport.cashierParam(payParam); this.callBack(payParam, cashierParam); - } catch (Exception e) { - throw e; } finally { lock.unlock(); } @@ -136,7 +119,7 @@ public class WalletPlugin implements Payment { try { memberWalletService.increase(new MemberWalletUpdateDTO(refundLog.getTotalAmount(), refundLog.getMemberId(), - "售后[" + refundLog.getAfterSaleNo() + "]审批,退还金额[" + refundLog.getTotalAmount() + "]", + "订单[" + refundLog.getOrderSn() + "],售后单[" + refundLog.getAfterSaleNo() + "],退还金额[" + refundLog.getTotalAmount() + "]", DepositServiceTypeEnum.WALLET_REFUND.name())); refundLog.setIsRefund(true); refundLogService.save(refundLog); diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java index a32e8572..3ba64830 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/WechatPlugin.java @@ -293,7 +293,7 @@ public class WechatPlugin implements Payment { Map map = WxPayKit.appPrepayIdCreateSign(appid, setting.getMchId(), prepayId, - setting.getApiclient_key(), SignType.HMACSHA256); + setting.getApiclient_key(), SignType.MD5); log.info("唤起支付参数:{}", map); return ResultUtil.data(map); @@ -554,12 +554,6 @@ public class WechatPlugin implements Payment { } - @Override - public void cancel(RefundLog refundLog) { - this.refund(refundLog); - } - - @Override public void refundNotify(HttpServletRequest request) { String timestamp = request.getHeader("Wechatpay-Timestamp"); diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/model/UnifiedOrderModel.java b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/model/UnifiedOrderModel.java index 25d5a3ca..52aeff50 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/model/UnifiedOrderModel.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/plugin/wechat/model/UnifiedOrderModel.java @@ -1,5 +1,7 @@ package cn.lili.modules.payment.kit.plugin.wechat.model; +import cn.hutool.json.JSONUtil; +import cn.lili.common.utils.StringUtils; import lombok.Data; import lombok.experimental.Accessors; @@ -42,6 +44,7 @@ public class UnifiedOrderModel { * 商品描述 */ private String description; + /** * 商户订单号 */ @@ -82,6 +85,7 @@ public class UnifiedOrderModel { * 场景信息 */ private SceneInfo scene_info; + } diff --git a/framework/src/main/java/cn/lili/modules/payment/serviceimpl/PaymentServiceImpl.java b/framework/src/main/java/cn/lili/modules/payment/serviceimpl/PaymentServiceImpl.java index 06b6d70a..97b69d8b 100644 --- a/framework/src/main/java/cn/lili/modules/payment/serviceimpl/PaymentServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/payment/serviceimpl/PaymentServiceImpl.java @@ -28,9 +28,12 @@ public class PaymentServiceImpl implements PaymentService { @Override public void success(PaymentSuccessParams paymentSuccessParams) { + //支付状态 boolean paymentResult = cashierSupport.paymentResult(paymentSuccessParams.getPayParam()); + + //已支付则返回 if (paymentResult) { - log.warn("订单支付状态后,调用支付成功接口,流水号:{}", paymentSuccessParams.getReceivableNo()); + log.warn("收银台重复收款,流水号:{}", paymentSuccessParams.getReceivableNo()); return; } diff --git a/framework/src/main/java/cn/lili/modules/permission/entity/dos/Department.java b/framework/src/main/java/cn/lili/modules/permission/entity/dos/Department.java index aa8d7348..854db81f 100644 --- a/framework/src/main/java/cn/lili/modules/permission/entity/dos/Department.java +++ b/framework/src/main/java/cn/lili/modules/permission/entity/dos/Department.java @@ -5,8 +5,9 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.EqualsAndHashCode; -import java.math.BigDecimal; +import javax.validation.constraints.NotNull; /** @@ -18,11 +19,13 @@ import java.math.BigDecimal; @Data @TableName("li_department") @ApiModel(value = "部门") +@EqualsAndHashCode(callSuper = true) public class Department extends BaseEntity { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "部门名称") + @NotNull(message = "部门名称不能为空") private String title; @ApiModelProperty(value = "父id") diff --git a/framework/src/main/java/cn/lili/modules/permission/entity/vo/SystemLogVO.java b/framework/src/main/java/cn/lili/modules/permission/entity/vo/SystemLogVO.java index 8718de48..b3a9ec9c 100644 --- a/framework/src/main/java/cn/lili/modules/permission/entity/vo/SystemLogVO.java +++ b/framework/src/main/java/cn/lili/modules/permission/entity/vo/SystemLogVO.java @@ -42,7 +42,7 @@ public class SystemLogVO implements Serializable { @ApiModelProperty(value = "日志记录时间") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") - @Field(type = FieldType.Date, format = DateFormat.basic_date_time) + @Field(type = FieldType.Date, format = DateFormat.basic_date_time, fielddata = true) private Date createTime = new Date(); @ApiModelProperty(value = "请求用户") diff --git a/framework/src/main/java/cn/lili/modules/permission/mapper/MenuMapper.java b/framework/src/main/java/cn/lili/modules/permission/mapper/MenuMapper.java index bd3c7235..049fb70e 100644 --- a/framework/src/main/java/cn/lili/modules/permission/mapper/MenuMapper.java +++ b/framework/src/main/java/cn/lili/modules/permission/mapper/MenuMapper.java @@ -24,7 +24,7 @@ public interface MenuMapper extends BaseMapper { @Select("SELECT menu.* FROM li_menu AS menu WHERE menu.id IN (" + "SELECT rm.menu_id FROM li_role_menu AS rm WHERE rm.role_id IN (" + "SELECT ur.role_id FROM li_user_role AS ur WHERE ur.user_id=#{userId}) OR rm.role_id IN (" + - "SELECT dr.role_id FROM li_department_role AS dr WHERE dr.id=(" + + "SELECT dr.role_id FROM li_department_role AS dr WHERE dr.department_id =(" + "SELECT department_id FROM li_admin_user AS au WHERE au.id = #{userId})))") List findByUserId(String userId); diff --git a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java index a7411f44..53ec3049 100644 --- a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java @@ -141,15 +141,6 @@ public class AdminUserServiceImpl extends ServiceImpl implements Me if (Boolean.TRUE.equals(authUser.getIsSuper())) { return this.tree(); } - List userMenus = this.baseMapper.findByUserId(authUser.getId()); + List userMenus = this.findUserList(authUser.getId()); return this.tree(userMenus); } @Override public List findUserList(String userId) { - String cacheKey = CachePrefix.MENU_USER_ID.getPrefix() + userId; + String cacheKey = CachePrefix.USER_MENU.getPrefix(UserEnums.MANAGER) + userId; List menuList = cache.get(cacheKey); if (menuList == null) { menuList = this.baseMapper.findByUserId(userId); - cache.put(cacheKey, menuList); + //每5分钟重新确认用户权限 + cache.put(cacheKey, menuList, 300L); } return menuList; } @@ -84,9 +86,9 @@ public class MenuServiceImpl extends ServiceImpl implements Me @Override public boolean saveOrUpdateMenu(Menu menu) { if (CharSequenceUtil.isNotEmpty(menu.getId())) { - cache.vagueDel(CachePrefix.MENU_USER_ID.getPrefix()); - cache.vagueDel(CachePrefix.USER_MENU.getPrefix()); + } + cache.vagueDel(CachePrefix.USER_MENU.getPrefix(UserEnums.MANAGER)); return this.saveOrUpdate(menu); } diff --git a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/RoleMenuServiceImpl.java b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/RoleMenuServiceImpl.java index 8966c190..0d2a22dc 100644 --- a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/RoleMenuServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/RoleMenuServiceImpl.java @@ -47,13 +47,7 @@ public class RoleMenuServiceImpl extends ServiceImpl i @Override public List findAllMenu(String userId) { - String cacheKey = CachePrefix.USER_MENU.getPrefix() + userId; - List menuList = (List) cache.get(cacheKey); - if (menuList == null) { - menuList = menuMapper.getUserRoleMenu(userId); - cache.put(cacheKey, menuList); - } - return menuList; + return menuMapper.getUserRoleMenu(userId); } @@ -65,8 +59,7 @@ public class RoleMenuServiceImpl extends ServiceImpl i this.deleteRoleMenu(roleId); //重新保存角色菜单关系 this.saveBatch(roleMenus); - cache.vagueDel(CachePrefix.MENU_USER_ID.getPrefix()); - cache.vagueDel(CachePrefix.USER_MENU.getPrefix()); + } catch (Exception e) { log.error("修改用户权限错误", e); } @@ -78,8 +71,7 @@ public class RoleMenuServiceImpl extends ServiceImpl i QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("role_id", roleId); this.remove(queryWrapper); - cache.vagueDel(CachePrefix.MENU_USER_ID.getPrefix()); - cache.vagueDel(CachePrefix.USER_MENU.getPrefix()); + } @Override @@ -88,7 +80,6 @@ public class RoleMenuServiceImpl extends ServiceImpl i QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.in("role_id", roleId); this.remove(queryWrapper); - cache.vagueDel(CachePrefix.MENU_USER_ID.getPrefix()); - cache.vagueDel(CachePrefix.USER_MENU.getPrefix()); + } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/SystemLogServiceImpl.java b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/SystemLogServiceImpl.java index 7b519465..693794c0 100644 --- a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/SystemLogServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/SystemLogServiceImpl.java @@ -14,10 +14,9 @@ import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; @@ -42,8 +41,7 @@ public class SystemLogServiceImpl implements SystemLogService { * ES */ @Autowired - @Qualifier("elasticsearchRestTemplate") - private ElasticsearchRestTemplate restTemplate; + private ElasticsearchOperations restTemplate; @Override public void saveLog(SystemLogVO systemLogVO) { diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/BasePromotions.java b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/BasePromotions.java index f3366dde..5867af4a 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/BasePromotions.java +++ b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/BasePromotions.java @@ -29,7 +29,7 @@ public class BasePromotions extends BaseEntity { @ApiModelProperty(value = "商家名称,如果是平台,这个值为 platform") private String storeName; - @ApiModelProperty(value = "商家id,如果是平台,这个值为 platform") + @ApiModelProperty(value = "商家id,如果是平台,这个值为 0") private String storeId; @NotEmpty(message = "活动名称不能为空") diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java index 6eeff349..11c30b9a 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java +++ b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java @@ -36,7 +36,7 @@ public class MemberCoupon extends BaseEntity { @ApiModelProperty(value = "从哪个模版领取的优惠券") private String couponId; - @ApiModelProperty(value = "商家id,如果是平台发送,这个值为 platform") + @ApiModelProperty(value = "商家id,如果是平台发送,这个值为 0") private String storeId; @ApiModelProperty(value = "商家名称,如果是平台,这个值为 platform") diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/vos/PromotionSkuVO.java b/framework/src/main/java/cn/lili/modules/promotion/entity/vos/PromotionSkuVO.java index 57c54dad..24b3558d 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/entity/vos/PromotionSkuVO.java +++ b/framework/src/main/java/cn/lili/modules/promotion/entity/vos/PromotionSkuVO.java @@ -5,6 +5,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serializable; + /** * 促销skuVO * @@ -15,7 +17,9 @@ import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor -public class PromotionSkuVO { +public class PromotionSkuVO implements Serializable { + + private static final long serialVersionUID = -8587010496940375179L; /** * 促销类型 diff --git a/framework/src/main/java/cn/lili/modules/promotion/event/UpdateEsGoodsIndexPromotionsEvent.java b/framework/src/main/java/cn/lili/modules/promotion/event/UpdateEsGoodsIndexPromotionsEvent.java deleted file mode 100644 index 94442bf7..00000000 --- a/framework/src/main/java/cn/lili/modules/promotion/event/UpdateEsGoodsIndexPromotionsEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lili.modules.promotion.event; - -import lombok.Data; -import org.springframework.context.ApplicationEvent; - -/** - * @author paulG - * @since 2022/1/19 - **/ -@Data -public class UpdateEsGoodsIndexPromotionsEvent extends ApplicationEvent { - - private String promotionsJsonStr; - - public UpdateEsGoodsIndexPromotionsEvent(Object source, String promotionsJsonStr) { - super(source); - this.promotionsJsonStr = promotionsJsonStr; - } -} diff --git a/framework/src/main/java/cn/lili/modules/promotion/listener/UpdateEsGoodsIndexPromotionsListener.java b/framework/src/main/java/cn/lili/modules/promotion/listener/UpdateEsGoodsIndexPromotionsListener.java deleted file mode 100644 index 00417c5f..00000000 --- a/framework/src/main/java/cn/lili/modules/promotion/listener/UpdateEsGoodsIndexPromotionsListener.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lili.modules.promotion.listener; - -import cn.lili.common.properties.RocketmqCustomProperties; -import cn.lili.modules.promotion.event.UpdateEsGoodsIndexPromotionsEvent; -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 UpdateEsGoodsIndexPromotionsListener { - - /** - * rocketMq - */ - @Autowired - private RocketMQTemplate rocketMQTemplate; - /** - * rocketMq配置 - */ - @Autowired - private RocketmqCustomProperties rocketmqCustomProperties; - - - @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true) - public void updateEsGoodsIndexPromotions(UpdateEsGoodsIndexPromotionsEvent event) { - //更新商品促销消息 - String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_PROMOTIONS.name(); - //发送mq消息 - rocketMQTemplate.asyncSend(destination, event.getPromotionsJsonStr(), RocketmqSendCallbackBuilder.commonCallback()); - } - - -} diff --git a/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java b/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java index a19fcd48..0d438b6a 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java +++ b/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java @@ -125,6 +125,13 @@ public interface MemberCouponService extends IService { */ void cancellation(String memberId, String id); + /** + * 作废无效的会员优惠券 + * + * @return 是否操作成功 + */ + boolean expireInvalidMemberCoupon(String memberId); + /** * 关闭会员优惠券 * diff --git a/framework/src/main/java/cn/lili/modules/promotion/service/PromotionGoodsService.java b/framework/src/main/java/cn/lili/modules/promotion/service/PromotionGoodsService.java index 58a80e00..4aac7c38 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/service/PromotionGoodsService.java +++ b/framework/src/main/java/cn/lili/modules/promotion/service/PromotionGoodsService.java @@ -3,6 +3,7 @@ package cn.lili.modules.promotion.service; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.vo.PageVO; +import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -10,6 +11,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import java.util.Date; import java.util.List; +import java.util.Map; /** * 促销商品业务层 @@ -35,7 +37,7 @@ public interface PromotionGoodsService extends IService { /** * 获取某sku所有有效活动 * - * @param skuId 商品skuId + * @param skuId 商品skuId * @param storeIds 店铺id * @return 促销商品集合 */ @@ -70,7 +72,7 @@ public interface PromotionGoodsService extends IService { /** * 获取当前有效时间特定促销类型的促销商品信息 * - * @param skuId skuId + * @param skuId skuId * @param promotionTypes 特定促销类型 * @return 促销商品信息 */ @@ -79,7 +81,7 @@ public interface PromotionGoodsService extends IService { /** * 获取当前有效时间特定促销类型的促销商品价格 * - * @param skuId skuId + * @param skuId skuId * @param promotionTypes 特定促销类型 * @return 促销商品价格 */ @@ -154,4 +156,13 @@ public interface PromotionGoodsService extends IService { */ void deletePromotionGoods(PromotionGoodsSearchParams searchParams); + /** + * 获取当前商品促销信息 + * + * @param dataSku 商品sku信息 + * @param cartType 购物车类型 + * @return 当前商品促销信息 + */ + Map getCurrentGoodsPromotion(GoodsSku dataSku, String cartType); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/promotion/service/PromotionService.java b/framework/src/main/java/cn/lili/modules/promotion/service/PromotionService.java index 85ad2a41..8f8b5819 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/service/PromotionService.java +++ b/framework/src/main/java/cn/lili/modules/promotion/service/PromotionService.java @@ -1,5 +1,8 @@ package cn.lili.modules.promotion.service; +import cn.lili.modules.promotion.entity.dos.PromotionGoods; + +import java.util.List; import java.util.Map; /** @@ -15,7 +18,7 @@ public interface PromotionService { * * @return 当前促销活动集合 */ - Map getCurrentPromotion(); + Map> getCurrentPromotion(); /** * 根据商品索引获取当前商品索引的所有促销活动信息 diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java index 1baa838a..05682167 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java @@ -1,8 +1,10 @@ package cn.lili.modules.promotion.serviceimpl; +import cn.hutool.core.map.MapBuilder; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONUtil; 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.vo.PageVO; @@ -10,19 +12,16 @@ import cn.lili.modules.promotion.entity.dos.BasePromotions; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.dto.search.BasePromotionsSearchParams; import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum; -import cn.lili.modules.promotion.event.UpdateEsGoodsIndexPromotionsEvent; import cn.lili.modules.promotion.service.AbstractPromotionsService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.promotion.tools.PromotionTools; import cn.lili.mybatis.util.PageUtil; -import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.GoodsTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.transaction.annotation.Transactional; @@ -47,12 +46,6 @@ public abstract class AbstractPromotionsServiceImpl, T e @Autowired private RocketmqCustomProperties rocketmqCustomProperties; - /** - * rocketMq - */ - @Autowired - private RocketMQTemplate rocketMQTemplate; - @Autowired private ApplicationEventPublisher applicationEventPublisher; @@ -252,12 +245,12 @@ public abstract class AbstractPromotionsServiceImpl, T e * @param promotions 促销实体 */ @Override + @Transactional(rollbackFor = {Exception.class}) public void updateEsGoodsIndex(T promotions) { if (promotions.getStartTime() == null && promotions.getEndTime() == null) { + Map build = MapBuilder.create().put("promotionKey", this.getPromotionType() + "-" + promotions.getId()).put("scopeId", promotions.getScopeId()).build(); //删除商品促销消息 - String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.DELETE_GOODS_INDEX_PROMOTIONS.name(); - //发送mq消息 - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(promotions), RocketmqSendCallbackBuilder.commonCallback()); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除商品促销事件", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.DELETE_GOODS_INDEX_PROMOTIONS.name(), JSONUtil.toJsonStr(build))); } else { String esPromotionKey = this.getPromotionType().name() + "-" + promotions.getId(); @@ -268,7 +261,7 @@ public abstract class AbstractPromotionsServiceImpl, T e map.put("promotionsType", promotions.getClass().getName()); // 促销实体 map.put("promotions", promotions); - applicationEventPublisher.publishEvent(new UpdateEsGoodsIndexPromotionsEvent("更新商品索引促销事件", JSONUtil.toJsonStr(map))); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("更新商品索引促销事件", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.UPDATE_GOODS_INDEX_PROMOTIONS.name(), JSONUtil.toJsonStr(map))); } } diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java index 4f08616f..167fd2eb 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java @@ -291,7 +291,7 @@ public class CouponServiceImpl extends AbstractPromotionsServiceImpl getMemberCoupons(MemberCouponSearchParams param, PageVO pageVo) { QueryWrapper queryWrapper = param.queryWrapper(); - return this.page(PageUtil.initPage(pageVo), queryWrapper); + Page page = this.page(PageUtil.initPage(pageVo), queryWrapper); + if (page.getRecords().stream().anyMatch(i -> i.getEndTime().before(new Date()))) { + this.expireInvalidMemberCoupon(param.getMemberId()); + return this.page(PageUtil.initPage(pageVo), queryWrapper); + } + return page; } /** @@ -119,7 +126,12 @@ public class MemberCouponServiceImpl extends ServiceImpl getMemberCoupons(MemberCouponSearchParams param) { - return this.list(param.queryWrapper()); + List list = this.list(param.queryWrapper()); + if (list.stream().anyMatch(i -> i.getEndTime().before(new Date()))) { + this.expireInvalidMemberCoupon(param.getMemberId()); + return this.list(param.queryWrapper()); + } + return list; } /** @@ -273,6 +285,23 @@ public class MemberCouponServiceImpl extends ServiceImpl updateWrapper = new LambdaUpdateWrapper() + .eq(CharSequenceUtil.isNotEmpty(memberId), MemberCoupon::getMemberId, memberId) + .eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()) + .le(MemberCoupon::getEndTime, new Date()) + .set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name()); + return this.update(updateWrapper); + } + private void receiverCoupon(String couponId, String memberId, String memberName, Coupon coupon) { this.checkCouponLimit(couponId, memberId); MemberCoupon memberCoupon = new MemberCoupon(coupon); diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java index 4edd344a..51e60018 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java @@ -297,9 +297,9 @@ public class PintuanServiceImpl extends AbstractPromotionsServiceImpl promotionGoods = PromotionTools.promotionGoodsInit(pintuan.getPromotionGoodsList(), pintuan, PromotionTypeEnum.PINTUAN); for (PromotionGoods promotionGood : promotionGoods) { - if (goodsSkuService.getGoodsSkuByIdFromCache(promotionGood.getSkuId()) == null) { + if (goodsSkuService.getCanPromotionGoodsSkuByIdFromCache(promotionGood.getSkuId()) == null) { log.error("商品[" + promotionGood.getGoodsName() + "]不存在或处于不可售卖状态!"); - throw new ServiceException(); + throw new ServiceException("商品[" + promotionGood.getGoodsName() + "]不存在或处于不可售卖状态!"); } //查询是否在同一时间段参与了拼团活动 Integer count = promotionGoodsService.findInnerOverlapPromotionGoods(PromotionTypeEnum.SECKILL.name(), promotionGood.getSkuId(), pintuan.getStartTime(), pintuan.getEndTime(), pintuan.getId()); diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java index b25d7742..2be950f4 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java @@ -222,6 +222,7 @@ public class PointsGoodsServiceImpl extends AbstractPromotionsServiceImpl query = MapUtil.builder(new HashMap()).put("id", promotions.getSkuId()).build(); Map update = MapUtil.builder(new HashMap()).put("points", promotions.getPoints()).build(); //修改规格索引,发送mq消息 @@ -277,7 +278,7 @@ public class PointsGoodsServiceImpl extends AbstractPromotionsServiceImpl findSkuValidPromotion(String skuId, String storeIds) { @@ -232,8 +242,6 @@ public class PromotionGoodsServiceImpl extends ServiceImpl promotionIds) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() - .in(PromotionGoods::getPromotionId, promotionIds); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().in(PromotionGoods::getPromotionId, promotionIds); this.remove(queryWrapper); } @@ -284,4 +291,41 @@ public class PromotionGoodsServiceImpl extends ServiceImpl getCurrentGoodsPromotion(GoodsSku dataSku, String cartType) { + Map promotionMap; + EsGoodsIndex goodsIndex = goodsIndexService.findById(dataSku.getId()); + if (goodsIndex == null) { + GoodsVO goodsVO = this.goodsService.getGoodsVO(dataSku.getGoodsId()); + goodsIndex = goodsIndexService.getResetEsGoodsIndex(dataSku, goodsVO.getGoodsParamsDTOList()); + } + if (goodsIndex.getPromotionMap() != null && !goodsIndex.getPromotionMap().isEmpty()) { + if (goodsIndex.getPromotionMap().keySet().stream().anyMatch(i -> i.contains(PromotionTypeEnum.SECKILL.name())) || (goodsIndex.getPromotionMap().keySet().stream().anyMatch(i -> i.contains(PromotionTypeEnum.PINTUAN.name())) && CartTypeEnum.PINTUAN.name().equals(cartType))) { + Optional> containsPromotion = goodsIndex.getPromotionMap().entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); + containsPromotion.ifPresent(stringObjectEntry -> this.setGoodsPromotionInfo(dataSku, stringObjectEntry)); + } + promotionMap = goodsIndex.getPromotionMap(); + } else { + promotionMap = null; + dataSku.setPromotionFlag(false); + dataSku.setPromotionPrice(null); + } + return promotionMap; + } + + private void setGoodsPromotionInfo(GoodsSku dataSku, Map.Entry promotionInfo) { + JSONObject promotionsObj = JSONUtil.parseObj(promotionInfo.getValue()); + PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams(); + searchParams.setSkuId(dataSku.getId()); + searchParams.setPromotionId(promotionsObj.get("id").toString()); + PromotionGoods promotionsGoods = this.getPromotionsGoods(searchParams); + if (promotionsGoods != null && promotionsGoods.getPrice() != null) { + dataSku.setPromotionFlag(true); + dataSku.setPromotionPrice(promotionsGoods.getPrice()); + } else { + dataSku.setPromotionFlag(false); + dataSku.setPromotionPrice(null); + } + } + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionServiceImpl.java index cd0df5e8..b50c79ce 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionServiceImpl.java @@ -2,8 +2,7 @@ package cn.lili.modules.promotion.serviceimpl; import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.modules.promotion.entity.dos.*; -import cn.lili.modules.promotion.entity.dto.search.FullDiscountSearchParams; -import cn.lili.modules.promotion.entity.dto.search.PintuanSearchParams; +import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams; import cn.lili.modules.promotion.entity.dto.search.SeckillSearchParams; import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.service.*; @@ -16,6 +15,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 促销业务层实现 @@ -69,37 +69,11 @@ public class PromotionServiceImpl implements PromotionService { * @return 当前促销活动集合 */ @Override - public Map getCurrentPromotion() { - Map resultMap = new HashMap<>(16); - - SeckillSearchParams seckillSearchParams = new SeckillSearchParams(); - seckillSearchParams.setPromotionStatus(PromotionsStatusEnum.START.name()); - //获取当前进行的秒杀活动活动 - List seckillList = seckillService.listFindAll(seckillSearchParams); - if (seckillList != null && !seckillList.isEmpty()) { - for (Seckill seckill : seckillList) { - resultMap.put(PromotionTypeEnum.SECKILL.name(), seckill); - } - } - FullDiscountSearchParams fullDiscountSearchParams = new FullDiscountSearchParams(); - fullDiscountSearchParams.setPromotionStatus(PromotionsStatusEnum.START.name()); - //获取当前进行的满优惠活动 - List fullDiscountList = fullDiscountService.listFindAll(fullDiscountSearchParams); - if (fullDiscountList != null && !fullDiscountList.isEmpty()) { - for (FullDiscount fullDiscount : fullDiscountList) { - resultMap.put(PromotionTypeEnum.FULL_DISCOUNT.name(), fullDiscount); - } - } - PintuanSearchParams pintuanSearchParams = new PintuanSearchParams(); - pintuanSearchParams.setPromotionStatus(PromotionsStatusEnum.START.name()); - //获取当前进行的拼团活动 - List pintuanList = pintuanService.listFindAll(pintuanSearchParams); - if (pintuanList != null && !pintuanList.isEmpty()) { - for (Pintuan pintuan : pintuanList) { - resultMap.put(PromotionTypeEnum.PINTUAN.name(), pintuan); - } - } - return resultMap; + public Map> getCurrentPromotion() { + PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams(); + searchParams.setPromotionStatus(PromotionsStatusEnum.START.name()); + List promotionGoods = promotionGoodsService.listFindAll(searchParams); + return promotionGoods.stream().collect(Collectors.groupingBy(PromotionGoods::getPromotionType)); } /** @@ -150,7 +124,6 @@ public class PromotionServiceImpl implements PromotionService { searchParams.setSkuId(promotionGoods.getSkuId()); List seckillApplyList = seckillApplyService.getSeckillApplyList(searchParams); if (seckillApplyList != null && !seckillApplyList.isEmpty()) { - SeckillApply seckillApply = seckillApplyList.get(0); String[] split = seckill.getHours().split(","); int[] hoursSored = Arrays.stream(split).mapToInt(Integer::parseInt).toArray(); Arrays.sort(hoursSored); @@ -158,7 +131,6 @@ public class PromotionServiceImpl implements PromotionService { seckill.setEndTime(promotionGoods.getEndTime()); promotionMap.put(esPromotionKey, seckill); } - } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillApplyServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillApplyServiceImpl.java index 7bc1a1c8..992116bd 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillApplyServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillApplyServiceImpl.java @@ -161,7 +161,7 @@ public class SeckillApplyServiceImpl extends ServiceImpl promotionGoodsList = new ArrayList<>(); for (SeckillApplyVO seckillApply : seckillApplyList) { //获取参与活动的商品信息 - GoodsSku goodsSku = goodsSkuService.getGoodsSkuByIdFromCache(seckillApply.getSkuId()); + GoodsSku goodsSku = goodsSkuService.getCanPromotionGoodsSkuByIdFromCache(seckillApply.getSkuId()); if (!goodsSku.getStoreId().equals(storeId)) { continue; } @@ -184,6 +184,7 @@ public class SeckillApplyServiceImpl extends ServiceImpl promotionGoods = PromotionTools.promotionGoodsInit(promotionGoodsList, seckill, PromotionTypeEnum.SECKILL); result = promotionGoodsService.saveBatch(promotionGoods); this.seckillService.updateEsGoodsSeckill(seckill, list); + + LambdaQueryWrapper deleteWrapper = new LambdaQueryWrapper<>(); + deleteWrapper.eq(SeckillApply::getSeckillId, seckill.getId()); + deleteWrapper.notIn(SeckillApply::getSkuId, promotionGoodsList.stream().map(PromotionGoods::getSkuId).collect(Collectors.toList())); + this.remove(deleteWrapper); } - LambdaQueryWrapper deleteWrapper = new LambdaQueryWrapper<>(); - deleteWrapper.eq(SeckillApply::getSeckillId, seckill.getId()); - deleteWrapper.notIn(SeckillApply::getSkuId, promotionGoodsList.stream().map(PromotionGoods::getSkuId).collect(Collectors.toList())); - this.remove(deleteWrapper); seckillService.updateSeckillGoodsNum(seckill.getId()); return result; @@ -343,7 +345,7 @@ public class SeckillApplyServiceImpl extends ServiceImpl= hour || ((i + 1) < hoursSored.length && hoursSored[i + 1] > hour)); + boolean hoursSoredHour = (hoursSored[i] >= hour || i + 1 == hoursSored.length); if (hoursSoredHour) { SimpleDateFormat format = new SimpleDateFormat(DatePattern.NORM_DATE_PATTERN); String date = format.format(new Date()); @@ -377,7 +379,7 @@ public class SeckillApplyServiceImpl extends ServiceImpl collect = seckillApplyList.stream().filter(i -> i.getTimeLine().equals(startTimeline) && i.getPromotionApplyStatus().equals(PromotionsApplyStatusEnum.PASS.name())).collect(Collectors.toList()); for (SeckillApply seckillApply : collect) { - GoodsSku goodsSku = goodsSkuService.getGoodsSkuByIdFromCache(seckillApply.getSkuId()); + GoodsSku goodsSku = goodsSkuService.getCanPromotionGoodsSkuByIdFromCache(seckillApply.getSkuId()); if (goodsSku != null) { SeckillGoodsVO goodsVO = new SeckillGoodsVO(); BeanUtil.copyProperties(seckillApply, goodsVO); diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillServiceImpl.java index f5477391..a76f3e35 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/SeckillServiceImpl.java @@ -3,6 +3,7 @@ package cn.lili.modules.promotion.serviceimpl; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.map.MapBuilder; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.json.JSONUtil; @@ -14,7 +15,6 @@ import cn.lili.modules.promotion.entity.dos.Seckill; import cn.lili.modules.promotion.entity.dos.SeckillApply; import cn.lili.modules.promotion.entity.dto.search.SeckillSearchParams; import cn.lili.modules.promotion.entity.enums.PromotionsApplyStatusEnum; -import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum; import cn.lili.modules.promotion.entity.vos.SeckillVO; import cn.lili.modules.promotion.mapper.SeckillMapper; import cn.lili.modules.promotion.service.SeckillApplyService; @@ -40,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.List; +import java.util.Map; /** * 秒杀活动业务层实现 @@ -150,8 +151,11 @@ public class SeckillServiceImpl extends AbstractPromotionsServiceImpl skuIds) { - seckill.setScopeType(PromotionsScopeTypeEnum.PORTION_GOODS.name()); - seckill.setScopeId(ArrayUtil.join(skuIds.toArray(), ",")); + Map build = MapBuilder.create().put("promotionKey", this.getPromotionType() + "-" + seckill.getId()).put("scopeId", ArrayUtil.join(skuIds.toArray(), ",")).build(); //删除商品促销消息 String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.DELETE_GOODS_INDEX_PROMOTIONS.name(); //发送mq消息 - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(seckill), RocketmqSendCallbackBuilder.commonCallback()); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(build), RocketmqSendCallbackBuilder.commonCallback()); } @Override diff --git a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionCacheKeys.java b/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionCacheKeys.java deleted file mode 100644 index 6281f779..00000000 --- a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionCacheKeys.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lili.modules.promotion.tools; - -import cn.lili.cache.CachePrefix; - -/** - * 满额活动缓存Key - * @author paulG - * @since 2020/10/12 - **/ -public class PromotionCacheKeys { - - /** - * 读取满优惠redis key - * @param activityId 活动ID - * @return 满优惠redis key - */ - public static String getFullDiscountKey(String activityId){ - return CachePrefix.STORE_ID_FULL_DISCOUNT + "::" + activityId; - } - - /** - * 读取满优惠redis key - * @param id id - * @return 满优惠redis key - */ - public static String getPromotionGoodsKey(String id){ - return CachePrefix.PROMOTION_GOODS + "::" + id; - } - - /** - * 读取秒杀活动redis key - * @param timeStr 时间字符串(格式为 yyyyMMdd) - * @return 满优惠redis key - */ - public static String getSeckillTimelineKey(String timeStr){ - return CachePrefix.STORE_ID_SECKILL + "::" + timeStr; - } - -} diff --git a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java b/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java index 125bde42..1eb51582 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java +++ b/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java @@ -1,5 +1,6 @@ package cn.lili.modules.promotion.tools; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.CharSequenceUtil; @@ -12,6 +13,7 @@ import cn.lili.modules.promotion.entity.dos.BasePromotions; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; import java.util.*; import java.util.function.Consumer; @@ -24,11 +26,12 @@ import java.util.stream.Collectors; * @author paulG * @since 2020/8/18 **/ +@Slf4j public class PromotionTools { public static final String START_TIME_COLUMN = "start_time"; public static final String END_TIME_COLUMN = "end_time"; - public static final String PLATFORM_ID = "platform"; + public static final String PLATFORM_ID = "0"; public static final String PLATFORM_NAME = "platform"; /** @@ -130,12 +133,15 @@ public class PromotionTools { promotionGoods.setStoreName(promotion.getStoreName()); } promotionGoods.setTitle(promotion.getPromotionName()); - if (promotionGoods.getStartTime() == null) { + // 如果是秒杀活动保留原时间 + if (promotionGoods.getStartTime() == null || !PromotionTypeEnum.SECKILL.equals(promotionTypeEnum)) { promotionGoods.setStartTime(promotion.getStartTime()); } - if (promotionGoods.getEndTime() == null) { + if (promotionGoods.getStartTime() == null || !PromotionTypeEnum.SECKILL.equals(promotionTypeEnum)) { promotionGoods.setEndTime(promotion.getEndTime()); } + promotionGoods.setStartTime(promotion.getStartTime()); + promotionGoods.setEndTime(promotion.getEndTime()); promotionGoods.setPromotionType(promotionTypeEnum.name()); promotionGoods.setNum(0); promotionGoods.setDeleteFlag(promotion.getDeleteFlag()); @@ -159,18 +165,23 @@ public class PromotionTools { } public static Map filterInvalidPromotionsMap(Map map) { - if (map == null) { + if (CollUtil.isEmpty(map)) { + return new HashMap<>(); + } + try { + //移除无效促销活动 + return map.entrySet().stream().filter(Objects::nonNull).filter(i -> { + JSONObject promotionsObj = JSONUtil.parseObj(i.getValue()); + BasePromotions basePromotions = promotionsObj.toBean(BasePromotions.class); + if (basePromotions != null && basePromotions.getStartTime() != null && basePromotions.getEndTime() != null) { + return basePromotions.getStartTime().getTime() <= System.currentTimeMillis() && basePromotions.getEndTime().getTime() >= System.currentTimeMillis(); + } + return i.getValue() != null; + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue)); + } catch (Exception e) { + log.error("过滤无效促销活动出现异常。异常促销信息:{},异常信息:{} ", map, e); return new HashMap<>(); } - //移除无效促销活动 - return map.entrySet().stream().filter(i -> { - JSONObject promotionsObj = JSONUtil.parseObj(i.getValue()); - BasePromotions basePromotions = promotionsObj.toBean(BasePromotions.class); - if (basePromotions.getStartTime() != null && basePromotions.getEndTime() != null) { - return basePromotions.getStartTime().getTime() <= System.currentTimeMillis() && basePromotions.getEndTime().getTime() >= System.currentTimeMillis(); - } - return true; - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dos/CustomWords.java b/framework/src/main/java/cn/lili/modules/search/entity/dos/CustomWords.java index e11a2fc6..c64cf367 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dos/CustomWords.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dos/CustomWords.java @@ -4,7 +4,10 @@ import cn.lili.mybatis.BaseEntity; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; @@ -18,6 +21,9 @@ import javax.validation.constraints.NotEmpty; @Data @TableName("li_custom_words") @ApiModel(value = "自定义分词") +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor public class CustomWords extends BaseEntity { private static final long serialVersionUID = 650889506808657977L; @@ -31,8 +37,12 @@ public class CustomWords extends BaseEntity { private String name; - @ApiModelProperty(value = "是否禁用") + @ApiModelProperty(value = "是否禁用: 0,禁用;1,不禁用") private Integer disabled; + public CustomWords(String name) { + this.name = name; + this.disabled = 1; + } } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsAttribute.java b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsAttribute.java index bbfad035..434f3a09 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsAttribute.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsAttribute.java @@ -33,7 +33,7 @@ public class EsGoodsAttribute implements Serializable { /** * 属性名称 */ - @Field(type = FieldType.Text) + @Field(type = FieldType.Text, fielddata = true) private String name; /** @@ -45,7 +45,7 @@ public class EsGoodsAttribute implements Serializable { /** * 属性值 */ - @Field(type = FieldType.Text) + @Field(type = FieldType.Text, fielddata = true) private String value; diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java index cd5372de..743b5dd5 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java @@ -6,14 +6,12 @@ import cn.lili.elasticsearch.EsSuffix; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.dto.GoodsParamsDTO; import cn.lili.modules.promotion.tools.PromotionTools; -import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.Accessors; import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; @@ -30,7 +28,7 @@ import java.util.Map; * @author paulG **/ @Data -@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME) +@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME, createIndex = false) @ToString @NoArgsConstructor @Accessors(chain = true) @@ -99,42 +97,42 @@ public class EsGoodsIndex implements Serializable { /** * 品牌id */ - @Field(type = FieldType.Integer, fielddata = true) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("品牌id") private String brandId; /** * 品牌名称 */ - @Field(type = FieldType.Keyword, fielddata = true) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("品牌名称") private String brandName; /** * 品牌图片地址 */ - @Field(type = FieldType.Keyword, fielddata = true) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("品牌图片地址") private String brandUrl; /** * 分类path */ - @Field(type = FieldType.Keyword) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("分类path") private String categoryPath; /** * 分类名称path */ - @Field(type = FieldType.Keyword) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("分类名称path") private String categoryNamePath; /** * 店铺分类id */ - @Field(type = FieldType.Keyword) + @Field(type = FieldType.Text, fielddata = true) @ApiModelProperty("店铺分类id") private String storeCategoryPath; @@ -217,6 +215,8 @@ public class EsGoodsIndex implements Serializable { /** * 销售模式 + * + * @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum */ @Field(type = FieldType.Text) @ApiModelProperty("销售模式") @@ -251,17 +251,18 @@ public class EsGoodsIndex implements Serializable { private String goodsVideo; @ApiModelProperty("商品发布时间") - @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") - @Field(type = FieldType.Date, format = DateFormat.basic_date_time) - private Date releaseTime; + @Field(type = FieldType.Date) + private Long releaseTime; /** * @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum */ @ApiModelProperty(value = "商品类型", required = true) + @Field(type = FieldType.Text) private String goodsType; @ApiModelProperty(value = "商品sku基础分数", required = true) + @Field(type = FieldType.Integer) private Integer skuSource; /** @@ -277,7 +278,7 @@ public class EsGoodsIndex implements Serializable { * @see PromotionTypeEnum * value 为 促销活动实体信息 */ - @Field(type = FieldType.Nested) + @Field(type = FieldType.Text) @ApiModelProperty("商品促销活动集合JSON,key 为 促销活动类型,value 为 促销活动实体信息 ") private String promotionMapJson; @@ -309,14 +310,14 @@ public class EsGoodsIndex implements Serializable { this.grade = sku.getGrade(); this.recommend = sku.getRecommend(); this.goodsType = sku.getGoodsType(); - this.releaseTime = new Date(); + this.releaseTime = new Date().getTime(); } } /** * 参数索引增加 * - * @param sku 商品sku信息 + * @param sku 商品sku信息 * @param goodsParamDTOS 商品参数信息 */ public EsGoodsIndex(GoodsSku sku, List goodsParamDTOS) { @@ -374,10 +375,14 @@ public class EsGoodsIndex implements Serializable { this.authFlag = sku.getAuthFlag(); this.intro = sku.getIntro(); this.grade = sku.getGrade(); - this.releaseTime = new Date(); + this.releaseTime = new Date().getTime(); } } + public Map getOriginPromotionMap() { + return JSONUtil.parseObj(this.promotionMapJson); + } + public Map getPromotionMap() { return PromotionTools.filterInvalidPromotionsMap(JSONUtil.parseObj(this.promotionMapJson)); } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dos/HotWordsHistory.java b/framework/src/main/java/cn/lili/modules/search/entity/dos/HotWordsHistory.java new file mode 100644 index 00000000..a012fc33 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/entity/dos/HotWordsHistory.java @@ -0,0 +1,52 @@ +package cn.lili.modules.search.entity.dos; + +import cn.lili.mybatis.BaseIdEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * HotWordsHistory + * + * @author Chopper + * @version v1.0 + * 2022-04-14 09:39 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("li_hot_words_history") +public class HotWordsHistory extends BaseIdEntity implements Comparable, Serializable { + + /** + * 词 + */ + private String keywords; + + /** + * 分数 + */ + private Integer score; + + @ApiModelProperty(value = "创建时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + public HotWordsHistory(String keywords, Integer score) { + this.keywords = keywords; + this.score = score; + } + + @Override + public int compareTo(HotWordsHistory hotWordsHistory) { + return hotWordsHistory.getScore() - this.score; + } +} diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java b/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java index 564d0ecd..2f0759d6 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java @@ -44,4 +44,7 @@ public class EsGoodsSearchDTO { @ApiModelProperty(hidden = true) private Map> notShowCol = new HashMap<>(); + @ApiModelProperty("当前商品skuId,根据当前浏览的商品信息来给用户推荐可能喜欢的商品") + private String currentGoodsId; + } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dto/HotWordsSearchParams.java b/framework/src/main/java/cn/lili/modules/search/entity/dto/HotWordsSearchParams.java new file mode 100644 index 00000000..61cd07c7 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/entity/dto/HotWordsSearchParams.java @@ -0,0 +1,83 @@ +package cn.lili.modules.search.entity.dto; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.common.utils.StringUtils; +import cn.lili.common.vo.PageVO; +import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; +import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; +import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; +import cn.lili.modules.statistics.util.StatisticsDateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.beans.BeanUtils; + +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; + +/** + * 商品查询条件 + * + * @author pikachu + * @since 2020-02-24 19:27:20 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class HotWordsSearchParams extends PageVO { + + private static final long serialVersionUID = 2544015852728566887L; + + @NotNull(message = "搜索热词不能为空") + @ApiModelProperty(value = "热词") + private String keywords; + + @ApiModelProperty(value = "快捷搜索", allowableValues = "TODAY, YESTERDAY, LAST_SEVEN, LAST_THIRTY") + private String searchType; + + @ApiModelProperty(value = "类型:年(YEAR)、月(MONTH)") + private String timeType; + + @ApiModelProperty(value = "年份") + private Integer year; + + @ApiModelProperty(value = "月份") + private Integer month; + + + //临时参数 不作为前端传递 + private Date startTIme; + + private Date endTime; + + //搜索热词数量 + private Integer top = 50; + + public QueryWrapper queryWrapper() { + //组织查询时间 + QueryWrapper queryWrapper = new QueryWrapper<>(); + StatisticsQueryParam statisticsQueryParam = new StatisticsQueryParam(); + BeanUtils.copyProperties(this, statisticsQueryParam); + Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam); + + //获取当前时间 + Calendar calendar = Calendar.getInstance(); + + + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + + if (StringUtils.isNotEmpty(keywords)) { + queryWrapper.like("keywords", keywords); + } + queryWrapper.between("create_time", dates[0], dates[1]); + + startTIme = dates[0]; + endTime = dates[1]; + + return queryWrapper; + } + +} diff --git a/framework/src/main/java/cn/lili/modules/search/entity/vo/CustomWordsVO.java b/framework/src/main/java/cn/lili/modules/search/entity/vo/CustomWordsVO.java index d6596b37..75258eba 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/vo/CustomWordsVO.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/vo/CustomWordsVO.java @@ -3,6 +3,7 @@ package cn.lili.modules.search.entity.vo; import cn.lili.modules.search.entity.dos.CustomWords; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; /** * @author paulG @@ -10,8 +11,13 @@ import lombok.EqualsAndHashCode; **/ @EqualsAndHashCode(callSuper = true) @Data +@NoArgsConstructor public class CustomWordsVO extends CustomWords { private static final long serialVersionUID = 143299060233417009L; + public CustomWordsVO(String name) { + this.setName(name); + this.setDisabled(1); + } } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/vo/HotWordsHistoryVO.java b/framework/src/main/java/cn/lili/modules/search/entity/vo/HotWordsHistoryVO.java new file mode 100644 index 00000000..cbbdc0f9 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/entity/vo/HotWordsHistoryVO.java @@ -0,0 +1,33 @@ +package cn.lili.modules.search.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Date; + +/** + * 在线会员 + * + * @author Chopper + * @since 2021-02-21 09:59 + */ +@Data +public class HotWordsHistoryVO { + + /** + * 时间 + */ + private Date createTime; + + /** + * 词 + */ + private String keywords; + + /** + * 分数 + */ + private Integer score; + +} diff --git a/framework/src/main/java/cn/lili/modules/search/mapper/CustomWordsMapper.java b/framework/src/main/java/cn/lili/modules/search/mapper/CustomWordsMapper.java index 359cd238..6f3d99ec 100644 --- a/framework/src/main/java/cn/lili/modules/search/mapper/CustomWordsMapper.java +++ b/framework/src/main/java/cn/lili/modules/search/mapper/CustomWordsMapper.java @@ -1,6 +1,7 @@ package cn.lili.modules.search.mapper; import cn.lili.modules.search.entity.dos.CustomWords; +import cn.lili.mybatis.mybatisplus.external.SpiceBaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** @@ -9,5 +10,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; * @author paulG * @since 2020/10/15 **/ -public interface CustomWordsMapper extends BaseMapper { +public interface CustomWordsMapper extends BaseMapper, SpiceBaseMapper { } diff --git a/framework/src/main/java/cn/lili/modules/search/mapper/HotWordsHistoryMapper.java b/framework/src/main/java/cn/lili/modules/search/mapper/HotWordsHistoryMapper.java new file mode 100644 index 00000000..97a1d90c --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/mapper/HotWordsHistoryMapper.java @@ -0,0 +1,32 @@ +package cn.lili.modules.search.mapper; + +import cn.lili.modules.search.entity.dos.CustomWords; +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.vo.HotWordsHistoryVO; +import cn.lili.modules.statistics.entity.vo.OrderStatisticsDataVO; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 搜索热词历史记录数据处理层 + * + * @author paulG + * @since 2020/10/15 + **/ +public interface HotWordsHistoryMapper extends BaseMapper { + + /** + * 获取订单统计数据 + * + * @param queryWrapper 查询条件 + * @return 订单统计列表 + */ + @Select("SELECT sum(score) as score,keywords FROM li_hot_words_history " +" ${ew.customSqlSegment}") + List statistics(@Param(Constants.WRAPPER) Wrapper queryWrapper); + +} diff --git a/framework/src/main/java/cn/lili/modules/search/service/CustomWordsService.java b/framework/src/main/java/cn/lili/modules/search/service/CustomWordsService.java index 5193cdf1..90d775bc 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/CustomWordsService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/CustomWordsService.java @@ -6,6 +6,8 @@ import cn.lili.modules.search.entity.vo.CustomWordsVO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + /** * 自定义分词业务层 * @@ -52,6 +54,22 @@ public interface CustomWordsService extends IService { */ boolean deleteCustomWords(String id); + /** + * 根据名字批量删除 + * + * @param names 名称列表 + * @return 是否删除成功 + */ + boolean deleteBathByName(List names); + + /** + * 批量插入自定义分词 + * + * @param customWordsList 自定义分词列表 + * @return 受影响行数 + */ + long insertBatchCustomWords(List customWordsList); + /** * 分页查询自定义分词 * diff --git a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java index f40be6d4..199e7e79 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java @@ -20,7 +20,7 @@ import java.util.Map; public interface EsGoodsIndexService { /** - * 全局索引初始化 + * 全局索引数据初始化 */ void init(); @@ -29,7 +29,13 @@ public interface EsGoodsIndexService { * * @return */ - Map getProgress(); + Map getProgress(); + + + /** + * 全局索引初始化 + */ + void initIndex(); /** * 添加商品索引 @@ -38,6 +44,13 @@ public interface EsGoodsIndexService { */ void addIndex(EsGoodsIndex goods); + /** + * 添加商品索引 + * + * @param goods 商品索引信息 + */ + void addIndex(List goods); + /** * 更新商品索引 * @@ -71,9 +84,9 @@ public interface EsGoodsIndexService { /** * 删除索引 * - * @param goods 商品索引信息 + * @param queryFields 查询条件 (key 为字段,value为字段值) */ - void deleteIndex(EsGoodsIndex goods); + void deleteIndex(Map queryFields); /** * 删除索引 @@ -93,8 +106,9 @@ public interface EsGoodsIndexService { * 初始化商品索引 * * @param goodsIndexList 商品索引列表 + * @param regeneratorIndex 是否重新生成索引 */ - void initIndex(List goodsIndexList); + void initIndex(List goodsIndexList, boolean regeneratorIndex); /** * 更新商品索引的促销信息 @@ -132,20 +146,20 @@ public interface EsGoodsIndexService { void updateEsGoodsIndexAllByList(BasePromotions promotion, String key); /** - * 删除指定商品的促销信息 + * 删除索引中指定的促销活动id的促销活动 * - * @param skuIds skuId列表 - * @param promotionType 促销类型 + * @param skuIds 商品skuId + * @param promotionsKey 促销活动Key */ - void deleteEsGoodsPromotionIndexByList(List skuIds, PromotionTypeEnum promotionType); + void deleteEsGoodsPromotionByPromotionKey(List skuIds, String promotionsKey); + /** * 删除索引中指定的促销活动id的促销活动 * - * @param skuIds 商品skuId - * @param promotionId 促销活动Id + * @param promotionsKey 促销活动Key */ - void deleteEsGoodsPromotionByPromotionId(List skuIds, String promotionId); + void deleteEsGoodsPromotionByPromotionKey(String promotionsKey); /** * 清除所以商品索引的无效促销活动 diff --git a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java index 0e50be00..4e1dbf30 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java @@ -4,7 +4,6 @@ import cn.lili.common.vo.PageVO; 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.entity.dto.HotWordsDTO; import org.springframework.data.elasticsearch.core.SearchPage; import java.util.List; @@ -26,28 +25,6 @@ public interface EsGoodsSearchService { */ SearchPage searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo); - /** - * 获取热门关键词 - * - * @param count 热词数量 - * @return 热词集合 - */ - List getHotWords(Integer count); - - /** - * 设置热门关键词 - * - * @param hotWords 热词分数 - */ - void setHotWords(HotWordsDTO hotWords); - - /** - * 删除热门关键词 - * - * @param keywords 热词 - */ - void deleteHotWords(String keywords); - /** * 获取筛选器 * diff --git a/framework/src/main/java/cn/lili/modules/search/service/HotWordsHistoryService.java b/framework/src/main/java/cn/lili/modules/search/service/HotWordsHistoryService.java new file mode 100644 index 00000000..d357b643 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/service/HotWordsHistoryService.java @@ -0,0 +1,41 @@ +package cn.lili.modules.search.service; + +import cn.lili.modules.search.entity.dos.CustomWords; +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.dto.HotWordsDTO; +import cn.lili.modules.search.entity.dto.HotWordsSearchParams; +import cn.lili.modules.search.entity.vo.HotWordsHistoryVO; +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 org.apache.poi.ss.formula.functions.T; + +import java.util.Date; +import java.util.List; + +/** + * HotWordsService + * + * @author Chopper + * @version v1.0 + * 2022-04-14 09:35 + */ +public interface HotWordsHistoryService extends IService { + + /** + * 热词统计 + * + * @param hotWordsSearchParams + * @return + */ + List statistics(HotWordsSearchParams hotWordsSearchParams); + + /** + * 根据时间查询 + * + * @param queryTime 查询时间 + * @return + */ + List queryByDay(Date queryTime); +} diff --git a/framework/src/main/java/cn/lili/modules/search/service/HotWordsService.java b/framework/src/main/java/cn/lili/modules/search/service/HotWordsService.java new file mode 100644 index 00000000..a13c9e7e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/service/HotWordsService.java @@ -0,0 +1,47 @@ +package cn.lili.modules.search.service; + +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.dto.HotWordsDTO; + +import java.util.List; + +/** + * HotWordsService + * + * @author Chopper + * @version v1.0 + * 2022-04-14 09:35 + */ +public interface HotWordsService { + + /** + * 获取热门关键词 + * + * @param count 热词数量 + * @return 热词集合 + */ + List getHotWords(Integer count); + + /** + * 获取热门关键词 + * + * @param count 热词数量 + * @return 热词集合 + */ + List getHotWordsVO(Integer count); + + /** + * 设置热门关键词 + * + * @param hotWords 热词分数 + */ + void setHotWords(HotWordsDTO hotWords); + + /** + * 删除热门关键词 + * + * @param keywords 热词 + */ + void deleteHotWords(String keywords); + +} diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/CustomWordsServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/CustomWordsServiceImpl.java index d366e4c8..405050fa 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/CustomWordsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/CustomWordsServiceImpl.java @@ -68,7 +68,7 @@ public class CustomWordsServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper().eq(CustomWords::getName, customWordsVO.getName()); CustomWords one = this.getOne(queryWrapper, false); if (one != null && one.getDisabled().equals(1)) { - throw new ServiceException(ResultCode.CUSTOM_WORDS_EXIST_ERROR); + return false; } else if (one != null && !one.getDisabled().equals(1)) { this.remove(queryWrapper); } @@ -91,6 +91,18 @@ public class CustomWordsServiceImpl extends ServiceImpl names) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(CustomWords::getName, names); + return this.remove(queryWrapper); + } + + @Override + public long insertBatchCustomWords(List customWordsList) { + return this.baseMapper.insertBatchSomeColumn(customWordsList); + } + /** * 修改自定义分词 * diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java index 9eacac60..c53ef32b 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java @@ -1,45 +1,56 @@ package cn.lili.modules.search.serviceimpl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ReflectUtil; -import cn.hutool.extra.pinyin.PinyinUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; 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.exception.RetryException; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; +import cn.lili.common.vo.PageVO; import cn.lili.elasticsearch.BaseElasticsearchService; import cn.lili.elasticsearch.EsSuffix; import cn.lili.elasticsearch.config.ElasticsearchProperties; -import cn.lili.modules.goods.entity.dos.*; +import cn.lili.modules.goods.entity.dos.Brand; +import cn.lili.modules.goods.entity.dos.Category; +import cn.lili.modules.goods.entity.dos.GoodsSku; +import cn.lili.modules.goods.entity.dos.StoreGoodsLabel; import cn.lili.modules.goods.entity.dto.GoodsParamsDTO; +import cn.lili.modules.goods.entity.dto.GoodsSkuDTO; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; -import cn.lili.modules.goods.entity.enums.GoodsWordsTypeEnum; -import cn.lili.modules.goods.service.*; +import cn.lili.modules.goods.service.BrandService; +import cn.lili.modules.goods.service.CategoryService; +import cn.lili.modules.goods.service.GoodsSkuService; +import cn.lili.modules.goods.service.StoreGoodsLabelService; import cn.lili.modules.promotion.entity.dos.BasePromotions; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.service.PromotionService; import cn.lili.modules.promotion.tools.PromotionTools; +import cn.lili.modules.search.entity.dos.CustomWords; +import cn.lili.modules.search.entity.dos.EsGoodsAttribute; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO; import cn.lili.modules.search.repository.EsGoodsIndexRepository; +import cn.lili.modules.search.service.CustomWordsService; import cn.lili.modules.search.service.EsGoodsIndexService; import cn.lili.modules.search.service.EsGoodsSearchService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.GoodsTagsEnum; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.assertj.core.util.IterableUtil; -import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.update.UpdateRequest; @@ -48,22 +59,22 @@ import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.index.reindex.BulkByScrollResponse; +import org.elasticsearch.index.reindex.DeleteByQueryRequest; import org.elasticsearch.index.reindex.UpdateByQueryRequest; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptType; -import org.mybatis.spring.MyBatisSystemException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchPage; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; -import org.springframework.util.ObjectUtils; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -77,9 +88,10 @@ import java.util.stream.Collectors; public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements EsGoodsIndexService { private static final String IGNORE_FIELD = "serialVersionUID,promotionMap,id,goodsId"; - + private static final String KEY_SUCCESS = "success"; + private static final String KEY_FAIL = "fail"; + private static final String KEY_PROCESSED = "processed"; private final Map fieldMap = ReflectUtil.getFieldMap(EsGoodsIndex.class); - @Autowired private ElasticsearchProperties elasticsearchProperties; @Autowired @@ -87,16 +99,14 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Autowired private EsGoodsSearchService goodsSearchService; @Autowired - private GoodsWordsService goodsWordsService; - @Autowired private PromotionService promotionService; + @Autowired + private CustomWordsService customWordsService; @Autowired private GoodsSkuService goodsSkuService; @Autowired - private GoodsService goodsService; - @Autowired private BrandService brandService; @Autowired @@ -117,8 +127,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Autowired - @Qualifier("elasticsearchRestTemplate") - private ElasticsearchRestTemplate restTemplate; + private ElasticsearchOperations restTemplate; @Override public void init() { @@ -135,38 +144,60 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements //初始化标识 cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); - cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true); + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true, 10L, TimeUnit.MINUTES); + ThreadUtil.execAsync(() -> { try { - List esGoodsIndices = new ArrayList<>(); - LambdaQueryWrapper goodsQueryWrapper = new LambdaQueryWrapper<>(); - goodsQueryWrapper.eq(Goods::getAuthFlag, GoodsAuthEnum.PASS.name()); - goodsQueryWrapper.eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name()); - goodsQueryWrapper.eq(Goods::getDeleteFlag, false); + QueryWrapper skuQueryWrapper = new QueryWrapper<>(); + skuQueryWrapper.eq("gs.auth_flag", GoodsAuthEnum.PASS.name()); + skuQueryWrapper.eq("gs.market_enable", GoodsStatusEnum.UPPER.name()); + skuQueryWrapper.eq("gs.delete_flag", false); - for (Goods goods : goodsService.list(goodsQueryWrapper)) { - LambdaQueryWrapper skuQueryWrapper = new LambdaQueryWrapper<>(); - skuQueryWrapper.eq(GoodsSku::getGoodsId, goods.getId()); - skuQueryWrapper.eq(GoodsSku::getAuthFlag, GoodsAuthEnum.PASS.name()); - skuQueryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); - skuQueryWrapper.eq(GoodsSku::getDeleteFlag, false); - List goodsSkuList = goodsSkuService.list(skuQueryWrapper); - int skuSource = 100; - for (GoodsSku goodsSku : goodsSkuList) { - EsGoodsIndex esGoodsIndex = wrapperEsGoodsIndex(goodsSku, goods); - esGoodsIndex.setSkuSource(skuSource--); + Map resultMap = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); + + if (CollUtil.isEmpty(resultMap)) { + QueryWrapper skuCountQueryWrapper = new QueryWrapper<>(); + skuCountQueryWrapper.eq("auth_flag", GoodsAuthEnum.PASS.name()); + skuCountQueryWrapper.eq("market_enable", GoodsStatusEnum.UPPER.name()); + skuCountQueryWrapper.eq("delete_flag", false); + resultMap = new HashMap<>(); + resultMap.put(KEY_SUCCESS, 0L); + resultMap.put(KEY_FAIL, 0L); + resultMap.put(KEY_PROCESSED, 0L); + resultMap.put("total", this.goodsSkuService.count(skuCountQueryWrapper)); + cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), resultMap); + } + + for (int i = 1; ; i++) { + List esGoodsIndices = new ArrayList<>(); + Page skuPage = new Page<>(i, 100); + IPage skuIPage = goodsSkuService.getGoodsSkuDTOByPage(skuPage, skuQueryWrapper); + if (skuIPage == null || CollUtil.isEmpty(skuIPage.getRecords())) { + break; + } + for (GoodsSkuDTO goodsSku : skuIPage.getRecords()) { + int skuSource = 100; + EsGoodsIndex esGoodsIndex = wrapperEsGoodsIndex(goodsSku); + long count = esGoodsIndices.stream().filter(j -> j.getGoodsId().equals(esGoodsIndex.getGoodsId())).count(); + if (count >= 1) { + skuSource -= count; + } + esGoodsIndex.setSkuSource(skuSource); esGoodsIndices.add(esGoodsIndex); //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity()); } + //批量插入索引,如果为第一次则删除原索引并创建新索引 + this.initIndex(esGoodsIndices, i == 1); } + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); + //初始化商品索引 - this.initIndex(esGoodsIndices); } catch (Exception e) { log.error("商品索引生成异常:", e); //如果出现异常,则将进行中的任务标识取消掉,打印日志 @@ -174,38 +205,44 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); } }); + } @Override - public Map getProgress() { - Map map = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); + public Map getProgress() { + Map map = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); if (map == null) { return Collections.emptyMap(); } Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix()); - map.put("flag", Boolean.TRUE.equals(flag) ? 1 : 0); + map.put("flag", Boolean.TRUE.equals(flag) ? 1L : 0L); return map; } + @Override + public void initIndex() { + //索引名称拼接 + String indexName = this.getIndexName(); + + //索引初始化,因为mapping结构问题: + //但是如果索引已经自动生成过,这里就不会创建索引,设置mapping,所以这里决定在初始化索引的同时,将已有索引删除,重新创建 + + boolean indexExist = this.indexExist(indexName); + log.info("检测 {} 索引结构是否存在:{}", indexName, indexExist); + if (!indexExist) { + + log.info("初始化索引结构 {}", indexName); + //如果索引不存在,则创建索引 + createIndexRequest(indexName); + } + + } + @Override public void addIndex(EsGoodsIndex goods) { try { //分词器分词 -// AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(getIndexName(), "ik_max_word", goods.getGoodsName()); -// AnalyzeResponse analyze = client.indices().analyze(analyzeRequest, RequestOptions.DEFAULT); -// List tokens = analyze.getTokens(); - -// if (goods.getAttrList() != null && !goods.getAttrList().isEmpty()) { -// //保存分词 -// for (EsGoodsAttribute esGoodsAttribute : goods.getAttrList()) { -// wordsToDb(esGoodsAttribute.getValue()); -// } -// } -// //分析词条 -// for (AnalyzeResponse.AnalyzeToken token : tokens) { -// //保存词条进入数据库 -// wordsToDb(token.getTerm()); -// } + this.analyzeAndSaveWords(goods); //生成索引 goodsIndexRepository.save(goods); } catch (Exception e) { @@ -213,11 +250,77 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } + /** + * 添加商品索引 + * + * @param goods 商品索引信息 + */ + @Override + public void addIndex(List goods) { + try { + for (EsGoodsIndex esGoodsIndex : goods) { + this.analyzeAndSaveWords(esGoodsIndex); + } + goodsIndexRepository.saveAll(goods); + } catch (Exception e) { + log.error("批量为商品生成索引异常", e); + } + } + @Override public void updateIndex(EsGoodsIndex goods) { + this.analyzeAndSaveWords(goods); goodsIndexRepository.save(goods); } + + /** + * 商品分词 + * + * @param goods 商品信息 + */ + private void analyzeAndSaveWords(EsGoodsIndex goods) { + try { + List keywordsList = new ArrayList<>(); + //根据商品参数分词 + if (goods.getAttrList() != null && !goods.getAttrList().isEmpty()) { + //保存分词 + for (EsGoodsAttribute esGoodsAttribute : goods.getAttrList()) { + if (keywordsList.stream().noneMatch(i -> i.toLowerCase(Locale.ROOT).equals(esGoodsAttribute.getValue().toLowerCase(Locale.ROOT)))) { + keywordsList.add(esGoodsAttribute.getValue()); + } + } + } + //根据商品名称生成分词 + keywordsList.add(goods.getGoodsName().substring(0, Math.min(goods.getGoodsName().length(), 10))); + + //去除重复词 + removeDuplicate(keywordsList); + //入库自定义分词 + List customWordsArrayList = new ArrayList<>(); + keywordsList.forEach(item -> customWordsArrayList.add(new CustomWords(item))); + //这里采用先批量删除再插入的方法,故意这么做。否则需要挨个匹配是否存在,性能消耗更大 + if (CollUtil.isNotEmpty(customWordsArrayList)) { + customWordsService.deleteBathByName(keywordsList); + customWordsService.insertBatchCustomWords(customWordsArrayList); + } + } catch (Exception e) { + log.info(goods + "自定义分词错误", e); + } + } + + /** + * 去除 重复元素 + * + * @param list + * @return + */ + public static void removeDuplicate(List list) { + HashSet h = new HashSet(list); + list.clear(); + list.addAll(h); + } + /** * 更新商品索引的的部分属性(只填写更新的字段,不需要更新的字段不要填写) * @@ -257,7 +360,15 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements script.append("ctx._source.").append(entry.getKey()).append("=").append("'").append(entry.getValue()).append("'").append(";"); } update.setScript(new Script(script.toString())); - client.updateByQueryAsync(update, RequestOptions.DEFAULT, this.actionListener()); + update.setConflicts("proceed"); + try { + BulkByScrollResponse bulkByScrollResponse = client.updateByQuery(update, RequestOptions.DEFAULT); + if (bulkByScrollResponse.getVersionConflicts() > 0) { + throw new RetryException("更新商品索引失败,es内容版本冲突"); + } + } catch (IOException e) { + log.error("更新商品索引异常", e); + } } /** @@ -277,7 +388,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements UpdateRequest updateRequest = new UpdateRequest(indexName, goodsIndex.getId()); JSONObject jsonObject = JSONUtil.parseObj(goodsIndex); - jsonObject.set("releaseTime", goodsIndex.getReleaseTime().getTime()); + jsonObject.set("releaseTime", goodsIndex.getReleaseTime()); updateRequest.doc(jsonObject); request.add(updateRequest); } @@ -287,13 +398,30 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } + /** + * 删除索引 + * + * @param queryFields 查询条件 + */ @Override - public void deleteIndex(EsGoodsIndex goods) { - if (ObjectUtils.isEmpty(goods)) { - //如果对象为空,则删除全量 - goodsIndexRepository.deleteAll(); + public void deleteIndex(Map queryFields) { + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + for (Map.Entry entry : queryFields.entrySet()) { + boolQueryBuilder.filter(QueryBuilders.termsQuery(entry.getKey(), entry.getValue())); + } + + DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(); + deleteByQueryRequest.setQuery(boolQueryBuilder); + deleteByQueryRequest.indices(getIndexName()); + deleteByQueryRequest.setConflicts("proceed"); + try { + BulkByScrollResponse bulkByScrollResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT); + if (bulkByScrollResponse.getVersionConflicts() > 0) { + throw new RetryException("删除索引失败,es内容版本冲突"); + } + } catch (IOException e) { + log.error("删除索引异常", e); } - goodsIndexRepository.delete(goods); } /** @@ -316,11 +444,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); queryBuilder.withQuery(QueryBuilders.termsQuery("id", ids.toArray())); this.restTemplate.delete(queryBuilder.build(), EsGoodsIndex.class); - } @Override - public void initIndex(List goodsIndexList) { + public void initIndex(List goodsIndexList, boolean regeneratorIndex) { if (goodsIndexList == null || goodsIndexList.isEmpty()) { //初始化标识 cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); @@ -334,26 +461,21 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements //但是如果索引已经自动生成过,这里就不会创建索引,设置mapping,所以这里决定在初始化索引的同时,将已有索引删除,重新创建 //如果索引存在,则删除,重新生成。 这里应该有更优解。 - if (this.indexExist(indexName)) { - deleteIndexRequest(indexName); + boolean indexExist = this.indexExist(indexName); + if (regeneratorIndex || !indexExist) { + if (indexExist) { + this.deleteIndexRequest(indexName); + } + //如果索引不存在,则创建索引 + this.createIndexRequest(indexName); } - //如果索引不存在,则创建索引 - createIndexRequest(indexName); - Map resultMap = new HashMap<>(16); - final String KEY_SUCCESS = "success"; - final String KEY_FAIL = "fail"; - final String KEY_PROCESSED = "processed"; - resultMap.put("total", goodsIndexList.size()); - resultMap.put(KEY_SUCCESS, 0); - resultMap.put(KEY_FAIL, 0); - resultMap.put(KEY_PROCESSED, 0); - cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), resultMap); + Map resultMap = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); if (!goodsIndexList.isEmpty()) { - goodsIndexRepository.deleteAll(); for (EsGoodsIndex goodsIndex : goodsIndexList) { try { - addIndex(goodsIndex); + log.info("生成商品索引:{}", goodsIndex); + this.addIndex(goodsIndex); resultMap.put(KEY_SUCCESS, resultMap.get(KEY_SUCCESS) + 1); } catch (Exception e) { log.error("商品{}生成索引错误!", goodsIndex); @@ -364,7 +486,6 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), resultMap); - cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); } @Override @@ -389,10 +510,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void updateEsGoodsIndexPromotions(List ids, BasePromotions promotion, String key) { BulkRequest bulkRequest = new BulkRequest(); - log.info("修改商品活动索引"); + log.info("更新商品索引的促销信息----------"); log.info("商品ids: {}", ids); - log.info("活动关键字: {}", key); log.info("活动: {}", promotion); + log.info("key: {}", key); for (String id : ids) { UpdateRequest updateRequest = this.updateEsGoodsIndexPromotions(id, promotion, key); if (updateRequest != null) { @@ -432,93 +553,93 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements */ @Override public void updateEsGoodsIndexAllByList(BasePromotions promotion, String key) { - List goodsIndices = new ArrayList<>(); - //如果storeId不为空,则表示是店铺活动 - if (promotion.getStoreId() != null && !promotion.getStoreId().equals(PromotionTools.PLATFORM_ID)) { - EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO(); - searchDTO.setStoreId(promotion.getStoreId()); - //查询出店铺商品 - SearchPage esGoodsIndices = goodsSearchService.searchGoods(searchDTO, null); - for (SearchHit searchHit : esGoodsIndices.getContent()) { - goodsIndices.add(searchHit.getContent()); + ThreadUtil.execAsync(() -> { + for (int i = 1; ; i++) { + List skuIds; + //如果storeId不为空,则表示是店铺活动 + if (promotion.getStoreId() != null && !promotion.getStoreId().equals(PromotionTools.PLATFORM_ID)) { + PageVO pageVO = new PageVO(); + pageVO.setPageNumber(i); + pageVO.setPageSize(1000); + EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO(); + searchDTO.setStoreId(promotion.getStoreId()); + //查询出店铺商品 + SearchPage esGoodsIndices = goodsSearchService.searchGoods(searchDTO, pageVO); + + skuIds = esGoodsIndices.isEmpty() ? new ArrayList<>() : esGoodsIndices.getContent().stream().map(SearchHit::getId).collect(Collectors.toList()); + } else { + //否则是平台活动 + org.springframework.data.domain.Page all = goodsIndexRepository.findAll(PageRequest.of(i, 1000)); + + //查询出全部商品 + skuIds = all.isEmpty() ? new ArrayList<>() : all.toList().stream().map(EsGoodsIndex::getId).collect(Collectors.toList()); + } + if (skuIds.isEmpty()) { + break; + } + this.deleteEsGoodsPromotionByPromotionKey(skuIds, key); + this.updateEsGoodsIndexPromotions(skuIds, promotion, key); } - } else { - //否则是平台活动 - Iterable all = goodsIndexRepository.findAll(); - //查询出全部商品 - goodsIndices = new ArrayList<>(IterableUtil.toCollection(all)); - } - List skuIds = goodsIndices.stream().map(EsGoodsIndex::getId).collect(Collectors.toList()); - this.deleteEsGoodsPromotionByPromotionId(skuIds, promotion.getId()); - this.updateEsGoodsIndexPromotions(skuIds, promotion, key); + + }); + } @Override - public void deleteEsGoodsPromotionIndexByList(List skuIds, PromotionTypeEnum promotionType) { - //批量删除活动索引 + public void deleteEsGoodsPromotionByPromotionKey(List skuIds, String promotionsKey) { + BulkRequest bulkRequest = new BulkRequest(); + log.info("删除商品活动索引"); + log.info("商品skuIds: {}", skuIds); + log.info("活动Key: {}", promotionsKey); + if (skuIds == null || skuIds.isEmpty()) { + return; + } for (String skuId : skuIds) { EsGoodsIndex goodsIndex = findById(skuId); //商品索引不为空 if (goodsIndex != null) { - Map promotionMap = goodsIndex.getPromotionMap(); - if (promotionMap != null && !promotionMap.isEmpty()) { - //如果存在同类型促销活动删除 - List collect = promotionMap.keySet().stream().filter(i -> i.contains(promotionType.name())).collect(Collectors.toList()); - collect.forEach(promotionMap::remove); - goodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(promotionMap)); - updateIndex(goodsIndex); + UpdateRequest updateRequest = this.removePromotionByPromotionKey(goodsIndex, promotionsKey); + if (updateRequest != null) { + bulkRequest.add(updateRequest); } } else { log.error("更新索引商品促销信息失败!skuId 为 【{}】的索引不存在!", skuId); } } + this.executeBulkUpdateRequest(bulkRequest); } + /** + * 删除索引中指定的促销活动id的促销活动 + * + * @param promotionsKey 促销活动Key + */ @Override - public void deleteEsGoodsPromotionByPromotionId(List skuIds, String promotionId) { - BulkRequest bulkRequest = new BulkRequest(); - log.info("删除商品活动索引"); - log.info("商品skuIds: {}", skuIds); - log.info("活动Id: {}", promotionId); - if (skuIds != null && !skuIds.isEmpty()) { - for (String skuId : skuIds) { - EsGoodsIndex goodsIndex = findById(skuId); - //商品索引不为空 - if (goodsIndex != null) { - UpdateRequest updateRequest = this.removePromotionByPromotionId(goodsIndex, promotionId); - if (updateRequest != null) { - bulkRequest.add(updateRequest); - } - } else { - log.error("更新索引商品促销信息失败!skuId 为 【{}】的索引不存在!", skuId); - } - } - } else { + public void deleteEsGoodsPromotionByPromotionKey(String promotionsKey) { + ThreadUtil.execAsync(() -> { + BulkRequest bulkRequest = new BulkRequest(); for (EsGoodsIndex goodsIndex : this.goodsIndexRepository.findAll()) { - UpdateRequest updateRequest = this.removePromotionByPromotionId(goodsIndex, promotionId); + UpdateRequest updateRequest = this.removePromotionByPromotionKey(goodsIndex, promotionsKey); if (updateRequest != null) { bulkRequest.add(updateRequest); } } - } - this.executeBulkUpdateRequest(bulkRequest); - + this.executeBulkUpdateRequest(bulkRequest); + }); } /** * 从索引中删除指定促销活动id的促销活动 * - * @param goodsIndex 索引 - * @param promotionId 促销活动id + * @param goodsIndex 索引 + * @param promotionsKey 促销活动key */ - private UpdateRequest removePromotionByPromotionId(EsGoodsIndex goodsIndex, String promotionId) { - Map promotionMap = goodsIndex.getPromotionMap(); + private UpdateRequest removePromotionByPromotionKey(EsGoodsIndex goodsIndex, String promotionsKey) { + Map promotionMap = goodsIndex.getOriginPromotionMap(); if (promotionMap != null && !promotionMap.isEmpty()) { //如果存在同促销ID的活动删除 - List collect = promotionMap.keySet().stream().filter(i -> i.split("-")[1].equals(promotionId)).collect(Collectors.toList()); - collect.forEach(promotionMap::remove); - goodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(promotionMap)); - return this.getGoodsIndexPromotionUpdateRequest(goodsIndex.getId(), promotionMap); + Map filterPromotionMap = promotionMap.entrySet().stream().filter(i -> !i.getKey().equals(promotionsKey)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return this.getGoodsIndexPromotionUpdateRequest(goodsIndex.getId(), filterPromotionMap); } return null; } @@ -530,7 +651,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements public void cleanInvalidPromotion() { Iterable all = goodsIndexRepository.findAll(); for (EsGoodsIndex goodsIndex : all) { - Map promotionMap = goodsIndex.getPromotionMap(); + Map promotionMap = goodsIndex.getOriginPromotionMap(); //获取商品索引 if (promotionMap != null && !promotionMap.isEmpty()) { //促销不为空则进行清洗 @@ -566,7 +687,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements //如果商品索引不为空,返回促销信息,否则返回空 if (goodsIndex != null) { - Map promotionMap = goodsIndex.getPromotionMap(); + Map promotionMap = goodsIndex.getOriginPromotionMap(); if (promotionMap == null || promotionMap.isEmpty()) { return new HashMap<>(16); } @@ -631,11 +752,13 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements private UpdateRequest updateGoodsIndexPromotion(EsGoodsIndex goodsIndex, String key, BasePromotions promotion) { Map promotionMap; //数据非空处理,如果空给一个新的信息 - if (goodsIndex.getPromotionMap() == null || goodsIndex.getPromotionMap().isEmpty()) { + if (goodsIndex.getOriginPromotionMap() == null || goodsIndex.getOriginPromotionMap().isEmpty()) { promotionMap = new HashMap<>(1); } else { - promotionMap = goodsIndex.getPromotionMap(); + promotionMap = goodsIndex.getOriginPromotionMap(); } +// log.info("ES修改商品活动索引-原商品索引信息:{}", goodsIndex); +// log.info("ES修改商品活动索引-原商品索引活动信息:{}", promotionMap); //如果活动已结束 if (promotion.getPromotionStatus().equals(PromotionsStatusEnum.END.name()) || promotion.getPromotionStatus().equals(PromotionsStatusEnum.CLOSE.name())) {//如果存在活动 //删除活动 @@ -643,6 +766,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } else { promotionMap.put(key, promotion); } +// log.info("ES修改商品活动索引-过滤后商品索引活动信息:{}", promotionMap); return this.getGoodsIndexPromotionUpdateRequest(goodsIndex.getId(), promotionMap); } @@ -656,7 +780,8 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements UpdateRequest updateRequest = new UpdateRequest(); updateRequest.index(getIndexName()); updateRequest.id(id); - updateRequest.retryOnConflict(5); + updateRequest.retryOnConflict(3); +// updateRequest.version(promotionMap.size()); Map params = new HashMap<>(); params.put("promotionMap", JSONUtil.toJsonStr(promotionMap)); Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.promotionMapJson=params.promotionMap;", params); @@ -712,63 +837,35 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } - /** - * 将商品关键字入库 - * - * @param words 商品关键字 - */ - private void wordsToDb(String words) { - if (CharSequenceUtil.isEmpty(words)) { - return; - } - try { - //是否有重复 - GoodsWords entity = goodsWordsService.getOne(new LambdaQueryWrapper().eq(GoodsWords::getWords, words)); - if (entity == null) { - GoodsWords goodsWords = new GoodsWords(); - goodsWords.setWords(words); - goodsWords.setWholeSpell(PinyinUtil.getPinyin(words, "")); - goodsWords.setAbbreviate(PinyinUtil.getFirstLetter(words, "")); - goodsWords.setType(GoodsWordsTypeEnum.SYSTEM.name()); - goodsWords.setSort(0); - goodsWordsService.save(goodsWords); - } - } catch (MyBatisSystemException me) { - log.error(words + "关键字已存在!"); - } catch (Exception e) { - log.error("关键字入库异常!", e); - } - } - private String getIndexName() { //索引名称拼接 return elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; } - private EsGoodsIndex wrapperEsGoodsIndex(GoodsSku goodsSku, Goods goods) { + private EsGoodsIndex wrapperEsGoodsIndex(GoodsSkuDTO goodsSku) { EsGoodsIndex index = new EsGoodsIndex(goodsSku); //商品参数索引 - if (goods.getParams() != null && !goods.getParams().isEmpty()) { - List goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class); + if (CharSequenceUtil.isNotEmpty(goodsSku.getParams())) { + List goodsParamDTOS = JSONUtil.toList(goodsSku.getParams(), GoodsParamsDTO.class); index = new EsGoodsIndex(goodsSku, goodsParamDTOS); } //商品分类索引 - if (goods.getCategoryPath() != null) { - List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(","))); + if (goodsSku.getCategoryPath() != null) { + List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goodsSku.getCategoryPath().split(","))); if (!categories.isEmpty()) { index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ",")); } } //商品品牌索引 - Brand brand = brandService.getById(goods.getBrandId()); + Brand brand = brandService.getById(goodsSku.getBrandId()); if (brand != null) { index.setBrandName(brand.getName()); index.setBrandUrl(brand.getLogo()); } //店铺分类索引 - if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) { - List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(","))); + if (goodsSku.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goodsSku.getStoreCategoryPath())) { + List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goodsSku.getStoreCategoryPath().split(","))); if (!storeGoodsLabels.isEmpty()) { index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ",")); } @@ -778,18 +875,4 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements index.setPromotionMapJson(JSONUtil.toJsonStr(goodsCurrentPromotionMap)); return index; } - - private ActionListener actionListener() { - return new ActionListener() { - @Override - public void onResponse(BulkByScrollResponse bulkByScrollResponse) { - log.info("UpdateByQueryResponse: {}", bulkByScrollResponse); - } - - @Override - public void onFailure(Exception e) { - log.error("UpdateByQueryRequestFailure: ", e); - } - }; - } } diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java index ec9e3391..463cf50d 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java @@ -11,10 +11,8 @@ import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; 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.entity.dto.HotWordsDTO; import cn.lili.modules.search.entity.dto.ParamOptions; import cn.lili.modules.search.entity.dto.SelectorOptions; -import cn.lili.modules.search.service.EsGoodsIndexService; import cn.lili.modules.search.service.EsGoodsSearchService; import com.alibaba.druid.util.StringUtils; import lombok.extern.slf4j.Slf4j; @@ -27,7 +25,6 @@ import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.functionscore.FieldValueFactorFunctionBuilder; import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; -import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder; import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; import org.elasticsearch.search.aggregations.*; import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested; @@ -36,16 +33,14 @@ import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHitSupport; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.SearchPage; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Service; import java.util.*; @@ -60,6 +55,9 @@ import java.util.*; @Service public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { + // 最小分词匹配 + private static final String MINIMUM_SHOULD_MATCH = "20%"; + private static final String ATTR_PATH = "attrList"; private static final String ATTR_VALUE = "attrList.value"; private static final String ATTR_NAME = "attrList.name"; @@ -73,11 +71,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { * ES */ @Autowired - @Qualifier("elasticsearchRestTemplate") - private ElasticsearchRestTemplate restTemplate; - - @Autowired - private EsGoodsIndexService esGoodsIndexService; + private ElasticsearchOperations restTemplate; /** * 缓存 */ @@ -86,16 +80,12 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { @Override public SearchPage searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo) { - boolean exists = restTemplate.indexOps(EsGoodsIndex.class).exists(); - if (!exists) { - esGoodsIndexService.init(); - } - if (CharSequenceUtil.isNotEmpty(searchDTO.getKeyword())) { + if (CharSequenceUtil.isNotBlank(searchDTO.getKeyword())) { cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), searchDTO.getKeyword()); } NativeSearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder(searchDTO, pageVo); NativeSearchQuery searchQuery = searchQueryBuilder.build(); - log.info("searchGoods DSL:{}", searchQuery.getQuery()); + log.debug("searchGoods DSL:{}", searchQuery.getQuery()); SearchHits search = restTemplate.search(searchQuery, EsGoodsIndex.class); for (int i = 0; i < search.getSearchHits().size() ; i++){ if (search.getSearchHits().get(i).getContent().getSmall().contains("fuluapiossproductnew.oss-cn-hangzhou.aliyuncs.com")){ @@ -108,38 +98,6 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { return SearchHitSupport.searchPageFor(search, searchQuery.getPageable()); } - @Override - public List getHotWords(Integer count) { - if (count == null) { - count = 0; - } - List hotWords = new ArrayList<>(); - // redis 排序中,下标从0开始,所以这里需要 -1 处理 - count = count - 1; - Set> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count); - if (set == null || set.isEmpty()) { - return new ArrayList<>(); - } - for (ZSetOperations.TypedTuple defaultTypedTuple : set) { - hotWords.add(Objects.requireNonNull(defaultTypedTuple.getValue()).toString()); - } - return hotWords; - } - - @Override - public void setHotWords(HotWordsDTO hotWords) { - cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), hotWords.getKeywords(), hotWords.getPoint()); - } - - /** - * 删除热门关键词 - * - * @param keywords 热词 - */ - @Override - public void deleteHotWords(String keywords) { - cache.zRemove(CachePrefix.HOT_WORD.getPrefix(), keywords); - } @Override public EsGoodsRelatedInfo getSelector(EsGoodsSearchDTO goodsSearch, PageVO pageVo) { @@ -161,7 +119,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { NativeSearchQuery searchQuery = builder.build(); SearchHits search = restTemplate.search(searchQuery, EsGoodsIndex.class); - log.info("getSelector DSL:{}", searchQuery.getQuery()); + log.debug("getSelector DSL:{}", searchQuery.getQuery()); Map aggregationMap = Objects.requireNonNull(search.getAggregations()).getAsMap(); return convertToEsGoodsRelatedInfo(aggregationMap, goodsSearch); } @@ -248,7 +206,8 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { String brandName = ""; if (brandBuckets.get(i).getAggregations() != null && brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME) != null) { - brandName = this.getAggregationsBrandOptions(brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME)); + ParsedStringTerms aggregation = brandBuckets.get(i).getAggregations().get(ATTR_BRAND_NAME); + brandName = this.getAggregationsBrandOptions(aggregation); if (StringUtils.isEmpty(brandName)) { continue; } @@ -258,7 +217,8 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { if (brandUrlBuckets != null && !brandUrlBuckets.isEmpty() && brandUrlBuckets.get(i).getAggregations() != null && brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL) != null) { - brandUrl = this.getAggregationsBrandOptions(brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL)); + ParsedStringTerms aggregation = brandUrlBuckets.get(i).getAggregations().get(ATTR_BRAND_URL); + brandUrl = this.getAggregationsBrandOptions(aggregation); if (StringUtils.isEmpty(brandUrl)) { continue; } @@ -403,6 +363,9 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { //对查询条件进行处理 this.commonSearch(filterBuilder, searchDTO); + //智能推荐 + this.recommended(filterBuilder, searchDTO); + //未上架的商品不显示 filterBuilder.must(QueryBuilders.matchQuery("marketEnable", GoodsStatusEnum.UPPER.name())); //待审核和审核不通过的商品不显示 @@ -411,13 +374,10 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { //关键字检索 if (CharSequenceUtil.isEmpty(searchDTO.getKeyword())) { - List filterFunctionBuilders = new ArrayList<>(); - GaussDecayFunctionBuilder skuNoScore = ScoreFunctionBuilders.gaussDecayFunction("skuSource", 100, 10).setWeight(10); - FunctionScoreQueryBuilder.FilterFunctionBuilder skuNoBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchAllQuery(), skuNoScore); - filterFunctionBuilders.add(skuNoBuilder); + List filterFunctionBuilders = this.buildFunctionSearch(); FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()]; filterFunctionBuilders.toArray(builders); - FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders) + FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(QueryBuilders.matchAllQuery(), builders) .scoreMode(FunctionScoreQuery.ScoreMode.SUM) .setMinScore(2); //聚合搜索则将结果放入过滤条件 @@ -441,6 +401,37 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { return nativeSearchQueryBuilder; } + /** + * 商品推荐 + * + * @param filterBuilder + * @param searchDTO + */ + private void recommended(BoolQueryBuilder filterBuilder, EsGoodsSearchDTO searchDTO) { + + String currentGoodsId = searchDTO.getCurrentGoodsId(); + if (CharSequenceUtil.isEmpty(currentGoodsId)) { + return; + } + + //排除当前商品 + filterBuilder.mustNot(QueryBuilders.matchQuery("id", currentGoodsId)); + + //查询当前浏览商品的索引信息 + EsGoodsIndex esGoodsIndex = restTemplate.get(currentGoodsId, EsGoodsIndex.class); + if (esGoodsIndex == null) { + return; + } + //推荐与当前浏览商品相同一个二级分类下的商品 + String categoryPath = esGoodsIndex.getCategoryPath(); + if (CharSequenceUtil.isNotEmpty(categoryPath)) { + //匹配二级分类 + String substring = categoryPath.substring(0, categoryPath.lastIndexOf(",")); + filterBuilder.must(QueryBuilders.wildcardQuery("categoryPath", substring + "*")); + } + + } + /** * 查询属性处理 * @@ -542,46 +533,40 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { * @param keyword 关键字 */ private void keywordSearch(BoolQueryBuilder filterBuilder, String keyword) { - List filterFunctionBuilders = new ArrayList<>(); - if (keyword.contains(" ")) { - for (String s : keyword.split(" ")) { - filterFunctionBuilders.addAll(this.buildKeywordSearch(s)); - } - } else { - filterFunctionBuilders = this.buildKeywordSearch(keyword); - } + + List filterFunctionBuilders = this.buildFunctionSearch(); + + //分词匹配 + // operator 为 AND 时 需全部分词匹配。为 OR 时 需配置 minimumShouldMatch(最小分词匹配数)不设置默认为1 + MatchQueryBuilder goodsNameMatchQuery = QueryBuilders.matchQuery("goodsName", keyword).operator(Operator.OR).minimumShouldMatch(MINIMUM_SHOULD_MATCH); FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()]; filterFunctionBuilders.toArray(builders); - FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders) + FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(goodsNameMatchQuery, builders) .scoreMode(FunctionScoreQuery.ScoreMode.SUM) .setMinScore(2); //聚合搜索则将结果放入过滤条件 filterBuilder.must(functionScoreQueryBuilder); + filterBuilder.should(QueryBuilders.boolQuery().should(QueryBuilders.matchPhraseQuery("goodsName", keyword).boost(10))); } /** * 构造关键字查询 * - * @param keyword 关键字 * @return 构造查询的集合 */ - private List buildKeywordSearch(String keyword) { + private List buildFunctionSearch() { List filterFunctionBuilders = new ArrayList<>(); - MatchQueryBuilder goodsNameQuery = QueryBuilders.matchQuery("goodsName", keyword).operator(Operator.AND); - //分词匹配 - filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery, - ScoreFunctionBuilders.weightFactorFunction(10))); - //属性匹配 - filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.wildcardQuery(ATTR_VALUE, "*" + keyword + "*"), ScoreMode.None), - ScoreFunctionBuilders.weightFactorFunction(8))); - GaussDecayFunctionBuilder skuNoScore = ScoreFunctionBuilders.gaussDecayFunction("skuSource", 100, 10).setWeight(7); - FunctionScoreQueryBuilder.FilterFunctionBuilder skuNoBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery, skuNoScore); +// GaussDecayFunctionBuilder skuNoScore = ScoreFunctionBuilders.gaussDecayFunction("skuSource", 100, 10).setWeight(2); +// FunctionScoreQueryBuilder.FilterFunctionBuilder skuNoBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(skuNoScore); +// filterFunctionBuilders.add(skuNoBuilder); + FieldValueFactorFunctionBuilder skuNoScore = ScoreFunctionBuilders.fieldValueFactorFunction("skuSource").modifier(FieldValueFactorFunction.Modifier.LOG1P).setWeight(3); + FunctionScoreQueryBuilder.FilterFunctionBuilder skuNoBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(skuNoScore); filterFunctionBuilders.add(skuNoBuilder); - FieldValueFactorFunctionBuilder buyCountScore = ScoreFunctionBuilders.fieldValueFactorFunction("buyCount").modifier(FieldValueFactorFunction.Modifier.LOG1P).setWeight(6); - FunctionScoreQueryBuilder.FilterFunctionBuilder buyCountBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(goodsNameQuery, buyCountScore); + FieldValueFactorFunctionBuilder buyCountScore = ScoreFunctionBuilders.fieldValueFactorFunction("buyCount").modifier(FieldValueFactorFunction.Modifier.LOG1P).setWeight(3); + FunctionScoreQueryBuilder.FilterFunctionBuilder buyCountBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(buyCountScore); filterFunctionBuilders.add(buyCountBuilder); return filterFunctionBuilders; } diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsHistoryServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsHistoryServiceImpl.java new file mode 100644 index 00000000..c3091ef7 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsHistoryServiceImpl.java @@ -0,0 +1,53 @@ +package cn.lili.modules.search.serviceimpl; + +import cn.lili.common.utils.DateUtil; +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.dto.HotWordsSearchParams; +import cn.lili.modules.search.mapper.HotWordsHistoryMapper; +import cn.lili.modules.search.service.HotWordsHistoryService; +import cn.lili.modules.search.service.HotWordsService; +import cn.lili.modules.statistics.entity.enums.SearchTypeEnum; +import cn.lili.modules.statistics.util.StatisticsDateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 历史热词 + * + * @author paulG + * @since 2020/10/15 + **/ +@Service +public class HotWordsHistoryServiceImpl extends ServiceImpl implements HotWordsHistoryService { + + @Autowired + private HotWordsService hotWordsService; + + @Override + public List statistics(HotWordsSearchParams hotWordsSearchParams) { + if (hotWordsSearchParams.getSearchType().equals(SearchTypeEnum.TODAY.name())) { + return hotWordsService.getHotWordsVO(hotWordsSearchParams.getTop()); + } + QueryWrapper queryWrapper = hotWordsSearchParams.queryWrapper(); + + queryWrapper.groupBy("keywords"); + queryWrapper.orderByDesc("score"); + queryWrapper.last("limit " + hotWordsSearchParams.getTop()); + List list = baseMapper.statistics(queryWrapper); + return list; + } + + @Override + public List queryByDay(Date queryTime) { + QueryWrapper queryWrapper = new QueryWrapper(); + + Date[] dates = StatisticsDateUtil.getDateArray(queryTime); + queryWrapper.between("create_time", dates[0], dates[1]); + return list(queryWrapper); + } + +} diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsServiceImpl.java new file mode 100644 index 00000000..d036f96e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/HotWordsServiceImpl.java @@ -0,0 +1,96 @@ +package cn.lili.modules.search.serviceimpl; + +import cn.lili.cache.Cache; +import cn.lili.cache.CachePrefix; +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.dto.HotWordsDTO; +import cn.lili.modules.search.mapper.HotWordsHistoryMapper; +import cn.lili.modules.search.service.HotWordsService; +import cn.lili.modules.system.entity.dos.Setting; +import cn.lili.modules.system.entity.enums.SettingEnum; +import cn.lili.modules.system.service.SettingService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * HotWordsServiceImpl + * + * @author Chopper + * @version v1.0 + * 2022-04-14 09:35 + */ +@Slf4j +@Service +public class HotWordsServiceImpl implements HotWordsService { + + /** + * 缓存 + */ + @Autowired + private Cache cache; + + @Override + public List getHotWords(Integer count) { + if (count == null) { + count = 0; + } + List hotWords = new ArrayList<>(); + // redis 排序中,下标从0开始,所以这里需要 -1 处理 + count = count - 1; + Set> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count); + if (set == null || set.isEmpty()) { + return new ArrayList<>(); + } + for (ZSetOperations.TypedTuple defaultTypedTuple : set) { + hotWords.add(Objects.requireNonNull(defaultTypedTuple.getValue()).toString()); + } + return hotWords; + } + + @Override + public List getHotWordsVO(Integer count) { + if (count == null) { + count = 50; + } + List hotWords = new ArrayList<>(); + // redis 排序中,下标从0开始,所以这里需要 -1 处理 + count = count - 1; + Set> set = cache.reverseRangeWithScores(CachePrefix.HOT_WORD.getPrefix(), count); + if (set == null || set.isEmpty()) { + return new ArrayList<>(); + } + for (ZSetOperations.TypedTuple defaultTypedTuple : set) { + try { + hotWords.add(new HotWordsHistory(defaultTypedTuple.getValue().toString(), + defaultTypedTuple.getScore().intValue())); + } catch (Exception e) { + log.error("读取热词错误", e); + } + + } + + + Collections.sort(hotWords); + return hotWords; + } + + @Override + public void setHotWords(HotWordsDTO hotWords) { + cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), hotWords.getKeywords(), hotWords.getPoint()); + } + + /** + * 删除热门关键词 + * + * @param keywords 热词 + */ + @Override + public void deleteHotWords(String keywords) { + cache.zRemove(CachePrefix.HOT_WORD.getPrefix(), keywords); + } + +} diff --git a/framework/src/main/java/cn/lili/modules/sms/entity/dos/SmsReach.java b/framework/src/main/java/cn/lili/modules/sms/entity/dos/SmsReach.java index 09ec8dfa..33ff2db6 100644 --- a/framework/src/main/java/cn/lili/modules/sms/entity/dos/SmsReach.java +++ b/framework/src/main/java/cn/lili/modules/sms/entity/dos/SmsReach.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.EqualsAndHashCode; import org.springframework.data.annotation.CreatedDate; import org.springframework.format.annotation.DateTimeFormat; @@ -23,8 +24,11 @@ import java.util.Date; @Data @TableName("li_sms_reach") @ApiModel(value = "短信任务") +@EqualsAndHashCode(callSuper = true) public class SmsReach extends BaseIdEntity { + private static final long serialVersionUID = -8106666482841131277L; + @ApiModelProperty(value = "签名名称", required = true) private String signName; diff --git a/framework/src/main/java/cn/lili/modules/sms/impl/SmsUtilAliImplService.java b/framework/src/main/java/cn/lili/modules/sms/impl/SmsUtilAliImplService.java index 87c785c3..513748c3 100644 --- a/framework/src/main/java/cn/lili/modules/sms/impl/SmsUtilAliImplService.java +++ b/framework/src/main/java/cn/lili/modules/sms/impl/SmsUtilAliImplService.java @@ -122,7 +122,9 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { //如果是测试模式 默认验证码 6个1 if (systemSettingProperties.getIsTestModel()) { code = "111111"; + log.info("测试模式 - 接收手机:{},验证码:{}",mobile,code); } else { + log.info("接收手机:{},验证码:{}",mobile,code); //发送短信 this.sendSmsCode(smsSetting.getSignName(), mobile, params, templateCode); } @@ -154,6 +156,9 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { .setTemplateParam(JSONUtil.toJsonStr(param)); try { SendSmsResponse response = client.sendSms(sendSmsRequest); + if (!("OK").equals(response.getBody().getCode())) { + throw new ServiceException(response.getBody().getMessage()); + } } catch (Exception e) { log.error("发送短信错误", e); } diff --git a/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OnlineMemberVO.java b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OnlineMemberVO.java index fc66d9da..bd20847b 100644 --- a/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OnlineMemberVO.java +++ b/framework/src/main/java/cn/lili/modules/statistics/entity/vo/OnlineMemberVO.java @@ -3,6 +3,7 @@ package cn.lili.modules.statistics.entity.vo; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.Date; @@ -14,6 +15,7 @@ import java.util.Date; */ @Data @AllArgsConstructor +@NoArgsConstructor public class OnlineMemberVO { /** @@ -27,4 +29,9 @@ public class OnlineMemberVO { */ private Integer num; + /** + * 上一周期在线会员人数 + */ + private Integer lastNum; + } diff --git a/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/PlatformViewServiceImpl.java b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/PlatformViewServiceImpl.java index 9b0e69c7..5d824068 100644 --- a/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/PlatformViewServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/statistics/serviceimpl/PlatformViewServiceImpl.java @@ -131,7 +131,7 @@ public class PlatformViewServiceImpl extends ServiceImpl { * @param queryWrapper 查询条件 * @return 结算单 */ - @Select("SELECT SUM( final_price ) AS orderPrice,SUM( commission_price ) AS commissionPrice" + - ",SUM( distribution_rebate ) AS distributionCommission,SUM( site_coupon_commission ) AS siteCouponCommission" + - ",SUM( point_settlement_price ) AS pointSettlementPrice " + - ",SUM( kanjia_settlement_price ) AS kanjiaSettlementPrice " + - ",SUM( bill_price ) AS billPrice " + + @Select("SELECT IFNULL(SUM( final_price ),0) AS orderPrice,IFNULL(SUM( commission_price ),0) AS commissionPrice" + + ",IFNULL(SUM( distribution_rebate ),0) AS distributionCommission,IFNULL(SUM( site_coupon_commission ),0) AS siteCouponCommission" + + ",IFNULL(SUM( point_settlement_price ),0) AS pointSettlementPrice " + + ",IFNULL(SUM( kanjia_settlement_price ),0) AS kanjiaSettlementPrice " + + ",IFNULL(SUM( bill_price ),0) AS billPrice " + "FROM li_store_flow ${ew.customSqlSegment}") Bill getOrderBill(@Param(Constants.WRAPPER) QueryWrapper queryWrapper); @@ -49,8 +49,8 @@ public interface BillMapper extends BaseMapper { * @param queryWrapper 查询条件 * @return 结算单 */ - @Select("SELECT SUM( final_price ) AS refundPrice,SUM( commission_price ) AS refundCommissionPrice" + - ",SUM( distribution_rebate ) AS distributionRefundCommission,SUM( site_coupon_commission ) AS siteCouponRefundCommission" + - ",SUM( bill_price ) AS billPrice FROM li_store_flow ${ew.customSqlSegment}") + @Select("SELECT IFNULL(SUM( final_price ),0) AS refundPrice,IFNULL(SUM( commission_price ),0) AS refundCommissionPrice" + + ",IFNULL(SUM( distribution_rebate ),0) AS distributionRefundCommission,IFNULL(SUM( site_coupon_commission ),0) AS siteCouponRefundCommission" + + ",IFNULL(SUM( final_price ),0) AS billPrice FROM li_store_flow ${ew.customSqlSegment}") Bill getRefundBill(@Param(Constants.WRAPPER) QueryWrapper queryWrapper); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/store/mapper/StoreDetailMapper.java b/framework/src/main/java/cn/lili/modules/store/mapper/StoreDetailMapper.java index 079370ff..20ce9e1c 100644 --- a/framework/src/main/java/cn/lili/modules/store/mapper/StoreDetailMapper.java +++ b/framework/src/main/java/cn/lili/modules/store/mapper/StoreDetailMapper.java @@ -80,7 +80,8 @@ public interface StoreDetailMapper extends BaseMapper { @Select("SELECT store_id,settlement_day FROM li_store_detail " + "WHERE settlement_cycle LIKE concat(#{day},',%') " + "OR settlement_cycle LIKE concat('%,',#{day},',%') " + - "OR settlement_cycle LIKE concat('%,',#{day})") + "OR settlement_cycle LIKE concat('%,',#{day})"+ + "OR settlement_cycle = #{day}") List getSettlementStore(int day); /** diff --git a/framework/src/main/java/cn/lili/modules/store/service/StoreService.java b/framework/src/main/java/cn/lili/modules/store/service/StoreService.java index 95632b0d..28693e53 100644 --- a/framework/src/main/java/cn/lili/modules/store/service/StoreService.java +++ b/framework/src/main/java/cn/lili/modules/store/service/StoreService.java @@ -106,8 +106,9 @@ public interface StoreService extends IService { * 更新店铺商品数量 * * @param storeId 店铺ID + * @param num 商品数量 */ - void updateStoreGoodsNum(String storeId); + void updateStoreGoodsNum(String storeId, Long num); /** * 更新店铺收藏数量 diff --git a/framework/src/main/java/cn/lili/modules/store/serviceimpl/BillServiceImpl.java b/framework/src/main/java/cn/lili/modules/store/serviceimpl/BillServiceImpl.java index f5eecdb6..8d081926 100644 --- a/framework/src/main/java/cn/lili/modules/store/serviceimpl/BillServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/store/serviceimpl/BillServiceImpl.java @@ -68,14 +68,18 @@ public class BillServiceImpl extends ServiceImpl implements Bi StoreDetailVO store = storeDetailService.getStoreDetailVO(storeId); Bill bill = new Bill(); - //结算基础信息 + /** + * @TODO 结算单基础信息 + */ bill.setStartTime(startTime); - bill.setEndTime(DateUtil.yesterday()); + bill.setEndTime(endTime); bill.setBillStatus(BillStatusEnum.OUT.name()); bill.setStoreId(storeId); bill.setStoreName(store.getStoreName()); - //设置结算信息 + /** + * @TODO 结算单基础信息 + */ bill.setBankAccountName(store.getSettlementBankAccountName()); bill.setBankAccountNumber(store.getSettlementBankAccountNum()); bill.setBankCode(store.getSettlementBankJointName()); @@ -84,40 +88,51 @@ public class BillServiceImpl extends ServiceImpl implements Bi //店铺结算单号 bill.setSn(SnowFlake.createStr("B")); - //入账结算信息 - Bill orderBill = this.baseMapper.getOrderBill(new QueryWrapper() - .eq("store_id", storeId) - .eq("flow_type", FlowTypeEnum.PAY.name()) - .between("create_time", startTime, endTime)); - double orderPrice = 0D; - if (orderBill != null) { - bill.setOrderPrice(orderBill.getOrderPrice()); - bill.setCommissionPrice(orderBill.getCommissionPrice()); - bill.setDistributionCommission(orderBill.getDistributionCommission()); - bill.setSiteCouponCommission(orderBill.getSiteCouponCommission()); - bill.setPointSettlementPrice(orderBill.getPointSettlementPrice()); - bill.setKanjiaSettlementPrice(orderBill.getKanjiaSettlementPrice()); - //入账金额=订单金额 - orderPrice = orderBill.getBillPrice(); - } - - //退款结算信息 - Bill refundBill = this.baseMapper.getRefundBill(new QueryWrapper() - .eq("store_id", storeId) - .eq("flow_type", FlowTypeEnum.REFUND.name()) - .between("create_time", startTime, endTime)); + Bill refundBill = this.baseMapper.getRefundBill(new QueryWrapper().eq("store_id", storeId).eq("flow_type", FlowTypeEnum.REFUND.name()).between("create_time", startTime, endTime)); + //店铺退款金额 Double refundPrice = 0D; if (refundBill != null) { - bill.setRefundPrice(refundBill.getRefundPrice()); - bill.setRefundCommissionPrice(refundBill.getRefundCommissionPrice()); - bill.setDistributionRefundCommission(refundBill.getDistributionRefundCommission()); - bill.setSiteCouponRefundCommission(refundBill.getSiteCouponRefundCommission()); - refundPrice = refundBill.getBillPrice(); + //退单金额 + bill.setRefundPrice(refundBill.getRefundPrice() != null ? refundBill.getRefundPrice() : 0D); + //退单产生退还佣金金额 + bill.setRefundCommissionPrice(refundBill.getRefundCommissionPrice() != null ? refundBill.getRefundCommissionPrice() : 0D); + //分销订单退还,返现佣金返还 + bill.setDistributionRefundCommission(refundBill.getDistributionRefundCommission() != null ? refundBill.getDistributionRefundCommission() : 0D); + //退货平台优惠券补贴返还 + bill.setSiteCouponRefundCommission(refundBill.getSiteCouponRefundCommission() != null ? refundBill.getSiteCouponRefundCommission() : 0D); + //退款金额=店铺最终退款结算金额 + refundPrice = refundBill.getBillPrice() != null ? refundBill.getBillPrice() : 0D; } - //最终结算金额=入款结算金额-退款结算金额 - Double finalPrice = CurrencyUtil.sub(orderPrice, refundPrice); + + /** + * @TODO 入账结算信息 + */ + Bill orderBill = this.baseMapper.getOrderBill(new QueryWrapper().eq("store_id", storeId).eq("flow_type", FlowTypeEnum.PAY.name()).between("create_time", startTime, endTime)); + //店铺入款结算金额 + double orderPrice = 0D; + + if (orderBill != null) { + //结算周期内订单付款总金额 + bill.setOrderPrice(orderBill.getOrderPrice() != null ? orderBill.getOrderPrice() : 0D); + //平台收取佣金 + bill.setCommissionPrice(orderBill.getCommissionPrice() != null ? orderBill.getCommissionPrice() : 0D); + //分销返现支出 + bill.setDistributionCommission(orderBill.getDistributionCommission() != null ? orderBill.getDistributionCommission() : 0D); + //平台优惠券补贴 + bill.setSiteCouponCommission(orderBill.getSiteCouponCommission() != null ? orderBill.getSiteCouponCommission() : 0D); + //积分商品结算价格 + bill.setPointSettlementPrice(orderBill.getPointSettlementPrice() != null ? orderBill.getPointSettlementPrice() : 0D); + //砍价商品结算价格 + bill.setKanjiaSettlementPrice(orderBill.getKanjiaSettlementPrice() != null ? orderBill.getKanjiaSettlementPrice() : 0D); + + //入款结算金额= 店铺支付结算金额 + 平台优惠券补贴 + 分销订单退还,返现佣金返还+退单产生退还佣金金额 + orderPrice = CurrencyUtil.add(orderBill.getBillPrice() == null ? 0 : orderBill.getBillPrice(), bill.getSiteCouponCommission() == null ? 0 : bill.getSiteCouponCommission(), bill.getDistributionRefundCommission() == null ? 0 : bill.getDistributionRefundCommission(), bill.getRefundCommissionPrice() == null ? 0 : bill.getRefundCommissionPrice()); + } + //最终结算金额=入款结算金额-退款结算金额-退货平台优惠券补贴返还 + Double finalPrice = CurrencyUtil.sub(orderPrice, refundPrice, bill.getSiteCouponRefundCommission() == null ? 0 : bill.getSiteCouponRefundCommission()); + //店铺最终结算金额=最终结算金额 bill.setBillPrice(finalPrice); //添加结算单 @@ -251,9 +266,7 @@ public class BillServiceImpl extends ServiceImpl implements Bi writer.setColumnWidth(12, 20); - List storeFlowRefundDownloadVOList = storeFlowService.getStoreFlowRefundDownloadVO( - StoreFlowQueryDTO.builder().type(FlowTypeEnum.REFUND.name()).bill(bill).build() - ); + List storeFlowRefundDownloadVOList = storeFlowService.getStoreFlowRefundDownloadVO(StoreFlowQueryDTO.builder().type(FlowTypeEnum.REFUND.name()).bill(bill).build()); writer.write(storeFlowRefundDownloadVOList, true); ServletOutputStream out = null; diff --git a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java index 2a3c78c1..00bd103f 100644 --- a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java @@ -3,6 +3,8 @@ package cn.lili.modules.store.serviceimpl; import cn.hutool.core.date.DateTime; import cn.hutool.core.map.MapUtil; import cn.hutool.json.JSONUtil; +import cn.lili.cache.Cache; +import cn.lili.cache.CachePrefix; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; @@ -62,9 +64,17 @@ public class StoreDetailServiceImpl extends ServiceImpl implements @Autowired private StoreDetailService storeDetailService; + + @Autowired + private Cache cache; + @Override public IPage findByConditionPage(StoreSearchParams storeSearchParams, PageVO page) { return this.baseMapper.getStoreList(PageUtil.initPage(page), storeSearchParams.queryWrapper()); @@ -153,6 +159,7 @@ public class StoreServiceImpl extends ServiceImpl implements storeDetailService.updateStoreGoodsInfo(store); } } + cache.remove(CachePrefix.STORE.getPrefix() + storeEditDTO.getStoreId()); return store; } @@ -228,7 +235,7 @@ public class StoreServiceImpl extends ServiceImpl implements //获取当前操作的店铺 Store store = getStoreByMember(); //如果没有申请过店铺,新增店铺 - if (!Optional.ofNullable(store).isPresent()) { + if (store != null) { AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser()); Member member = memberService.getById(authUser.getId()); store = new Store(member); @@ -239,12 +246,21 @@ public class StoreServiceImpl extends ServiceImpl implements BeanUtil.copyProperties(storeCompanyDTO, storeDetail); return storeDetailService.save(storeDetail); } else { + store = new Store(); BeanUtil.copyProperties(storeCompanyDTO, store); this.updateById(store); //判断是否存在店铺详情,如果没有则进行新建,如果存在则进行修改 StoreDetail storeDetail = storeDetailService.getStoreDetail(store.getId()); - BeanUtil.copyProperties(storeCompanyDTO, storeDetail); - return storeDetailService.updateById(storeDetail); + //如果店铺详情为空,则new ,否则复制对象,然后保存即可。 + if (storeDetail == null) { + storeDetail = new StoreDetail(); + storeDetail.setStoreId(store.getId()); + BeanUtil.copyProperties(storeCompanyDTO, storeDetail); + return storeDetailService.save(storeDetail); + } else { + BeanUtil.copyProperties(storeCompanyDTO, storeDetail); + return storeDetailService.updateById(storeDetail); + } } } @@ -285,12 +301,10 @@ public class StoreServiceImpl extends ServiceImpl implements } @Override - public void updateStoreGoodsNum(String storeId) { - //获取店铺已上架已审核通过商品数量 - long goodsNum = goodsService.countStoreGoodsNum(storeId); + public void updateStoreGoodsNum(String storeId, Long num) { //修改店铺商品数量 this.update(new LambdaUpdateWrapper() - .set(Store::getGoodsNum, goodsNum) + .set(Store::getGoodsNum, num) .eq(Store::getId, storeId)); } diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSetting.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSetting.java new file mode 100644 index 00000000..0b98d43b --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSetting.java @@ -0,0 +1,28 @@ +package cn.lili.modules.system.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 搜索热词 + * + * @author Bulbasaur + * @since 2021/5/16 11:10 下午 + */ +@Data +public class HotWordsSetting implements Serializable { + + //热词1-5,默认分数1-5 + + @ApiModelProperty(value = "热词默认配置") + private List hotWordsSettingItems = new ArrayList<>(); + + + @ApiModelProperty("每日保存数量") + private Integer saveNum; + +} diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSettingItem.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSettingItem.java new file mode 100644 index 00000000..41fa826c --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/HotWordsSettingItem.java @@ -0,0 +1,41 @@ +package cn.lili.modules.system.entity.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 积分签到设置 + * + * @author Chopper + * @since 2021-02-26 11:48 + */ +@Data +public class HotWordsSettingItem implements Comparable, Serializable { + + + @ApiModelProperty(value = "热词") + private String keywords; + + + @ApiModelProperty(value = "默认分数") + private Integer score; + + + public Integer getScore() { + if (score == null || score < 0) { + return 0; + } + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + @Override + public int compareTo(HotWordsSettingItem pointSettingItem) { + return pointSettingItem.getScore(); + } +} diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java index 80c5fd07..760c191c 100644 --- a/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java +++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java @@ -1,5 +1,7 @@ package cn.lili.modules.system.entity.dto; +import cn.lili.common.utils.StringUtils; +import cn.lili.modules.file.entity.enums.OssEnum; import lombok.Data; import java.io.Serializable; @@ -15,6 +17,12 @@ import java.io.Serializable; public class OssSetting implements Serializable { private static final long serialVersionUID = 2975271656230801861L; + + /** + * oss类型 + */ + private String type; + /** * 域名 */ @@ -35,4 +43,39 @@ public class OssSetting implements Serializable { * 密钥 */ private String accessKeySecret = ""; + + + /** + * minio服务地址 + */ + private String m_endpoint; + + /** + * minio 前端请求地址 + */ + private String m_frontUrl; + + /** + * minio用户名 + */ + private String m_accessKey; + + /** + * minio密码 + */ + private String m_secretKey; + + /** + * minio bucket名称 + */ + private String m_bucketName; + + + public String getType() { + //默认给阿里云oss存储类型 + if (StringUtils.isEmpty(type)) { + return OssEnum.ALI_OSS.name(); + } + return type; + } } diff --git a/framework/src/main/java/cn/lili/modules/system/entity/enums/SettingEnum.java b/framework/src/main/java/cn/lili/modules/system/entity/enums/SettingEnum.java index 304ad4e7..00d7b6cf 100644 --- a/framework/src/main/java/cn/lili/modules/system/entity/enums/SettingEnum.java +++ b/framework/src/main/java/cn/lili/modules/system/entity/enums/SettingEnum.java @@ -44,5 +44,7 @@ public enum SettingEnum { //支付宝支付设置 ALIPAY_PAYMENT, //微信支付设置 - WECHAT_PAYMENT; + WECHAT_PAYMENT, + //热词设置 + HOT_WORDS } diff --git a/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java b/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java index b3f1c16e..5cdf8698 100644 --- a/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java +++ b/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java @@ -19,9 +19,10 @@ public interface LogisticsService extends IService { * * @param logisticsId 物流公司ID * @param logisticsNo 单号 + * @param customerName 手机号后四位 * @return */ - Traces getLogistic(String logisticsId, String logisticsNo); + Traces getLogistic(String logisticsId, String logisticsNo, String customerName); /** * 获取已开启的物流公司列表 diff --git a/framework/src/main/java/cn/lili/modules/system/service/RegionService.java b/framework/src/main/java/cn/lili/modules/system/service/RegionService.java index 53261699..3696d7c3 100644 --- a/framework/src/main/java/cn/lili/modules/system/service/RegionService.java +++ b/framework/src/main/java/cn/lili/modules/system/service/RegionService.java @@ -36,6 +36,14 @@ public interface RegionService extends IService { @Cacheable(key = "#id") List getItem(String id); + /** + * 根据最后一级名称获取改所有上级地区id + * + * @param lastName 最后一级名称 + * @return 全部地区id + */ + String getItemByLastName(String lastName); + /** * 获取地址 * diff --git a/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java b/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java index e7b40f61..6dd2cbac 100644 --- a/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java @@ -43,9 +43,9 @@ public class LogisticsServiceImpl extends ServiceImpl params = new HashMap<>(8); params.put("RequestData", urlEncoder(requestData, "UTF-8")); params.put("EBusinessID", EBusinessID); diff --git a/framework/src/main/java/cn/lili/modules/system/serviceimpl/RegionServiceImpl.java b/framework/src/main/java/cn/lili/modules/system/serviceimpl/RegionServiceImpl.java index 5b29279d..cccf1860 100644 --- a/framework/src/main/java/cn/lili/modules/system/serviceimpl/RegionServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/system/serviceimpl/RegionServiceImpl.java @@ -61,6 +61,25 @@ public class RegionServiceImpl extends ServiceImpl impleme } } + /** + * 根据最后一级名称获取改所有上级地区id + * + * @param lastName 最后一级名称 + * @return 全部地区id + */ + @Override + public String getItemByLastName(String lastName) { + StringBuilder sql = new StringBuilder(); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(Region::getName, lastName); + Region region = this.getOne(lambdaQueryWrapper, false); + if (region != null) { + sql.append(region.getPath()).append(",").append(region.getId()); + return sql.toString().replace(",0,", ""); + } + return null; + } + @Override public List getItem(String id) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); @@ -73,9 +92,9 @@ public class RegionServiceImpl extends ServiceImpl impleme @Override public Map getRegion(String cityCode, String townName) { //获取地址信息 - Region region = this.baseMapper.selectOne(new QueryWrapper() + Region region = this.getOne(new QueryWrapper() .eq("city_code", cityCode) - .eq("name", townName)); + .eq("name", townName), false); if (region != null) { //获取它的层级关系 String path = region.getPath(); diff --git a/framework/src/main/java/cn/lili/modules/wallet/entity/dos/MemberWithdrawApply.java b/framework/src/main/java/cn/lili/modules/wallet/entity/dos/MemberWithdrawApply.java index 02aaf1eb..cf598ddf 100644 --- a/framework/src/main/java/cn/lili/modules/wallet/entity/dos/MemberWithdrawApply.java +++ b/framework/src/main/java/cn/lili/modules/wallet/entity/dos/MemberWithdrawApply.java @@ -1,5 +1,6 @@ package cn.lili.modules.wallet.entity.dos; +import cn.lili.modules.wallet.entity.enums.WithdrawStatusEnum; import cn.lili.mybatis.BaseEntity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; @@ -28,6 +29,9 @@ public class MemberWithdrawApply extends BaseEntity { @ApiModelProperty(value = "申请提现金额") private Double applyMoney; + /** + * @see WithdrawStatusEnum + */ @ApiModelProperty(value = "提现状态") private String applyStatus; diff --git a/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/MemberWalletServiceImpl.java b/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/MemberWalletServiceImpl.java index 87766492..be6f99ee 100644 --- a/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/MemberWalletServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/wallet/serviceimpl/MemberWalletServiceImpl.java @@ -84,7 +84,7 @@ public class MemberWalletServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("member_id", memberId); //执行查询 - MemberWallet memberWallet = this.baseMapper.selectOne(queryWrapper); + MemberWallet memberWallet = this.getOne(queryWrapper, false); //如果没有钱包,则创建钱包 if (memberWallet == null) { memberWallet = this.save(memberId, memberService.getById(memberId).getUsername()); @@ -168,8 +168,8 @@ public class MemberWalletServiceImpl extends ServiceImpl CurrencyUtil.sub(memberWallet.getMemberWallet(), memberWalletUpdateDTO.getMoney())) { - throw new ServiceException(ResultCode.WALLET_WITHDRAWAL_INSUFFICIENT); + if (0 > CurrencyUtil.sub(memberWallet.getMemberFrozenWallet(), memberWalletUpdateDTO.getMoney())) { + throw new ServiceException(ResultCode.WALLET_WITHDRAWAL_FROZEN_AMOUNT_INSUFFICIENT); } memberWallet.setMemberFrozenWallet(CurrencyUtil.sub(memberWallet.getMemberFrozenWallet(), memberWalletUpdateDTO.getMoney())); this.updateById(memberWallet); @@ -186,7 +186,7 @@ public class MemberWalletServiceImpl extends ServiceImpl().eq("member_id", memberId)); + MemberWallet memberWallet = this.getOne(new QueryWrapper().eq("member_id", memberId), false); //如果会员预存款信息不存在则同步重新建立预存款信息 if (memberWallet == null) { Member member = memberService.getById(memberId); diff --git a/framework/src/main/java/cn/lili/modules/wechat/entity/dos/WechatMessage.java b/framework/src/main/java/cn/lili/modules/wechat/entity/dos/WechatMessage.java index 5753b2e6..6441be30 100644 --- a/framework/src/main/java/cn/lili/modules/wechat/entity/dos/WechatMessage.java +++ b/framework/src/main/java/cn/lili/modules/wechat/entity/dos/WechatMessage.java @@ -1,5 +1,6 @@ package cn.lili.modules.wechat.entity.dos; +import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; import cn.lili.mybatis.BaseEntity; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; @@ -34,6 +35,9 @@ public class WechatMessage extends BaseEntity { @ApiModelProperty(value = "是否开启") private Boolean enable = true; + /** + * @see OrderStatusEnum + */ @ApiModelProperty("订单状态") private String orderStatus; diff --git a/framework/src/main/java/cn/lili/modules/wechat/serviceimpl/WechatMessageServiceImpl.java b/framework/src/main/java/cn/lili/modules/wechat/serviceimpl/WechatMessageServiceImpl.java index 9c57334c..448ff57a 100644 --- a/framework/src/main/java/cn/lili/modules/wechat/serviceimpl/WechatMessageServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/wechat/serviceimpl/WechatMessageServiceImpl.java @@ -87,14 +87,14 @@ public class WechatMessageServiceImpl extends ServiceImpl { Map params = new HashMap<>(1); params.put("template_id", templateId); - String message = WechatMessageUtil.wechatHandler(HttpUtil.post(delMsgTpl + accessToken, params)); + String message = WechatMessageUtil.wechatHandler(HttpUtils.doPostWithJson(delMsgTpl + accessToken, params)); log.info("删除模版请求:{},删除模版响应:{}", params, message); }); - } + }*/ //加入数据 List tmpList = initData(); diff --git a/framework/src/main/java/cn/lili/mybatis/BaseEntity.java b/framework/src/main/java/cn/lili/mybatis/BaseEntity.java index ab73d591..126c6cbc 100644 --- a/framework/src/main/java/cn/lili/mybatis/BaseEntity.java +++ b/framework/src/main/java/cn/lili/mybatis/BaseEntity.java @@ -64,7 +64,7 @@ public abstract class BaseEntity implements Serializable { @LastModifiedDate @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @TableField(fill = FieldFill.UPDATE) + @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(value = "更新时间", hidden = true) @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis") private Date updateTime; diff --git a/framework/src/main/java/cn/lili/mybatis/mybatisplus/MyMetaObjectHandler.java b/framework/src/main/java/cn/lili/mybatis/mybatisplus/MyMetaObjectHandler.java index 691daacc..eadaa7e3 100644 --- a/framework/src/main/java/cn/lili/mybatis/mybatisplus/MyMetaObjectHandler.java +++ b/framework/src/main/java/cn/lili/mybatis/mybatisplus/MyMetaObjectHandler.java @@ -22,11 +22,14 @@ public class MyMetaObjectHandler implements MetaObjectHandler { AuthUser authUser = UserContext.getCurrentUser(); if (authUser != null) { this.setFieldValByName("createBy", authUser.getUsername(), metaObject); - }else{ + } else { this.setFieldValByName("createBy", "SYSTEM", metaObject); } - this.setFieldValByName("createTime", new Date(), metaObject); + //有创建时间字段,切字段值为空 + if (metaObject.hasGetter("createTime")) { + this.setFieldValByName("createTime", new Date(), metaObject); + } //有值,则写入 if (metaObject.hasGetter("deleteFlag")) { this.setFieldValByName("deleteFlag", false, metaObject); diff --git a/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceBaseMapper.java b/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceBaseMapper.java new file mode 100644 index 00000000..8d56ccec --- /dev/null +++ b/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceBaseMapper.java @@ -0,0 +1,19 @@ +package cn.lili.mybatis.mybatisplus.external; + +import java.util.List; + +/** + * @author paulG + * @since 2022/7/18 + **/ +public interface SpiceBaseMapper { + + /** + * 批量插入 + * {@link com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn} + * + * @param entityList 要插入的数据 + * @return 成功插入的数据条数 + */ + long insertBatchSomeColumn(List entityList); +} diff --git a/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceSqlInjector.java b/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceSqlInjector.java new file mode 100644 index 00000000..5481579a --- /dev/null +++ b/framework/src/main/java/cn/lili/mybatis/mybatisplus/external/SpiceSqlInjector.java @@ -0,0 +1,33 @@ +package cn.lili.mybatis.mybatisplus.external; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author paulG + * @since 2022/7/18 + **/ +@Component +public class SpiceSqlInjector extends DefaultSqlInjector { + + /** + * 如果只需增加方法,保留mybatis plus自带方法, + * 可以先获取super.getMethodList(),再添加add + */ + @Override + public List getMethodList(Class mapperClass, TableInfo tableInfo) { + // 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法 + List methodList = super.getMethodList(mapperClass, tableInfo); + // 注入InsertBatchSomeColumn + // 在!t.isLogicDelete()表示不要逻辑删除字段,!"update_time".equals(t.getColumn())表示不要字段名为 update_time 的字段,不对进行操作 + // methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete() && !"update_time".equals(t.getColumn()))); + // 要逻辑删除 t.isLogicDelete() 默认不要 + methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete())); + return methodList; + } +} diff --git a/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java b/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java index 651e4ce5..e34525de 100644 --- a/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java +++ b/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java @@ -10,6 +10,10 @@ public enum GoodsTagsEnum { * "生成商品索引" */ GENERATOR_GOODS_INDEX("生成商品索引"), + /** + * "生成店铺商品索引" + */ + GENERATOR_STORE_GOODS_INDEX("生成店铺商品索引"), /** * "更新商品索引" */ @@ -31,6 +35,10 @@ public enum GoodsTagsEnum { * "重置商品索引" */ RESET_GOODS_INDEX("重置商品索引"), + /** + * "删除店铺商品索引" + */ + STORE_GOODS_DELETE("删除店铺商品索引"), /** * "删除商品" */ diff --git a/framework/src/test/java/cn/lili/test/RedisLimiterHelperTest.java b/framework/src/test/java/cn/lili/test/RedisLimiterHelperTest.java deleted file mode 100644 index 936bc736..00000000 --- a/framework/src/test/java/cn/lili/test/RedisLimiterHelperTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lili.test; - -import cn.lili.modules.order.order.entity.dos.OrderItem; -import cn.lili.modules.order.order.service.OrderItemService; -import cn.lili.modules.statistics.serviceimpl.OrderStatisticsServiceImpl; -import org.junit.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.ArrayList; -import java.util.List; - -/** - * RedisLimiterHelperTest - * - * @author Chopper - * @version v1.0 - * @since 2020-06-13 12:17 - */ - -@ExtendWith(SpringExtension.class) -@SpringBootTest -public class RedisLimiterHelperTest { - - @Autowired - private OrderItemService orderItemService; - - @Autowired - private OrderStatisticsServiceImpl orderStatisticsDataService; - - - @Test - public void orderTest() { - - - - } - - - @Test - public void testBatchUpdate() { - OrderItem orderItem = new OrderItem(); - orderItem.setId("1356539557729796097"); - orderItem.setCreateBy("1356539557729796097"); - - - OrderItem orderItem1 = new OrderItem(); - orderItem1.setId("1356787800921341953"); - orderItem1.setCreateBy("1356787800921341953"); - - - List orderItemList = new ArrayList<>(); - orderItemList.add(orderItem); - orderItemList.add(orderItem1); - - orderItemService.updateBatchById(orderItemList); - - } -} diff --git a/framework/src/test/java/cn/lili/test/script/ScriptTest.java b/framework/src/test/java/cn/lili/test/script/ScriptTest.java deleted file mode 100644 index 654c2071..00000000 --- a/framework/src/test/java/cn/lili/test/script/ScriptTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package cn.lili.test.script; - -import org.junit.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.scripting.support.ResourceScriptSource; -import org.springframework.test.annotation.Rollback; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; - -/** - * redis 事务测试 - * - * @author Chopper - * @version v1.0 - * @since - * 2020-02-22 20:26 - */ -@ExtendWith(SpringExtension.class) -@SpringBootTest -@Rollback() -@ContextConfiguration -@Configuration -@ComponentScan("cn.lili") -public class ScriptTest { - @Resource - private DefaultRedisScript redisScript; - @Resource - private StringRedisTemplate stringRedisTemplate; - - @Test - public void lua() { - stringRedisTemplate.opsForValue().set("key_1", "100"); - stringRedisTemplate.opsForValue().set("key_2", "95"); - stringRedisTemplate.opsForValue().set("key_3", "90"); - stringRedisTemplate.opsForValue().set("key_4", "85"); - List keys = new ArrayList<>(); - keys.add("key_1"); - keys.add("key_2"); - keys.add("key_3"); - keys.add("key_4"); - List value = new ArrayList<>(); - value.add("-1"); - value.add("-1"); - value.add("-1"); - value.add("-1"); - //启用十个线程 - for (int i = 0; i <= 10; i++) { - //每个线程循环十次 - Thread thread = new Thread(() -> { - for (int i1 = 0; i1 <= 10; i1++) { - Boolean execute = stringRedisTemplate.execute(redisScript, keys, value.toArray()); - System.out.println(Thread.currentThread().getName() + "|" + i1 + "|" + execute); - } - }); - thread.start(); - } - } - -} - -@Configuration -class LuaConfiguration { - @Bean - public DefaultRedisScript redisScript() { - DefaultRedisScript redisScript = new DefaultRedisScript<>(); - redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/quantity.lua"))); - redisScript.setResultType(Boolean.class); - return redisScript; - } -} diff --git a/manager-api/src/main/java/cn/lili/controller/hotwords/HotWordsManagerController.java b/manager-api/src/main/java/cn/lili/controller/hotwords/HotWordsManagerController.java deleted file mode 100644 index ce4eb8d3..00000000 --- a/manager-api/src/main/java/cn/lili/controller/hotwords/HotWordsManagerController.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lili.controller.hotwords; - -import cn.lili.common.enums.ResultUtil; -import cn.lili.common.vo.ResultMessage; -import cn.lili.modules.search.entity.dto.HotWordsDTO; -import cn.lili.modules.search.service.EsGoodsSearchService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 管理端,app版本控制器 - * - * @author Chopper - * @since 2018-07-04 21:50:52 - */ -@RestController -@Api(tags = "管理端,系统设置扩展接口") -@RequestMapping("/manager/hotwords/hotwords") -public class HotWordsManagerController { - - @Autowired - private EsGoodsSearchService esGoodsSearchService; - - @ApiOperation(value = "获取热词") - @GetMapping - public ResultMessage getHotWords() { - return ResultUtil.data(esGoodsSearchService.getHotWords(100)); - } - - @ApiOperation(value = "设置热词") - @PostMapping - public ResultMessage paymentForm(@Validated HotWordsDTO hotWords) { - esGoodsSearchService.setHotWords(hotWords); - return ResultUtil.success(); - } - - @ApiOperation(value = "设置热词") - @DeleteMapping("/{words}") - public ResultMessage deleteWords(@PathVariable String words) { - esGoodsSearchService.deleteHotWords(words); - return ResultUtil.success(); - } - -} diff --git a/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java b/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java index e0cf6b43..c3286749 100644 --- a/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java @@ -23,6 +23,8 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Objects; + /** * 管理端,交易投诉接口 * @@ -74,8 +76,8 @@ public class OrderComplaintManagerController { }) @PostMapping("/communication") public ResultMessage addCommunication(@RequestParam String complainId, @RequestParam String content) { - AuthUser currentUser = UserContext.getCurrentUser(); - OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.PLATFORM.name(), currentUser.getId(), currentUser.getUsername()); + AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); + OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.PLATFORM.name(), currentUser.getUsername(), currentUser.getId()); orderComplaintCommunicationService.addCommunication(communicationVO); return ResultUtil.data(communicationVO); } diff --git a/manager-api/src/main/java/cn/lili/controller/other/ArticleManagerController.java b/manager-api/src/main/java/cn/lili/controller/other/ArticleManagerController.java index f9cf79ce..d9372124 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/ArticleManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/ArticleManagerController.java @@ -42,6 +42,14 @@ public class ArticleManagerController { return ResultUtil.data(articleService.getById(id)); } + @ApiOperation(value = "根据类型查看文章") + @ApiImplicitParam(name = "type", value = "文章类型", required = true, dataType = "String", paramType = "path") + @GetMapping(value = "/type/{type}") + public ResultMessage
getByType(@PathVariable String type) { + + return ResultUtil.data(articleService.customGetByType(type)); + } + @ApiOperation(value = "分页获取") @ApiImplicitParams({ @ApiImplicitParam(name = "categoryId", value = "文章分类ID", paramType = "query"), @@ -60,7 +68,7 @@ public class ArticleManagerController { return ResultUtil.data(article); } - @ApiOperation(value = "修改文章") + @ApiOperation(value = "修改文章--文章id") @ApiImplicitParam(name = "id", value = "文章ID", required = true, paramType = "path") @PutMapping(value = "update/{id}", consumes = "application/json", produces = "application/json") public ResultMessage
update(@RequestBody Article article, @PathVariable("id") String id) { @@ -68,6 +76,15 @@ public class ArticleManagerController { return ResultUtil.data(articleService.updateArticle(article)); } + @ApiOperation(value = "修改文章--文章类型") + @ApiImplicitParam(name = "type", value = "文章类型", required = true, paramType = "path") + @PutMapping(value = "updateArticle/{type}", consumes = "application/json", produces = "application/json") + public ResultMessage
updateArticle(@RequestBody Article article, @PathVariable("type") String type,String id) { + article.setId(id); + article.setType(type); + return ResultUtil.data(articleService.updateArticleType(article)); + } + @ApiOperation(value = "修改文章状态") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "文章ID", required = true, paramType = "path"), diff --git a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java index 2ecb8cdd..89d878b3 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java @@ -33,7 +33,7 @@ public class ElasticsearchController { } @GetMapping("/progress") - public ResultMessage> getProgress() { + public ResultMessage> getProgress() { return ResultUtil.data(esGoodsIndexService.getProgress()); } } diff --git a/manager-api/src/main/java/cn/lili/controller/other/HotWordsManagerController.java b/manager-api/src/main/java/cn/lili/controller/other/HotWordsManagerController.java new file mode 100644 index 00000000..a8b5f01a --- /dev/null +++ b/manager-api/src/main/java/cn/lili/controller/other/HotWordsManagerController.java @@ -0,0 +1,83 @@ +package cn.lili.controller.other; + +import cn.lili.common.enums.ResultUtil; +import cn.lili.common.vo.ResultMessage; +import cn.lili.modules.search.entity.dos.HotWordsHistory; +import cn.lili.modules.search.entity.dto.HotWordsDTO; +import cn.lili.modules.search.entity.dto.HotWordsSearchParams; +import cn.lili.modules.search.service.HotWordsHistoryService; +import cn.lili.modules.search.service.HotWordsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.constraints.NotNull; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +/** + * 管理端,热词管理 + * + * @author Chopper + * @since 2018-07-04 21:50:52 + */ +@RestController +@Api(tags = "管理端,热词管理") +@RequestMapping("/manager/hotwords/hotwords") +public class HotWordsManagerController { + + @Autowired + private HotWordsService hotWordsService; + + + @Autowired + private HotWordsHistoryService hotWordsHistoryService; + + @ApiOperation(value = "获取热词") + @GetMapping + public ResultMessage getHotWords() { + return ResultUtil.data(hotWordsService.getHotWords(100)); + } + + @ApiOperation(value = "设置热词") + @PostMapping + public ResultMessage setHotWords(@Validated HotWordsDTO hotWords) { + hotWordsService.setHotWords(hotWords); + return ResultUtil.success(); + } + + @ApiOperation(value = "删除热词") + @DeleteMapping + public ResultMessage deleteWords(String words) { + hotWordsService.deleteHotWords(words); + return ResultUtil.success(); + } + + @ApiOperation(value = "历史热词") + @GetMapping("/history") + public ResultMessage deleteWords(HistorySearchParams historySearchParams) { + List hotWordsHistoryList = hotWordsHistoryService.queryByDay(historySearchParams.getDate()); + Collections.sort(hotWordsHistoryList); + return ResultUtil.data(hotWordsHistoryList); + } + + @ApiOperation(value = "热词统计") + @GetMapping("/statistics") + public ResultMessage deleteWords(HotWordsSearchParams hotWordsSearchParams) { + return ResultUtil.data(hotWordsHistoryService.statistics(hotWordsSearchParams)); + } +} + +@Data +class HistorySearchParams { + @DateTimeFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "查询日期不能为空") + private Date date; + +} diff --git a/manager-api/src/main/java/cn/lili/controller/other/broadcast/StudioManagerController.java b/manager-api/src/main/java/cn/lili/controller/other/broadcast/StudioManagerController.java index fb514b84..584db8bf 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/broadcast/StudioManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/broadcast/StudioManagerController.java @@ -36,7 +36,7 @@ public class StudioManagerController { @ApiOperation(value = "获取店铺直播间列表") @ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query") @GetMapping - public ResultMessage> page(PageVO pageVO, String status) { + public ResultMessage> page(PageVO pageVO, String status) { return ResultUtil.data(studioService.studioList(pageVO, null, status)); } diff --git a/manager-api/src/main/java/cn/lili/controller/passport/AdminUserManagerController.java b/manager-api/src/main/java/cn/lili/controller/passport/AdminUserManagerController.java index 1be65f27..80ca8903 100644 --- a/manager-api/src/main/java/cn/lili/controller/passport/AdminUserManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/passport/AdminUserManagerController.java @@ -8,7 +8,6 @@ import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.security.enums.UserEnums; import cn.lili.common.security.token.Token; -import cn.lili.common.utils.StringUtils; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; import cn.lili.common.vo.SearchVO; @@ -17,7 +16,6 @@ import cn.lili.modules.permission.entity.dos.AdminUser; import cn.lili.modules.permission.entity.dto.AdminUserDTO; import cn.lili.modules.permission.entity.vo.AdminUserVO; import cn.lili.modules.permission.service.AdminUserService; -import cn.lili.modules.permission.service.DepartmentService; import cn.lili.modules.verification.entity.enums.VerificationEnums; import cn.lili.modules.verification.service.VerificationService; import cn.lili.mybatis.util.PageUtil; @@ -49,8 +47,6 @@ import java.util.List; public class AdminUserManagerController { @Autowired private AdminUserService adminUserService; - @Autowired - private DepartmentService departmentService; /** * 会员 */ @@ -88,13 +84,10 @@ public class AdminUserManagerController { @GetMapping(value = "/info") @ApiOperation(value = "获取当前登录用户接口") - public ResultMessage getUserInfo() { + public ResultMessage getUserInfo() { AuthUser tokenUser = UserContext.getCurrentUser(); if (tokenUser != null) { - AdminUserVO adminUser = new AdminUserVO(adminUserService.findByUsername(tokenUser.getUsername())); - if (StringUtils.isNotEmpty(adminUser.getDepartmentId())) { - adminUser.setDepartmentTitle(departmentService.getById(adminUser.getDepartmentId()).getTitle()); - } + AdminUser adminUser = adminUserService.findByUsername(tokenUser.getUsername()); adminUser.setPassword(null); return ResultUtil.data(adminUser); } diff --git a/manager-api/src/main/java/cn/lili/controller/permission/DepartmentManagerController.java b/manager-api/src/main/java/cn/lili/controller/permission/DepartmentManagerController.java index 724b6c97..86087a74 100644 --- a/manager-api/src/main/java/cn/lili/controller/permission/DepartmentManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/permission/DepartmentManagerController.java @@ -1,15 +1,16 @@ package cn.lili.controller.permission; import cn.lili.common.enums.ResultUtil; -import cn.lili.mybatis.util.PageUtil; import cn.lili.common.vo.ResultMessage; import cn.lili.common.vo.SearchVO; import cn.lili.modules.permission.entity.dos.Department; import cn.lili.modules.permission.entity.vo.DepartmentVO; import cn.lili.modules.permission.service.DepartmentService; +import cn.lili.mybatis.util.PageUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -45,15 +46,14 @@ public class DepartmentManagerController { @PostMapping @ApiOperation(value = "新增部门") - public ResultMessage save(Department department) { + public ResultMessage save(@Validated Department department) { departmentService.save(department); return ResultUtil.data(department); } @PutMapping("/{id}") @ApiOperation(value = "更新部门") - public ResultMessage update(@PathVariable String id, Department department) { - departmentService.updateById(department); + public ResultMessage update(@PathVariable String id, @Validated Department department) { departmentService.updateById(department); return ResultUtil.data(department); } diff --git a/manager-api/src/main/java/cn/lili/controller/permission/MenuManagerController.java b/manager-api/src/main/java/cn/lili/controller/permission/MenuManagerController.java index e848ad80..4d952f1c 100644 --- a/manager-api/src/main/java/cn/lili/controller/permission/MenuManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/permission/MenuManagerController.java @@ -53,7 +53,6 @@ public class MenuManagerController { @ApiImplicitParam(name = "id", value = "菜单ID", required = true, paramType = "path", dataType = "String") @ApiOperation(value = "编辑") @PutMapping(value = "/{id}") - @DemoSite public ResultMessage edit(@PathVariable String id, Menu menu) { menu.setId(id); diff --git a/manager-api/src/main/java/cn/lili/controller/promotion/CouponActivityManagerController.java b/manager-api/src/main/java/cn/lili/controller/promotion/CouponActivityManagerController.java index 635d9ff1..e2c4cbf6 100644 --- a/manager-api/src/main/java/cn/lili/controller/promotion/CouponActivityManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/promotion/CouponActivityManagerController.java @@ -6,6 +6,7 @@ import cn.lili.common.exception.ServiceException; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.promotion.entity.dos.CouponActivity; +import cn.lili.modules.promotion.entity.dos.CouponActivityItem; import cn.lili.modules.promotion.entity.dto.CouponActivityDTO; import cn.lili.modules.promotion.entity.vos.CouponActivityVO; import cn.lili.modules.promotion.service.CouponActivityService; @@ -49,8 +50,12 @@ public class CouponActivityManagerController { @ApiOperation(value = "添加优惠券活动") @PostMapping - @PutMapping(consumes = "application/json", produces = "application/json") public ResultMessage addCouponActivity(@RequestBody(required = false) CouponActivityDTO couponActivityDTO) { + for (CouponActivityItem couponActivityItem : couponActivityDTO.getCouponActivityItems()) { + if (couponActivityItem.getNum() > 3) { + throw new ServiceException(ResultCode.COUPON_ACTIVITY_MAX_NUM); + } + } if (couponActivityService.savePromotions(couponActivityDTO)) { return ResultUtil.data(couponActivityDTO); } diff --git a/manager-api/src/main/java/cn/lili/controller/promotion/CouponManagerController.java b/manager-api/src/main/java/cn/lili/controller/promotion/CouponManagerController.java index b78c98c0..8a130ef9 100644 --- a/manager-api/src/main/java/cn/lili/controller/promotion/CouponManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/promotion/CouponManagerController.java @@ -44,7 +44,9 @@ public class CouponManagerController { @ApiOperation(value = "获取优惠券列表") @GetMapping public ResultMessage> getCouponList(CouponSearchParams queryParam, PageVO page) { - queryParam.setStoreId(PromotionTools.PLATFORM_ID); + if (queryParam.getStoreId() == null) { + queryParam.setStoreId(PromotionTools.PLATFORM_ID); + } return ResultUtil.data(couponService.pageVOFindAll(queryParam, page)); } diff --git a/manager-api/src/main/java/cn/lili/controller/promotion/PromotionManagerController.java b/manager-api/src/main/java/cn/lili/controller/promotion/PromotionManagerController.java index 9afbb2b4..a4c9f59d 100644 --- a/manager-api/src/main/java/cn/lili/controller/promotion/PromotionManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/promotion/PromotionManagerController.java @@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; import java.util.Map; /** @@ -37,8 +38,8 @@ public class PromotionManagerController { @GetMapping("/current") @ApiOperation(value = "获取当前进行中的促销活动") - public ResultMessage> getCurrentPromotion() { - Map currentPromotion = promotionService.getCurrentPromotion(); + public ResultMessage>> getCurrentPromotion() { + Map> currentPromotion = promotionService.getCurrentPromotion(); return ResultUtil.data(currentPromotion); } diff --git a/manager-api/src/main/java/cn/lili/controller/setting/SettingManagerController.java b/manager-api/src/main/java/cn/lili/controller/setting/SettingManagerController.java index e0f9c48d..bf85cf9b 100644 --- a/manager-api/src/main/java/cn/lili/controller/setting/SettingManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/setting/SettingManagerController.java @@ -185,6 +185,10 @@ public class SettingManagerController { return setting == null ? ResultUtil.data(new ImSetting()) : ResultUtil.data(JSONUtil.toBean(setting.getSettingValue(), ImSetting.class)); + case HOT_WORDS: + return setting == null ? + ResultUtil.data(new HotWordsSetting()) : + ResultUtil.data(JSONUtil.toBean(setting.getSettingValue(), HotWordsSetting.class)); default: throw new ServiceException(ResultCode.SETTING_NOT_TO_SET); } diff --git a/manager-api/src/main/java/cn/lili/security/ManagerAuthenticationFilter.java b/manager-api/src/main/java/cn/lili/security/ManagerAuthenticationFilter.java index 27a1586f..ddd981cb 100644 --- a/manager-api/src/main/java/cn/lili/security/ManagerAuthenticationFilter.java +++ b/manager-api/src/main/java/cn/lili/security/ManagerAuthenticationFilter.java @@ -84,7 +84,7 @@ public class ManagerAuthenticationFilter extends BasicAuthenticationFilter { //如果不是超级管理员, 则鉴权 - if (!authUser.getIsSuper()) { + if (Boolean.FALSE.equals(authUser.getIsSuper())) { //获取缓存中的权限 Map> permission = (Map>) cache.get(CachePrefix.PERMISSION_LIST.getPrefix(UserEnums.MANAGER) + authUser.getId()); diff --git a/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java b/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java index 3ecf49f3..762bcbdb 100644 --- a/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java +++ b/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java @@ -3,9 +3,11 @@ package cn.lili.test.elasticsearch; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.common.vo.PageVO; +import cn.lili.modules.goods.entity.dos.Goods; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; +import cn.lili.modules.goods.service.GoodsService; import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.promotion.service.PromotionService; import cn.lili.modules.search.entity.dos.EsGoodsAttribute; @@ -47,6 +49,9 @@ class EsTest { @Autowired private GoodsSkuService goodsSkuService; + @Autowired + private GoodsService goodsService; + @Autowired private Cache cache; @@ -63,6 +68,13 @@ class EsTest { // System.out.println(HtmlUtil.filter("+ADw-script+AD4-alert(document.cookie)+ADw-/script+AD4-")); // Date dt1 = new Date(2021, 12, 10); // Date dt2 = new Date(2021, 12, 14); + for (int i = 0; i < 1000; i++) { + + Goods goods = new Goods(); + goods.setGoodsName("测试商品" + i); +// goods.setAuthFlag(); + } + // } @@ -132,7 +144,7 @@ class EsTest { esGoodsIndices.add(index); cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity()); } - esGoodsIndexService.initIndex(esGoodsIndices); + esGoodsIndexService.initIndex(esGoodsIndices, true); Assertions.assertTrue(true); } diff --git a/manager-api/src/test/java/cn/lili/test/promotion/PromotionPriceTest.java b/manager-api/src/test/java/cn/lili/test/promotion/PromotionPriceTest.java deleted file mode 100644 index cfdafeb2..00000000 --- a/manager-api/src/test/java/cn/lili/test/promotion/PromotionPriceTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lili.test.promotion; - -import cn.lili.modules.promotion.entity.dos.BasePromotions; -import cn.lili.modules.promotion.service.PromotionGoodsService; -import cn.lili.modules.promotion.service.PromotionService; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.Map; - -/** - * @author paulG - * @since 2020/11/23 - **/ -@ExtendWith(SpringExtension.class) -@SpringBootTest -class PromotionPriceTest { - - @Autowired - private PromotionService promotionService; - - @Autowired - private PromotionGoodsService promotionGoodsServiceService; - - @Test - void testSeckillPrice() { - Map currentPromotion = promotionService.getCurrentPromotion(); - for (Map.Entry entry : currentPromotion.entrySet()) { - BasePromotions promotion = (BasePromotions) entry.getValue(); - System.out.println(entry.getKey() + "-" + promotion.getId()); - } - Assertions.assertTrue(true); - } - -} diff --git a/pom.xml b/pom.xml index 55d26d0f..24448aab 100644 --- a/pom.xml +++ b/pom.xml @@ -26,11 +26,11 @@ 1 4.22.32.ALL 3.5.1 - 5.7.20 + 5.8.0 2.0.3.RELEASE 3.0.4 2.9.10 - 1.18.22 + 1.18.24 3.15.6 4.5.18 3.11.1 @@ -38,7 +38,7 @@ 4.6.0 3.14.0 2.0.9 - 2.2.1 + 2.2.2 0.11.2 4.0.0 1.2.8 @@ -46,13 +46,13 @@ 4.7.2 4.7.2 2.0.9 - 2.6.2 + 2.6.6 1.21 5.1.0 5.1.0 - 7.0.1 - 3.4.1 - 1.7.35 + 7.1.1 + 3.5.0 + 1.7.36 3.2.3 1.9 4.3 @@ -60,6 +60,7 @@ 1.2.2 2.3.1 20211018.2 + 8.0.3 @@ -87,7 +88,6 @@ ${docker-registry}/${project.artifactId}:${revision}.${images-version} java ["java", "-jar", "/${project.build.finalName}.jar"] - true / @@ -110,7 +110,7 @@ central aliyun maven - http://maven.aliyun.com/nexus/content/groups/public/ + https://maven.aliyun.com/repository/public default diff --git a/seller-api/src/main/java/cn/lili/controller/order/OrderComplaintStoreController.java b/seller-api/src/main/java/cn/lili/controller/order/OrderComplaintStoreController.java index 3913294f..72faab7b 100644 --- a/seller-api/src/main/java/cn/lili/controller/order/OrderComplaintStoreController.java +++ b/seller-api/src/main/java/cn/lili/controller/order/OrderComplaintStoreController.java @@ -68,7 +68,7 @@ public class OrderComplaintStoreController { @PostMapping("/communication") public ResultMessage addCommunication(@RequestParam String complainId, @RequestParam String content) { AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); - OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.STORE.name(), currentUser.getStoreId(), currentUser.getUsername()); + OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.STORE.name(), currentUser.getUsername(), currentUser.getStoreId()); orderComplaintCommunicationService.addCommunication(communicationVO); return ResultUtil.success(); } diff --git a/seller-api/src/main/java/cn/lili/controller/other/broadcast/StudioStoreController.java b/seller-api/src/main/java/cn/lili/controller/other/broadcast/StudioStoreController.java index 09999f03..efe697e3 100644 --- a/seller-api/src/main/java/cn/lili/controller/other/broadcast/StudioStoreController.java +++ b/seller-api/src/main/java/cn/lili/controller/other/broadcast/StudioStoreController.java @@ -38,7 +38,7 @@ public class StudioStoreController { @ApiOperation(value = "获取店铺直播间列表") @ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query", dataType = "String") @GetMapping - public ResultMessage> page(PageVO pageVO, String status) { + public ResultMessage> page(PageVO pageVO, String status) { return ResultUtil.data(studioService.studioList(pageVO, null, status)); }