Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop into fengtianyangyang_clerk
Conflicts: DB/version4.2.3toMASTER.sql common-api/src/main/java/cn/lili/controller/common/SiteController.java common-api/src/main/java/cn/lili/controller/common/UploadController.java config/application.yml framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java framework/src/main/java/cn/lili/modules/page/serviceimpl/PageDataServiceImpl.java
This commit is contained in:
commit
26dd8ed13a
@ -1,2 +1,64 @@
|
||||
/** 新增已退货数量 **/
|
||||
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';
|
@ -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;
|
||||
|
||||
|
46
DB/version4.2.4toMASTER.sql
Normal file
46
DB/version4.2.4toMASTER.sql
Normal file
@ -0,0 +1,46 @@
|
||||
/** 增加签到日期 **/
|
||||
ALTER TABLE li_member_sign
|
||||
ADD day int DEFAULT NULL COMMENT '签到日 ';
|
||||
ALTER TABLE li_member_sign
|
||||
DROP INDEX uk_member_day;
|
||||
ALTER TABLE li_member_sign
|
||||
add unique uk_member_day (member_id, day) COMMENT 'uk_member_day';
|
||||
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for li_hot_words_history
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `li_hot_words_history`;
|
||||
CREATE TABLE `li_hot_words_history`
|
||||
(
|
||||
`id` bigint NOT NULL COMMENT 'ID',
|
||||
`create_time` datetime(6) DEFAULT NULL COMMENT '创建时间',
|
||||
`keywords` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '热词',
|
||||
`score` int DEFAULT NULL COMMENT '热词分数',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 COLLATE = utf8_bin COMMENT '热词历史表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of li_hot_words_history
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for li_wholesale
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `li_wholesale`;
|
||||
CREATE TABLE `li_wholesale`
|
||||
(
|
||||
`id` bigint NOT NULL,
|
||||
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
||||
`create_time` datetime(6) DEFAULT NULL,
|
||||
`delete_flag` bit(1) DEFAULT NULL,
|
||||
`update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
||||
`update_time` datetime(6) DEFAULT NULL,
|
||||
`price` decimal(10, 2) DEFAULT NULL COMMENT '价格',
|
||||
`goods_id` bigint DEFAULT NULL COMMENT '商品id',
|
||||
`sku_id` bigint DEFAULT NULL COMMENT '商品skuId',
|
||||
`num` int DEFAULT NULL COMMENT '起购量',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_bin COMMENT '批发规则表';
|
||||
|
40
README.md
40
README.md
@ -1,10 +1,6 @@
|
||||
## Lilishop B2B2C商城系统
|
||||
|
||||
##### 开源不易,如有帮助请点Star
|
||||
|
||||
|
||||
|
||||
#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,进群先看文档后提问)
|
||||
#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,其他问题先看文档后提问)
|
||||
|
||||
<<<<<<< HEAD
|
||||
##### 交流 qq 1群 961316482(已满)
|
||||
@ -16,12 +12,17 @@
|
||||
##### 交流 qq 1群 961316482(已满)
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=BAhURE3DG2YWhQk6kRxVapbLykqMoPS8&jump_from=webapi"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群" title="Lilishop交流群">点击快捷加群</a>
|
||||
|
||||
##### 交流 qq 2群 875294241
|
||||
##### 交流 qq 2群 875294241(已满)
|
||||
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=_lrekOvr5k2p5uTn5GRidI-chKEmpCX3&jump_from=webapi"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群2群" title="Lilishop交流群2群">点击快捷加群</a>
|
||||
>>>>>>> ae0c4aea12996d3d72eca7c6ccdc97922373e4d7
|
||||
|
||||
|
||||
##### 交流 qq 3群 263785057
|
||||
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=VUogkDvaso4zLTFH8nxFPDRKq0EthUn1&jump_from=webapi"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="Lilishop交流群3群" title="Lilishop交流群3群">点击快捷加群</a>
|
||||
|
||||
|
||||
##### 体验 公众号/小程序/APP 体验,扫描二维码
|
||||
|
||||

|
||||
@ -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’
|
||||
|
||||

|
||||
|
||||
### 快速部署本地商城
|
||||
### 快速本地部署
|
||||
|
||||
[点击跳转](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
|
||||
|
@ -14,6 +14,7 @@ import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
|
||||
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
|
||||
import cn.lili.modules.search.service.EsGoodsSearchService;
|
||||
import cn.lili.modules.search.service.HotWordsService;
|
||||
import cn.lili.modules.statistics.aop.PageViewPoint;
|
||||
import cn.lili.modules.statistics.aop.enums.PageViewEnum;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@ -62,6 +63,9 @@ public class GoodsBuyerController {
|
||||
@Autowired
|
||||
private EsGoodsSearchService goodsSearchService;
|
||||
|
||||
@Autowired
|
||||
private HotWordsService hotWordsService;
|
||||
|
||||
@ApiOperation(value = "通过id获取商品信息")
|
||||
@ApiImplicitParam(name = "goodsId", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping(value = "/get/{goodsId}")
|
||||
@ -117,7 +121,7 @@ public class GoodsBuyerController {
|
||||
@ApiOperation(value = "获取搜索热词")
|
||||
@GetMapping("/hot-words")
|
||||
public ResultMessage<List<String>> getGoodsHotWords(Integer count) {
|
||||
List<String> hotWords = goodsSearchService.getHotWords(count);
|
||||
List<String> hotWords = hotWordsService.getHotWords(count);
|
||||
return ResultUtil.data(hotWords);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.common.vo.ResultMessage;
|
||||
import cn.lili.modules.member.service.FootprintService;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -34,7 +35,7 @@ public class FootprintController {
|
||||
|
||||
@ApiOperation(value = "分页获取")
|
||||
@GetMapping
|
||||
public ResultMessage<List<EsGoodsIndex>> getByPage(PageVO page) {
|
||||
public ResultMessage<IPage<EsGoodsIndex>> getByPage(PageVO page) {
|
||||
return ResultUtil.data(footprintService.footPrintPage(page));
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class MemberEvaluationBuyerController {
|
||||
@ApiOperation(value = "查看会员评价详情")
|
||||
@ApiImplicitParam(name = "id", value = "评价ID", required = true, paramType = "path")
|
||||
@GetMapping(value = "/get/{id}")
|
||||
public ResultMessage<MemberEvaluationVO> save(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) {
|
||||
public ResultMessage<MemberEvaluationVO> get(@NotNull(message = "评价ID不能为空") @PathVariable("id") String id) {
|
||||
return ResultUtil.data(memberEvaluationService.queryById(id));
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -82,7 +82,7 @@ public class OrderComplaintBuyerController {
|
||||
@PostMapping("/communication")
|
||||
public ResultMessage<OrderComplaintCommunicationVO> addCommunication(@RequestParam String complainId, @RequestParam String content) {
|
||||
AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser());
|
||||
OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.BUYER.name(), currentUser.getId(), currentUser.getNickName());
|
||||
OrderComplaintCommunicationVO communicationVO = new OrderComplaintCommunicationVO(complainId, content, CommunicationOwnerEnum.BUYER.name(), currentUser.getNickName(), currentUser.getId());
|
||||
orderComplaintCommunicationService.addCommunication(communicationVO);
|
||||
return ResultUtil.data(communicationVO);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package cn.lili.controller.other.broadcast;
|
||||
import cn.lili.common.enums.ResultUtil;
|
||||
import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.common.vo.ResultMessage;
|
||||
import cn.lili.modules.goods.entity.dos.Studio;
|
||||
import cn.lili.modules.goods.entity.vos.StudioVO;
|
||||
import cn.lili.modules.goods.service.StudioService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -35,7 +35,7 @@ public class StudioController {
|
||||
@ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query", dataType = "String")
|
||||
})
|
||||
@GetMapping
|
||||
public ResultMessage<IPage<Studio>> page(PageVO pageVO, Integer recommend, String status) {
|
||||
public ResultMessage<IPage<StudioVO>> page(PageVO pageVO, Integer recommend, String status) {
|
||||
return ResultUtil.data(studioService.studioList(pageVO, recommend, status));
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,6 @@ public class MemberBuyerController {
|
||||
|
||||
@ApiOperation(value = "修改密码")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"),
|
||||
@ApiImplicitParam(name = "password", value = "是否保存登录", required = true, paramType = "query")
|
||||
})
|
||||
@PostMapping("/resetPassword")
|
||||
@ -177,6 +176,34 @@ public class MemberBuyerController {
|
||||
return ResultUtil.data(memberService.modifyPass(tokenUser.getId(), password, newPassword));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "初始设置密码")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query")
|
||||
})
|
||||
@PutMapping("/canInitPassword")
|
||||
public ResultMessage<Object> canInitPassword() {
|
||||
return ResultUtil.data(memberService.canInitPass());
|
||||
}
|
||||
|
||||
@ApiOperation(value = "初始设置密码")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query")
|
||||
})
|
||||
@PutMapping("/initPassword")
|
||||
public ResultMessage<Object> initPassword(@NotNull(message = "密码不能为空") @RequestParam String password) {
|
||||
memberService.initPass(password);
|
||||
return ResultUtil.success();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "注销账号")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query")
|
||||
})
|
||||
@PutMapping("/cancellation")
|
||||
public ResultMessage<Member> cancellation(@NotNull(message = "密码不能为空") @RequestParam String password) {
|
||||
memberService.cancellation(password);
|
||||
return ResultUtil.success();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "刷新token")
|
||||
@GetMapping("/refresh/{refreshToken}")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -2,9 +2,9 @@ package cn.lili.controller.common;
|
||||
|
||||
import cn.lili.common.enums.ResultUtil;
|
||||
import cn.lili.common.vo.ResultMessage;
|
||||
import cn.lili.modules.system.service.RegionService;
|
||||
import cn.lili.modules.system.entity.dos.Region;
|
||||
import cn.lili.modules.system.entity.vo.RegionVO;
|
||||
import cn.lili.modules.system.service.RegionService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
@ -38,6 +38,11 @@ public class RegionController {
|
||||
return ResultUtil.data(regionService.getRegion(cityCode,townName));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/name")
|
||||
@ApiOperation(value = "根据名字获取地区地址id")
|
||||
public ResultMessage<String> getItemByLastName(String lastName) {
|
||||
return ResultUtil.data(regionService.getItemByLastName(lastName));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/item/{id}")
|
||||
@ApiImplicitParam(name = "id", value = "地区ID", required = true, dataType = "String", paramType = "path")
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -1,8 +1,5 @@
|
||||
package cn.lili.controller.security;
|
||||
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.common.security.CustomAccessDeniedHandler;
|
||||
import cn.lili.common.properties.IgnoredUrlsProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -25,19 +22,10 @@ import org.springframework.web.cors.CorsConfigurationSource;
|
||||
public class CommonSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
||||
/**
|
||||
* 忽略验权配置
|
||||
*/
|
||||
@Autowired
|
||||
private IgnoredUrlsProperties ignoredUrlsProperties;
|
||||
/**
|
||||
* spring security -》 权限不足处理
|
||||
*/
|
||||
@Autowired
|
||||
private CustomAccessDeniedHandler accessDeniedHandler;
|
||||
@Autowired
|
||||
private Cache<String> cache;
|
||||
@Autowired
|
||||
private CorsConfigurationSource corsConfigurationSource;
|
||||
|
||||
@Override
|
||||
|
@ -121,6 +121,8 @@ ignored:
|
||||
- /source/**
|
||||
- /common/common/slider/**
|
||||
- /common/common/sms/**
|
||||
- /common/common/logo
|
||||
- /common/common/site
|
||||
- /druid/**
|
||||
- /swagger-ui.html
|
||||
- /doc.html
|
||||
|
@ -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:
|
||||
|
@ -19,6 +19,7 @@ import cn.lili.modules.order.cart.entity.vo.CartVO;
|
||||
import cn.lili.modules.order.order.entity.dos.Order;
|
||||
import cn.lili.modules.order.order.entity.dos.OrderItem;
|
||||
import cn.lili.modules.order.order.entity.dto.OrderMessage;
|
||||
import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
|
||||
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
|
||||
import cn.lili.modules.order.order.entity.enums.*;
|
||||
import cn.lili.modules.order.order.service.OrderItemService;
|
||||
@ -96,6 +97,15 @@ public class FullDiscountExecute implements TradeEvent, OrderStatusChangeEvent {
|
||||
if (orderMessage.getNewStatus().equals(OrderStatusEnum.PAID)) {
|
||||
log.debug("满减活动,订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
|
||||
renderGift(JSONUtil.toBean(cache.getString(CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn()), CartVO.class), orderMessage);
|
||||
} else if (orderMessage.getNewStatus().equals(OrderStatusEnum.CANCELLED)) {
|
||||
log.debug("满减活动,取消订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
|
||||
OrderSearchParams searchParams = new OrderSearchParams();
|
||||
searchParams.setParentOrderSn(orderMessage.getOrderSn());
|
||||
searchParams.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
|
||||
List<Order> orders = orderService.queryListByParams(searchParams);
|
||||
if (orders != null && !orders.isEmpty()) {
|
||||
orderService.systemCancel(orders.get(0).getSn(),"主订单取消,赠送订单字段自动取消");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +200,7 @@ public class FullDiscountExecute implements TradeEvent, OrderStatusChangeEvent {
|
||||
BeanUtil.copyProperties(priceDetailDTO, order, "id");
|
||||
//生成订单参数
|
||||
order.setSn(SnowFlake.createStr("G"));
|
||||
order.setParentOrderSn(originOrder.getSn());
|
||||
order.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
|
||||
order.setOrderStatus(OrderStatusEnum.UNPAID.name());
|
||||
order.setPayStatus(PayStatusEnum.PAID.name());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 库存扣减,他表示了订单状态是否出库成功
|
||||
@ -156,7 +157,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
* @param stocks
|
||||
*/
|
||||
private void checkStocks(List<Integer> stocks, OrderDetailVO order) {
|
||||
if (order.getOrderItems().size() == stocks.size()) {
|
||||
if (!stocks.isEmpty() && order.getOrderItems().size() == stocks.size() && stocks.stream().anyMatch(Objects::nonNull)) {
|
||||
return;
|
||||
}
|
||||
initSkuCache(order.getOrderItems());
|
||||
@ -357,6 +358,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
|
||||
GoodsSku goodsSku = new GoodsSku();
|
||||
goodsSku.setId(orderItem.getSkuId());
|
||||
goodsSku.setGoodsId(orderItem.getGoodsId());
|
||||
goodsSkus.add(goodsSku);
|
||||
}
|
||||
//批量获取商品库存
|
||||
|
@ -6,6 +6,8 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.common.aop.annotation.RetryOperation;
|
||||
import cn.lili.common.exception.RetryException;
|
||||
import cn.lili.event.GoodsCommentCompleteEvent;
|
||||
import cn.lili.modules.distribution.entity.dos.DistributionGoods;
|
||||
import cn.lili.modules.distribution.entity.dto.DistributionGoodsSearchParams;
|
||||
@ -30,7 +32,6 @@ import cn.lili.modules.promotion.service.PromotionGoodsService;
|
||||
import cn.lili.modules.promotion.service.PromotionService;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import cn.lili.modules.search.service.EsGoodsIndexService;
|
||||
import cn.lili.modules.store.service.StoreService;
|
||||
import cn.lili.rocketmq.tags.GoodsTagsEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
@ -58,11 +59,6 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
*/
|
||||
@Autowired
|
||||
private EsGoodsIndexService goodsIndexService;
|
||||
/**
|
||||
* 店铺
|
||||
*/
|
||||
@Autowired
|
||||
private StoreService storeService;
|
||||
/**
|
||||
* 商品
|
||||
*/
|
||||
@ -121,6 +117,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
private PromotionGoodsService promotionGoodsService;
|
||||
|
||||
@Override
|
||||
@RetryOperation
|
||||
public void onMessage(MessageExt messageExt) {
|
||||
|
||||
switch (GoodsTagsEnum.valueOf(messageExt.getTags())) {
|
||||
@ -135,20 +132,32 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
String goodsId = new String(messageExt.getBody());
|
||||
log.info("生成索引: {}", goodsId);
|
||||
Goods goods = this.goodsService.getById(goodsId);
|
||||
updateGoodsIndex(goods);
|
||||
this.updateGoodsIndex(goods);
|
||||
} catch (Exception e) {
|
||||
log.error("生成商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
|
||||
log.error("生成商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
case GENERATOR_STORE_GOODS_INDEX:
|
||||
try {
|
||||
String storeId = new String(messageExt.getBody());
|
||||
this.updateGoodsIndex(storeId);
|
||||
} catch (Exception e) {
|
||||
log.error("生成店铺商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
case UPDATE_GOODS_INDEX_PROMOTIONS:
|
||||
this.updateGoodsIndexPromotions(new String(messageExt.getBody()));
|
||||
break;
|
||||
case DELETE_GOODS_INDEX_PROMOTIONS:
|
||||
BasePromotions promotions = JSONUtil.toBean(new String(messageExt.getBody()), BasePromotions.class);
|
||||
if (CharSequenceUtil.isNotEmpty(promotions.getScopeId())) {
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(Arrays.asList(promotions.getScopeId().split(",")), promotions.getId());
|
||||
JSONObject jsonObject = JSONUtil.parseObj(new String(messageExt.getBody()));
|
||||
String promotionKey = jsonObject.getStr("promotionKey");
|
||||
if (CharSequenceUtil.isEmpty(promotionKey)) {
|
||||
break;
|
||||
}
|
||||
if (CharSequenceUtil.isNotEmpty(jsonObject.getStr("scopeId"))) {
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(Arrays.asList(jsonObject.getStr("scopeId").split(",")), promotionKey);
|
||||
} else {
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(null, promotions.getId());
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(promotionKey);
|
||||
}
|
||||
break;
|
||||
case UPDATE_GOODS_INDEX:
|
||||
@ -159,7 +168,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
List<Goods> goodsList = goodsService.queryListByParams(searchParams);
|
||||
this.updateGoodsIndex(goodsList);
|
||||
} catch (Exception e) {
|
||||
log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
|
||||
log.error("更新商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
case UPDATE_GOODS_INDEX_FIELD:
|
||||
@ -172,7 +181,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
Map<String, Object> updateFields = updateIndexFields.get("updateFields", Map.class);
|
||||
goodsIndexService.updateIndex(queryFields, updateFields);
|
||||
} catch (Exception e) {
|
||||
log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
|
||||
log.error("更新商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
case RESET_GOODS_INDEX:
|
||||
@ -181,13 +190,12 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
List<EsGoodsIndex> goodsIndices = JSONUtil.toList(goodsIdsJsonStr, EsGoodsIndex.class);
|
||||
goodsIndexService.updateBulkIndex(goodsIndices);
|
||||
} catch (Exception e) {
|
||||
log.error("重置商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
|
||||
log.error("重置商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
//审核商品
|
||||
case GOODS_AUDIT:
|
||||
Goods goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class);
|
||||
updateGoodsNum(goods);
|
||||
updateGoodsIndex(goods);
|
||||
break;
|
||||
//删除商品
|
||||
@ -195,19 +203,10 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
try {
|
||||
String goodsIdsJsonStr = new String(messageExt.getBody());
|
||||
for (String goodsId : JSONUtil.toList(goodsIdsJsonStr, String.class)) {
|
||||
Goods goodsById = this.goodsService.getById(goodsId);
|
||||
if (goodsById != null) {
|
||||
this.deleteGoods(goodsById);
|
||||
this.updateGoodsNum(goodsById);
|
||||
List<String> skuIdsByGoodsId = this.goodsSkuService.getSkuIdsByGoodsId(goodsId);
|
||||
if (skuIdsByGoodsId != null && !skuIdsByGoodsId.isEmpty()) {
|
||||
this.goodsIndexService.deleteIndexByIds(skuIdsByGoodsId);
|
||||
}
|
||||
}
|
||||
goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("goodsId", goodsId).build());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("删除商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody()));
|
||||
log.error("删除商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
//规格删除
|
||||
@ -216,6 +215,16 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
List<String> skuIds = JSONUtil.toList(message, String.class);
|
||||
goodsCollectionService.deleteSkuCollection(skuIds);
|
||||
break;
|
||||
case STORE_GOODS_DELETE:
|
||||
try {
|
||||
String storeId = new String(messageExt.getBody());
|
||||
goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("storeId", storeId).build());
|
||||
} catch (RetryException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
log.error("删除店铺商品索引事件执行异常,商品信息: " + new String(messageExt.getBody()), e);
|
||||
}
|
||||
break;
|
||||
//商品评价
|
||||
case GOODS_COMMENT_COMPLETE:
|
||||
MemberEvaluation memberEvaluation = JSONUtil.toBean(new String(messageExt.getBody()), MemberEvaluation.class);
|
||||
@ -244,22 +253,26 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
try {
|
||||
log.info("更新商品索引促销信息: {}", promotionsJsonStr);
|
||||
JSONObject jsonObject = JSONUtil.parseObj(promotionsJsonStr);
|
||||
// 转换为详细的促销信息(注:促销信息必须继承自 BasePromotions,且必须保证派生类存在与sdk包下)
|
||||
BasePromotions promotions = (BasePromotions) jsonObject.get("promotions",
|
||||
ClassLoaderUtil.loadClass(jsonObject.get("promotionsType").toString()));
|
||||
// 获取促销唯一key,由 促销类型 + 促销id 组成
|
||||
String esPromotionKey = jsonObject.get("esPromotionKey").toString();
|
||||
if (PromotionsScopeTypeEnum.PORTION_GOODS.name().equals(promotions.getScopeType())) {
|
||||
PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams();
|
||||
searchParams.setPromotionId(promotions.getId());
|
||||
List<PromotionGoods> promotionGoodsList = this.promotionGoodsService.listFindAll(searchParams);
|
||||
List<String> skuIds = promotionGoodsList.stream().map(PromotionGoods::getSkuId).collect(Collectors.toList());
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(skuIds, promotions.getId());
|
||||
// 更新商品索引促销信息(删除原索引中相关的促销信息,更新索引中促销信息)
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(skuIds, esPromotionKey);
|
||||
this.goodsIndexService.updateEsGoodsIndexByList(promotionGoodsList, promotions, esPromotionKey);
|
||||
} else if (PromotionsScopeTypeEnum.PORTION_GOODS_CATEGORY.name().equals(promotions.getScopeType())) {
|
||||
GoodsSearchParams searchParams = new GoodsSearchParams();
|
||||
searchParams.setCategoryPath(promotions.getScopeId());
|
||||
List<GoodsSku> goodsSkuByList = this.goodsSkuService.getGoodsSkuByList(searchParams);
|
||||
List<String> skuIds = goodsSkuByList.stream().map(GoodsSku::getId).collect(Collectors.toList());
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionId(skuIds, promotions.getId());
|
||||
// 更新商品索引促销信息(删除原索引中相关的促销信息,更新索引中促销信息)
|
||||
this.goodsIndexService.deleteEsGoodsPromotionByPromotionKey(skuIds, esPromotionKey);
|
||||
this.goodsIndexService.updateEsGoodsIndexPromotions(skuIds, promotions, esPromotionKey);
|
||||
} else if (PromotionsScopeTypeEnum.ALL.name().equals(promotions.getScopeType())) {
|
||||
this.goodsIndexService.updateEsGoodsIndexAllByList(promotions, esPromotionKey);
|
||||
@ -303,6 +316,22 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
goodsIndexService.updateBulkIndex(goodsIndices);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新商品索引根据店铺id
|
||||
*
|
||||
* @param storeId 店铺id
|
||||
*/
|
||||
private void updateGoodsIndex(String storeId) {
|
||||
//如果商品通过审核&&并且已上架
|
||||
GoodsSearchParams searchParams = new GoodsSearchParams();
|
||||
searchParams.setStoreId(storeId);
|
||||
for (Goods goods : this.goodsService.queryListByParams(searchParams)) {
|
||||
this.updateGoodsIndex(goods);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品索引
|
||||
*
|
||||
@ -339,20 +368,19 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
*/
|
||||
private void generatorGoodsIndex(Goods goods, List<GoodsSku> goodsSkuList) {
|
||||
int skuSource = 100;
|
||||
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
|
||||
for (GoodsSku goodsSku : goodsSkuList) {
|
||||
EsGoodsIndex esGoodsOld = goodsIndexService.findById(goodsSku.getId());
|
||||
EsGoodsIndex goodsIndex = this.settingUpGoodsIndexData(goods, goodsSku);
|
||||
goodsIndex.setSkuSource(skuSource--);
|
||||
log.info("goodsSku:{}", goodsSku);
|
||||
log.info("esGoodsOld:{}", esGoodsOld);
|
||||
//如果商品库存不为0,并且es中有数据
|
||||
if (goodsSku.getQuantity() > 0 && esGoodsOld == null) {
|
||||
if (goodsSku.getQuantity() > 0) {
|
||||
log.info("生成商品索引 {}", goodsIndex);
|
||||
this.goodsIndexService.addIndex(goodsIndex);
|
||||
} else if (goodsSku.getQuantity() > 0 && esGoodsOld != null) {
|
||||
goodsIndexService.updateIndex(goodsIndex);
|
||||
esGoodsIndices.add(goodsIndex);
|
||||
}
|
||||
}
|
||||
this.goodsIndexService.deleteIndex(MapUtil.builder(new HashMap<String, Object>()).put("goodsId", goods.getId()).build());
|
||||
this.goodsIndexService.addIndex(esGoodsIndices);
|
||||
}
|
||||
|
||||
private EsGoodsIndex settingUpGoodsIndexData(Goods goods, GoodsSku goodsSku) {
|
||||
@ -389,7 +417,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
}
|
||||
}
|
||||
|
||||
if (goodsIndex.getPromotionMap() == null || goodsIndex.getPromotionMap().isEmpty()) {
|
||||
if (goodsIndex.getOriginPromotionMap() == null || goodsIndex.getOriginPromotionMap().isEmpty()) {
|
||||
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsSkuPromotionMap(goodsIndex.getStoreId(), goodsIndex.getId());
|
||||
goodsIndex.setPromotionMapJson(JSONUtil.toJsonStr(goodsCurrentPromotionMap));
|
||||
}
|
||||
@ -421,21 +449,6 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改商品数量
|
||||
*
|
||||
* @param goods 信息体
|
||||
*/
|
||||
private void updateGoodsNum(Goods goods) {
|
||||
try {
|
||||
//更新店铺商品数量
|
||||
assert goods != null;
|
||||
storeService.updateStoreGoodsNum(goods.getStoreId());
|
||||
} catch (Exception e) {
|
||||
log.error("修改商品数量错误");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品购买完成
|
||||
* 1.更新商品购买数量
|
||||
|
@ -34,7 +34,7 @@ public class CouponExecute implements EveryDayExecute {
|
||||
*/
|
||||
@Override
|
||||
public void execute() {
|
||||
//将过期优惠券变更为过期状体
|
||||
//将过期优惠券变更为过期状态
|
||||
LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
|
||||
.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
|
||||
.le(MemberCoupon::getEndTime, new Date())
|
||||
|
@ -1,11 +1,24 @@
|
||||
package cn.lili.timetask.handler.impl.hotwords;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.common.utils.StringUtils;
|
||||
import cn.lili.modules.search.entity.dos.HotWordsHistory;
|
||||
import cn.lili.modules.search.service.HotWordsHistoryService;
|
||||
import cn.lili.modules.system.entity.dos.Setting;
|
||||
import cn.lili.modules.system.entity.dto.HotWordsSetting;
|
||||
import cn.lili.modules.system.entity.dto.HotWordsSettingItem;
|
||||
import cn.lili.modules.system.entity.enums.SettingEnum;
|
||||
import cn.lili.modules.system.service.SettingService;
|
||||
import cn.lili.timetask.handler.EveryDayExecute;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.DefaultTypedTuple;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
@ -18,13 +31,54 @@ public class HotWordsEveryDayTaskExecute implements EveryDayExecute {
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private HotWordsHistoryService hotWordsHistoryService;
|
||||
@Autowired
|
||||
private SettingService settingService;
|
||||
|
||||
/**
|
||||
* 执行每日任务
|
||||
*/
|
||||
@Override
|
||||
public void execute() {
|
||||
//获取大于0分的热词
|
||||
Set<DefaultTypedTuple> tuples = cache.zRangeByScore(CachePrefix.HOT_WORD.getPrefix(), 1, Integer.MAX_VALUE);
|
||||
//如果任务不为空
|
||||
if (!CollectionUtils.isEmpty(tuples)) {
|
||||
|
||||
//因为是第二天统计第一天的数据,所以这里获取昨天凌晨的时间
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - 1);
|
||||
|
||||
//批量保存热词
|
||||
List<HotWordsHistory> hotWordsHistories = new ArrayList<>();
|
||||
for (DefaultTypedTuple tuple : tuples) {
|
||||
String keywords = (String) tuple.getValue();
|
||||
Double score = tuple.getScore();
|
||||
hotWordsHistories.add(new HotWordsHistory(keywords, score.intValue(), calendar.getTime()));
|
||||
}
|
||||
|
||||
hotWordsHistoryService.saveBatch(hotWordsHistories);
|
||||
}
|
||||
//移除昨日的热搜词
|
||||
cache.remove(CachePrefix.HOT_WORD.getPrefix());
|
||||
|
||||
//设置今日默认热词
|
||||
Setting setting = settingService.get(SettingEnum.HOT_WORDS.name());
|
||||
if (setting == null) {
|
||||
return;
|
||||
}
|
||||
HotWordsSetting hotWordsSetting = JSONUtil.toBean(setting.getSettingValue(), HotWordsSetting.class);
|
||||
List<HotWordsSettingItem> hotWordsSettingItems = hotWordsSetting.getHotWordsSettingItems();
|
||||
if (hotWordsSettingItems != null && !hotWordsSettingItems.isEmpty()) {
|
||||
for (HotWordsSettingItem hotWordsSettingItem : hotWordsSettingItems) {
|
||||
cache.zAdd(CachePrefix.HOT_WORD.getPrefix(), hotWordsSettingItem.getScore(), hotWordsSettingItem.getKeywords());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -13,6 +13,7 @@ import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -54,8 +55,16 @@ public class OnlineMemberStatistics implements EveryHourExecute {
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Calendar finalCalendar = calendar;
|
||||
|
||||
AtomicReference<Integer> lastNum = new AtomicReference<>(0);
|
||||
onlineMemberVOS = onlineMemberVOS.stream()
|
||||
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(finalCalendar.getTime()))
|
||||
.filter(onlineMemberVO -> {
|
||||
//如果为过滤参数,则记录为过期参数,则为统一时段上一周期的在线人数
|
||||
if (!onlineMemberVO.getDate().after(finalCalendar.getTime())) {
|
||||
lastNum.set(onlineMemberVO.getNum());
|
||||
}
|
||||
return onlineMemberVO.getDate().after(finalCalendar.getTime());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//计入新数据
|
||||
@ -63,7 +72,7 @@ public class OnlineMemberStatistics implements EveryHourExecute {
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size()));
|
||||
onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size(), lastNum.get()));
|
||||
|
||||
//写入缓存
|
||||
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
|
||||
@ -95,7 +104,7 @@ public class OnlineMemberStatistics implements EveryHourExecute {
|
||||
onlineMemberVOS = onlineMemberVOS.stream()
|
||||
.filter(onlineMemberVO -> onlineMemberVO.getDate().after(calendar.getTime()))
|
||||
.collect(Collectors.toList());
|
||||
onlineMemberVOS.add(new OnlineMemberVO(time, num));
|
||||
onlineMemberVOS.add(new OnlineMemberVO(time, num, num));
|
||||
|
||||
//写入缓存
|
||||
cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
|
||||
|
@ -0,0 +1,49 @@
|
||||
package cn.lili.timetask.handler.impl.store;
|
||||
|
||||
import cn.lili.modules.goods.service.GoodsSkuService;
|
||||
import cn.lili.modules.store.entity.dos.Store;
|
||||
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
|
||||
import cn.lili.modules.store.service.StoreService;
|
||||
import cn.lili.timetask.handler.EveryDayExecute;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 店铺信息更新
|
||||
*
|
||||
* @author Chopper
|
||||
* @since 2021/3/15 5:30 下午
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StoreExecute implements EveryDayExecute {
|
||||
/**
|
||||
* 店铺
|
||||
*/
|
||||
@Autowired
|
||||
private StoreService storeService;
|
||||
|
||||
@Autowired
|
||||
private GoodsSkuService goodsSkuService;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
//获取所有开启的店铺
|
||||
List<Store> storeList = storeService.list(new LambdaQueryWrapper<Store>().eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()));
|
||||
|
||||
for (Store store : storeList) {
|
||||
try {
|
||||
Long num = goodsSkuService.countSkuNum(store.getId());
|
||||
storeService.updateStoreGoodsNum(store.getId(), num);
|
||||
} catch (Exception e) {
|
||||
log.error("店铺id为{},更新商品数量失败", store.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
@ -67,7 +67,7 @@ spring:
|
||||
default-datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: lilishop
|
||||
maxActive: 20
|
||||
|
651
deploy-api.yml
Normal file
651
deploy-api.yml
Normal file
@ -0,0 +1,651 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: lilishop-service
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: buyer-api-service
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: buyer-api-service
|
||||
app.kubernetes.io/instance: api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: "8888"
|
||||
nodePort: 30888
|
||||
port: 8888
|
||||
targetPort: buyer8888
|
||||
selector:
|
||||
lilishop.service: buyer-api
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: common-api-service
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: common-api-service
|
||||
app.kubernetes.io/instance: api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: "8890"
|
||||
nodePort: 30890
|
||||
port: 8890
|
||||
targetPort: common8890
|
||||
selector:
|
||||
lilishop.service: common-api
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: seller-api-service
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: seller-api-service
|
||||
app.kubernetes.io/instance: api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: "8889"
|
||||
nodePort: 30889
|
||||
port: 8889
|
||||
targetPort: seller8889
|
||||
selector:
|
||||
lilishop.service: seller-api
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: manager-api-service
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: manager-api-service
|
||||
app.kubernetes.io/instance: api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: "8887"
|
||||
nodePort: 30887
|
||||
port: 8887
|
||||
targetPort: manager8887
|
||||
selector:
|
||||
lilishop.service: manager-api
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: api-config
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: mysql-db-config
|
||||
app.kubernetes.io/instance: mysql-single
|
||||
app.kubernetes.io/version: "8.0.28"
|
||||
app.kubernetes.io/component: database
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
data:
|
||||
application.yml: |
|
||||
server:
|
||||
servlet:
|
||||
context-path: /
|
||||
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
threads:
|
||||
min-spare: 50
|
||||
max: 1000
|
||||
|
||||
# 与Spring Boot 2一样,默认情况下,大多数端点都不通过http公开,我们公开了所有端点。对于生产,您应该仔细选择要公开的端点。
|
||||
management:
|
||||
# health:
|
||||
# elasticsearch:
|
||||
# enabled: false
|
||||
# datasource:
|
||||
# enabled: false
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
spring:
|
||||
# 要在其中注册的Spring Boot Admin Server的URL。
|
||||
boot:
|
||||
admin:
|
||||
client:
|
||||
url: http://192.168.0.116:8000
|
||||
cache:
|
||||
type: redis
|
||||
# Redis
|
||||
redis:
|
||||
host: redis-service.lilishop-middleware
|
||||
port: 6379
|
||||
password: lilishop
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数(使用负值表示没有限制) 默认 8
|
||||
max-active: 200
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
|
||||
max-wait: 20
|
||||
# 连接池中的最大空闲连接 默认 8
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接 默认 8
|
||||
min-idle: 8
|
||||
# 文件大小上传配置
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 20MB
|
||||
max-request-size: 20MB
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
serialization:
|
||||
#关闭jackson 对json做解析
|
||||
fail-on-empty-beans: false
|
||||
|
||||
shardingsphere:
|
||||
datasource:
|
||||
# 数据库名称,可自定义,可以为多个,以逗号隔开,每个在这里定义的库,都要在下面定义连接属性
|
||||
names: default-datasource
|
||||
default-datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://mysql.lilishop-middleware:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: lilishop
|
||||
maxActive: 50
|
||||
initialSize: 20
|
||||
maxWait: 60000
|
||||
minIdle: 5
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
#是否缓存preparedStatement,也就是PSCache。在mysql下建议关闭。 PSCache对支持游标的数据库性能提升巨大,比如说oracle。
|
||||
poolPreparedStatements: false
|
||||
#要启用PSCache,-1为关闭 必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true 可以把这个数值配置大一些,比如说100
|
||||
maxOpenPreparedStatements: -1
|
||||
#配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
filters: stat,wall,log4j2
|
||||
#通过connectProperties属性来打开mergeSql功能;慢SQL记录
|
||||
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
#合并多个DruidDataSource的监控数据
|
||||
useGlobalDataSourceStat: true
|
||||
loginUsername: druid
|
||||
loginPassword: druid
|
||||
# sharding:
|
||||
# default-data-source-name: default-datasource
|
||||
# #需要拆分的表,可以设置多个 在 li_order 级别即可
|
||||
# tables:
|
||||
# #需要进行分表的逻辑表名
|
||||
# li_order:
|
||||
# #实际的表结点,下面代表的是li_order_为开头的所有表,如果能确定表的范围例如按月份分表,这里的写法是data2020.li_order_$->{2020..2021}_$->{01..12} 表示例如 li_order_2020_01 li_order_2020_03 li_order_2021_01
|
||||
# actual-data-nodes: data2020.li_order_$->{2019..2021}_$->{01..12}
|
||||
# table-strategy:
|
||||
# # 分表策略,根据创建日期
|
||||
# standard:
|
||||
# sharding-column: create_time
|
||||
# #分表策略
|
||||
# precise-algorithm-class-name: cn.lili.mybatis.sharding.CreateTimeShardingTableAlgorithm
|
||||
# #范围查询实现
|
||||
# range-algorithm-class-name: cn.lili.mybatis.sharding.CreateTimeShardingTableAlgorithm
|
||||
props:
|
||||
#是否打印逻辑SQL语句和实际SQL语句,建议调试时打印,在生产环境关闭
|
||||
sql:
|
||||
show: true
|
||||
|
||||
# 忽略鉴权url
|
||||
ignored:
|
||||
urls:
|
||||
- /editor-app/**
|
||||
- /actuator**
|
||||
- /actuator/**
|
||||
- /MP_verify_qSyvBPhDsPdxvOhC.txt
|
||||
- /weixin/**
|
||||
- /source/**
|
||||
- /store/passport/login/**
|
||||
- /store/passport/login/refresh/**
|
||||
- /common/common/slider/**
|
||||
- /common/common/sms/**
|
||||
- /buyer/payment/cashier/**
|
||||
- /buyer/other/pageData/**
|
||||
- /buyer/other/article/**
|
||||
- /buyer/goods/**
|
||||
- /buyer/store/**
|
||||
- /buyer/passport/connect/**
|
||||
- /buyer/members/**
|
||||
- /buyer/passport/member/**
|
||||
- /buyer/passport/member/refresh/**
|
||||
- /buyer/promotion/pintuan/**
|
||||
- /buyer/promotion/seckill/**
|
||||
- /buyer/promotion/pointsGoods/**
|
||||
- /buyer/promotion/coupon
|
||||
- /buyer/member/evaluation/**/goodsEvaluation
|
||||
- /buyer/member/evaluation/**/evaluationNumber
|
||||
- /buyer/other/appVersion/**
|
||||
- /buyer/broadcast/studio/**
|
||||
- /manager/passport/user/login
|
||||
- /manager/passport/user/refresh/**
|
||||
- /manager/other/elasticsearch
|
||||
- /manager/other/customWords
|
||||
- /druid/**
|
||||
- /swagger-ui.html
|
||||
- /doc.html
|
||||
- /swagger-resources/**
|
||||
- /swagger/**
|
||||
- /webjars/**
|
||||
- /v2/api-docs**
|
||||
- /configuration/ui
|
||||
- /boot-admin
|
||||
- /manager/promotion/seckill/init
|
||||
- /**/*.js
|
||||
- /**/*.css
|
||||
- /**/*.png
|
||||
- /**/*.ico
|
||||
|
||||
# Swagger界面内容配置
|
||||
swagger:
|
||||
title: lilishop API接口文档
|
||||
description: lilishop Api Documentation
|
||||
version: 4.2.2
|
||||
termsOfServiceUrl: https://pickmall.cn
|
||||
contact:
|
||||
name: lili
|
||||
url: https://pickmall.cn
|
||||
email: admin@pickmall.com
|
||||
|
||||
# Mybatis-plus
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
configuration:
|
||||
#缓存开启
|
||||
cache-enabled: true
|
||||
#日志
|
||||
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
|
||||
# 日志
|
||||
logging:
|
||||
# 输出级别
|
||||
level:
|
||||
cn.lili: info
|
||||
# org.hibernate: debug
|
||||
# org.springframework: debug
|
||||
file:
|
||||
# 指定路径
|
||||
path: logs
|
||||
logback:
|
||||
rollingpolicy:
|
||||
# 最大保存天数
|
||||
max-history: 7
|
||||
# 每个文件最大大小
|
||||
max-file-size: 5MB
|
||||
#加密参数
|
||||
jasypt:
|
||||
encryptor:
|
||||
password: lili
|
||||
|
||||
|
||||
lili:
|
||||
#验证码设置
|
||||
verification-code:
|
||||
#图形验证码有效时间 秒 包含滑块验证码有效时间, 以及验证通过之后,缓存中存储的验证结果有效时间
|
||||
effectiveTime: 300
|
||||
#水印
|
||||
watermark: LILI-SHOP
|
||||
#干扰项数量 最大2 默认0
|
||||
interfereNum: 1
|
||||
#允许误差像素
|
||||
faultTolerant: 3
|
||||
#短信模版配置
|
||||
sms:
|
||||
#登录
|
||||
LOGIN: SMS_205755300
|
||||
#注册
|
||||
REGISTER: SMS_205755298
|
||||
#找回密码
|
||||
FIND_USER: SMS_205755301
|
||||
#设置密码
|
||||
UPDATE_PASSWORD: SMS_205755297
|
||||
#支付密码
|
||||
WALLET_PASSWORD: SMS_205755301
|
||||
system:
|
||||
isDemoSite: false
|
||||
isTestModel: true
|
||||
# 脱敏级别:
|
||||
# 0:不做脱敏处理
|
||||
# 1:管理端用户手机号等信息脱敏
|
||||
# 2:商家端信息脱敏(为2时,表示管理端,商家端同时脱敏)
|
||||
sensitiveLevel: 1
|
||||
|
||||
statistics:
|
||||
# 在线人数统计 X 小时。这里设置48,即统计过去48小时每小时在线人数
|
||||
onlineMember: 48
|
||||
# 当前在线人数刷新时间间隔,单位秒,设置为600,则每10分钟刷新一次
|
||||
currentOnlineUpdate: 600
|
||||
#qq lbs 申请
|
||||
lbs:
|
||||
key: 4BYBZ-7MT6S-PUAOA-6BNWL-FJUD7-UUFXT
|
||||
sk: zhNKVrJK6UPOhqIjn8AQvG37b9sz6
|
||||
#域名
|
||||
domain:
|
||||
pc: http://192.168.0.116:8888
|
||||
wap: http://192.168.0.116:8888
|
||||
seller: http://192.168.0.116:8888
|
||||
admin: http://192.168.0.116:8888
|
||||
#api地址
|
||||
api:
|
||||
buyer: http://192.168.0.116:8888
|
||||
base: http://192.168.0.116:8888
|
||||
manager: http://192.168.0.116:8888
|
||||
seller: http://192.168.0.116:8888
|
||||
|
||||
# jwt 细节设定
|
||||
jwt-setting:
|
||||
# token过期时间(分钟)
|
||||
tokenExpireTime: 30
|
||||
|
||||
# 使用Spring @Cacheable注解失效时间
|
||||
cache:
|
||||
# 过期时间 单位秒 永久不过期设为-1
|
||||
timeout: 1500
|
||||
#多线程配置
|
||||
thread:
|
||||
corePoolSize: 5
|
||||
maxPoolSize: 50
|
||||
queueCapacity: 50
|
||||
data:
|
||||
elasticsearch:
|
||||
cluster-name: elasticsearch
|
||||
cluster-nodes: elasticsearch.lilishop-middleware:9200
|
||||
index:
|
||||
number-of-replicas: 0
|
||||
number-of-shards: 3
|
||||
index-prefix: lili
|
||||
schema: http
|
||||
# account:
|
||||
# username: elastic
|
||||
# password: LiLiShopES
|
||||
|
||||
logstash:
|
||||
server: logstash-service.lilishop-middleware:4560
|
||||
rocketmq:
|
||||
promotion-topic: lili_promotion_topic
|
||||
promotion-group: lili_promotion_group
|
||||
msg-ext-topic: lili_msg_topic
|
||||
msg-ext-group: lili_msg_group
|
||||
goods-topic: lili_goods_topic
|
||||
goods-group: lili_goods_group
|
||||
order-topic: lili_order_topic
|
||||
order-group: lili_order_group
|
||||
member-topic: lili_member_topic
|
||||
member-group: lili_member_group
|
||||
other-topic: lili_other_topic
|
||||
other-group: lili_other_group
|
||||
notice-topic: lili_notice_topic
|
||||
notice-group: lili_notice_group
|
||||
notice-send-topic: lili_send_notice_topic
|
||||
notice-send-group: lili_send_notice_group
|
||||
after-sale-topic: lili_after_sale_topic
|
||||
after-sale-group: lili_after_sale_group
|
||||
rocketmq:
|
||||
name-server: rocketmq.lilishop-middleware:9876
|
||||
isVIPChannel: false
|
||||
producer:
|
||||
group: lili_group
|
||||
send-message-timeout: 30000
|
||||
|
||||
xxl:
|
||||
job:
|
||||
admin:
|
||||
addresses: http://xxl-job-service.lilishop-middleware:9001/xxl-job-admin
|
||||
executor:
|
||||
appname: xxl-job-executor-lilishop
|
||||
address:
|
||||
ip:
|
||||
port: 8891
|
||||
logpath: ./xxl-job/executor
|
||||
logretentiondays: 7
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: buyer-api
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: buyer-api-service
|
||||
app.kubernetes.io/instance: buyer-api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
lilishop.service: buyer-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
lilishop.service: buyer-api
|
||||
spec:
|
||||
containers:
|
||||
- image: 192.168.0.108:31320/buyer-api:4.2.4.1
|
||||
name: buyer-api
|
||||
env:
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
- name: JAVA_OPTS
|
||||
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
|
||||
ports:
|
||||
- name: buyer8888
|
||||
containerPort: 8888
|
||||
volumeMounts:
|
||||
- mountPath: /application.yml
|
||||
name: application-yml
|
||||
subPath: application.yml
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: api-config
|
||||
name: application-yml
|
||||
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: common-api
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: common-api-service
|
||||
app.kubernetes.io/instance: common-api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
lilishop.service: common-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
lilishop.service: common-api
|
||||
spec:
|
||||
containers:
|
||||
- image: 192.168.0.108:31320/common-api:4.2.4.1
|
||||
name: common-api
|
||||
env:
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
- name: JAVA_OPTS
|
||||
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
|
||||
ports:
|
||||
- name: common8890
|
||||
containerPort: 8890
|
||||
volumeMounts:
|
||||
- mountPath: /application.yml
|
||||
name: application-yml
|
||||
subPath: application.yml
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: api-config
|
||||
name: application-yml
|
||||
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: seller-api
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: seller-api-service
|
||||
app.kubernetes.io/instance: seller-api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
lilishop.service: seller-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
lilishop.service: seller-api
|
||||
spec:
|
||||
containers:
|
||||
- image: 192.168.0.108:31320/seller-api:4.2.4.1
|
||||
name: seller-api
|
||||
env:
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
- name: JAVA_OPTS
|
||||
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
|
||||
ports:
|
||||
- name: seller8889
|
||||
containerPort: 8889
|
||||
volumeMounts:
|
||||
- mountPath: /application.yml
|
||||
name: application-yml
|
||||
subPath: application.yml
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: api-config
|
||||
name: application-yml
|
||||
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: manager-api
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: manager-api-service
|
||||
app.kubernetes.io/instance: manager-api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
lilishop.service: manager-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
lilishop.service: manager-api
|
||||
spec:
|
||||
containers:
|
||||
- image: 192.168.0.108:31320/manager-api:4.2.4.1
|
||||
name: manager-api
|
||||
env:
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
- name: JAVA_OPTS
|
||||
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
|
||||
ports:
|
||||
- name: manager8887
|
||||
containerPort: 8887
|
||||
volumeMounts:
|
||||
- mountPath: /application.yml
|
||||
name: application-yml
|
||||
subPath: application.yml
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: api-config
|
||||
name: application-yml
|
||||
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: consumer
|
||||
namespace: lilishop-service
|
||||
labels:
|
||||
app.kubernetes.io/name: consumer-service
|
||||
app.kubernetes.io/instance: buyer-api
|
||||
app.kubernetes.io/version: "4.2.4.1"
|
||||
app.kubernetes.io/component: api
|
||||
app.kubernetes.io/part-of: lilishop
|
||||
tier: "api-service"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
lilishop.service: consumer
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
lilishop.service: consumer
|
||||
spec:
|
||||
containers:
|
||||
- image: 192.168.0.108:31320/consumer:4.2.4.1
|
||||
name: consumer
|
||||
env:
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
- name: JAVA_OPTS
|
||||
value: -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Xms128m -Xmx256m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC
|
||||
volumeMounts:
|
||||
- mountPath: /application.yml
|
||||
name: application-yml
|
||||
subPath: application.yml
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: api-config
|
||||
name: application-yml
|
@ -132,6 +132,7 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.29</version>
|
||||
</dependency>
|
||||
<!-- Redis-->
|
||||
<dependency>
|
||||
@ -143,6 +144,12 @@
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>${redisson}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -422,6 +429,13 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
@ -465,16 +465,19 @@ public enum CachePrefix {
|
||||
*/
|
||||
INIT_INDEX_FLAG,
|
||||
|
||||
/**
|
||||
* 店铺
|
||||
*/
|
||||
STORE,
|
||||
/**
|
||||
* 店铺分类
|
||||
*/
|
||||
STORE_CATEGORY,
|
||||
/**
|
||||
* 用户菜单
|
||||
*/
|
||||
MENU_USER_ID,
|
||||
/**
|
||||
* 用户菜单
|
||||
* <p>
|
||||
* 这个缓存并非永久缓存,而是300秒缓存,也就是说修改用户关联的部门,关联的角色,
|
||||
* 部门关联的角色,角色关联的菜单等等,最多需要5分钟才能生效
|
||||
*/
|
||||
STORE_MENU_USER_ID,
|
||||
/**
|
||||
|
@ -6,6 +6,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 要实现对象的缓存,定义自己的序列化和反序列化器。使用阿里的fastjson来实现的比较多
|
||||
@ -13,8 +14,8 @@ import java.nio.charset.Charset;
|
||||
* @author Bulbasaur
|
||||
*/
|
||||
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
private Class<T> clazz;
|
||||
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
private final Class<T> clazz;
|
||||
|
||||
public FastJsonRedisSerializer(Class<T> clazz) {
|
||||
super();
|
||||
@ -26,7 +27,10 @@ public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||
if (null == t) {
|
||||
return new byte[0];
|
||||
}
|
||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
||||
return JSON.toJSONString(t,
|
||||
SerializerFeature.WriteClassName,
|
||||
SerializerFeature.DisableCircularReferenceDetect)
|
||||
.getBytes(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,7 +11,6 @@ import org.redisson.config.ClusterServersConfig;
|
||||
import org.redisson.config.Config;
|
||||
import org.redisson.config.SentinelServersConfig;
|
||||
import org.redisson.config.SingleServerConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@ -56,13 +55,11 @@ import java.util.Map;
|
||||
public class RedisConfig extends CachingConfigurerSupport {
|
||||
|
||||
|
||||
private static final String REDIS_PREFIX = "redis://";
|
||||
|
||||
@Value("${lili.cache.timeout:7200}")
|
||||
private Integer timeout;
|
||||
|
||||
@Autowired
|
||||
private RedisProperties redisProperties;
|
||||
|
||||
|
||||
/**
|
||||
* 当有多个管理器的时候,必须使用该注解在一个管理器上注释:表示该管理器为默认的管理器
|
||||
*
|
||||
@ -101,7 +98,7 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||
public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
|
||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||
//使用fastjson序列化
|
||||
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
|
||||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||
//value值的序列化采用fastJsonRedisSerializer
|
||||
template.setValueSerializer(fastJsonRedisSerializer);
|
||||
template.setHashValueSerializer(fastJsonRedisSerializer);
|
||||
@ -113,16 +110,15 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
public RedissonClient redisson() {
|
||||
public RedissonClient redisson(RedisProperties redisProperties) {
|
||||
Config config = new Config();
|
||||
|
||||
if (redisProperties.getSentinel() != null && !redisProperties.getSentinel().getNodes().isEmpty()) {
|
||||
// 哨兵模式
|
||||
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
|
||||
sentinelServersConfig.setMasterName(redisProperties.getSentinel().getMaster());
|
||||
List<String> sentinelAddress = new ArrayList<>();
|
||||
for (String node : redisProperties.getCluster().getNodes()) {
|
||||
sentinelAddress.add("redis://" + node);
|
||||
sentinelAddress.add(REDIS_PREFIX + node);
|
||||
}
|
||||
sentinelServersConfig.setSentinelAddresses(sentinelAddress);
|
||||
if (CharSequenceUtil.isNotEmpty(redisProperties.getSentinel().getPassword())) {
|
||||
@ -133,7 +129,7 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||
ClusterServersConfig clusterServersConfig = config.useClusterServers();
|
||||
List<String> clusterNodes = new ArrayList<>();
|
||||
for (String node : redisProperties.getCluster().getNodes()) {
|
||||
clusterNodes.add("redis://" + node);
|
||||
clusterNodes.add(REDIS_PREFIX + node);
|
||||
}
|
||||
clusterServersConfig.setNodeAddresses(clusterNodes);
|
||||
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
|
||||
@ -141,10 +137,11 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||
}
|
||||
} else {
|
||||
SingleServerConfig singleServerConfig = config.useSingleServer();
|
||||
singleServerConfig.setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort());
|
||||
singleServerConfig.setAddress(REDIS_PREFIX + redisProperties.getHost() + ":" + redisProperties.getPort());
|
||||
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
|
||||
singleServerConfig.setPassword(redisProperties.getPassword());
|
||||
}
|
||||
singleServerConfig.setPingConnectionInterval(1000);
|
||||
}
|
||||
|
||||
return Redisson.create(config);
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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, "当前优惠券不允许主动领取"),
|
||||
|
||||
/**
|
||||
* 拼团
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当天的开始时间
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤特殊字符串
|
||||
*
|
||||
|
@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
@ -124,7 +123,7 @@ public abstract class BaseElasticsearchService {
|
||||
" \"type\": \"keyword\"\n" +
|
||||
" },\n" +
|
||||
" \"type\": {\n" +
|
||||
" \"type\": \"long\"\n" +
|
||||
" \"type\": \"integer\"\n" +
|
||||
" },\n" +
|
||||
" \"value\": {\n" +
|
||||
" \"type\": \"keyword\"\n" +
|
||||
@ -165,14 +164,8 @@ public abstract class BaseElasticsearchService {
|
||||
" \"type\": \"long\"\n" +
|
||||
" },\n" +
|
||||
" \"releaseTime\": {\n" +
|
||||
" \"type\": \"text\",\n" +
|
||||
" \"fielddata\": true, \n" +
|
||||
" \"fields\": {\n" +
|
||||
" \"keyword\": {\n" +
|
||||
" \"type\": \"keyword\",\n" +
|
||||
" \"ignore_above\": 256\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" \"type\": \"date\",\n" +
|
||||
" \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\"\n" +
|
||||
" },\n" +
|
||||
" \"categoryPath\": {\n" +
|
||||
" \"type\": \"text\",\n" +
|
||||
@ -348,20 +341,20 @@ public abstract class BaseElasticsearchService {
|
||||
|
||||
PutMappingRequest request = new PutMappingRequest(index).source(source, XContentType.JSON);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
AtomicReference<AcknowledgedResponse> response = new AtomicReference<>();
|
||||
client.indices().putMappingAsync(
|
||||
request,
|
||||
RequestOptions.DEFAULT,
|
||||
new ActionListener<AcknowledgedResponse>() {
|
||||
@Override
|
||||
public void onResponse(AcknowledgedResponse r) {
|
||||
response.set(r);
|
||||
latch.countDown();
|
||||
log.info("创建索引mapping成功:{}", r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
latch.countDown();
|
||||
log.error("创建索引mapping失败", e);
|
||||
}
|
||||
});
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
|
@ -16,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.IOException;
|
||||
@ -69,11 +68,6 @@ public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
|
||||
return client;
|
||||
}
|
||||
|
||||
@Bean("elasticsearchRestTemplate")
|
||||
public ElasticsearchRestTemplate elasticsearchRestTemplate() {
|
||||
return new ElasticsearchRestTemplate(this.client);
|
||||
}
|
||||
|
||||
private HttpHost[] getHttpHosts() {
|
||||
List<String> clusterNodes = elasticsearchProperties.getClusterNodes();
|
||||
HttpHost[] httpHosts = new HttpHost[clusterNodes.size()];
|
||||
|
@ -112,4 +112,11 @@ public interface ConnectService extends IService<Connect> {
|
||||
* @return
|
||||
*/
|
||||
Connect queryConnect(ConnectQueryDTO connectQueryDTO);
|
||||
|
||||
/**
|
||||
* 根据会员id删除记录
|
||||
*
|
||||
* @param userId 会员id
|
||||
*/
|
||||
void deleteByMemberId(String userId);
|
||||
}
|
@ -8,7 +8,9 @@ import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.common.context.ThreadContextHolder;
|
||||
import cn.lili.common.enums.ClientTypeEnum;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.event.TransactionCommitSendMQEvent;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.common.properties.RocketmqCustomProperties;
|
||||
import cn.lili.common.security.AuthUser;
|
||||
import cn.lili.common.security.context.UserContext;
|
||||
import cn.lili.common.security.token.Token;
|
||||
@ -29,11 +31,13 @@ import cn.lili.modules.system.entity.dto.connect.WechatConnectSetting;
|
||||
import cn.lili.modules.system.entity.dto.connect.dto.WechatConnectSettingItem;
|
||||
import cn.lili.modules.system.entity.enums.SettingEnum;
|
||||
import cn.lili.modules.system.service.SettingService;
|
||||
import cn.lili.rocketmq.tags.MemberTagsEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -66,6 +70,14 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
private MemberTokenGenerate memberTokenGenerate;
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
/**
|
||||
* RocketMQ 配置
|
||||
*/
|
||||
@Autowired
|
||||
private RocketmqCustomProperties rocketmqCustomProperties;
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -89,6 +101,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
}
|
||||
return memberTokenGenerate.createToken(member, longTerm);
|
||||
} catch (NoPermissionException e) {
|
||||
log.error("联合登陆失败:", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -121,7 +134,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
|
||||
@Override
|
||||
public void bind(String unionId, String type) {
|
||||
AuthUser authUser = UserContext.getCurrentUser();
|
||||
AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
|
||||
Connect connect = new Connect(authUser.getId(), unionId, type);
|
||||
this.save(connect);
|
||||
}
|
||||
@ -160,6 +173,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Token miniProgramAutoLogin(WechatMPLoginParams params) {
|
||||
|
||||
Object cacheData = cache.get(CachePrefix.WECHAT_SESSION_PARAMS.getPrefix() + params.getUuid());
|
||||
@ -186,8 +200,8 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
/**
|
||||
* 通过微信返回等code 获取openid 等信息
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
* @param code 微信code
|
||||
* @return 微信返回的信息
|
||||
*/
|
||||
public JSONObject getConnect(String code) {
|
||||
WechatConnectSettingItem setting = getWechatMPSetting();
|
||||
@ -208,11 +222,12 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
* @param params 微信小程序自动登录参数
|
||||
* @param openId 微信openid
|
||||
* @param unionId 微信unionid
|
||||
* @return
|
||||
* @return token
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Token phoneMpBindAndLogin(String sessionKey, WechatMPLoginParams params, String openId, String unionId) {
|
||||
String encryptedData = params.getEncryptedData(), iv = params.getIv();
|
||||
String encryptedData = params.getEncryptedData();
|
||||
String iv = params.getIv();
|
||||
JSONObject userInfo = this.getUserInfo(encryptedData, sessionKey, iv);
|
||||
log.info("联合登陆返回:{}", userInfo.toString());
|
||||
String phone = (String) userInfo.get("purePhoneNumber");
|
||||
@ -232,6 +247,8 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
memberService.save(newMember);
|
||||
newMember = memberService.findByUsername(newMember.getUsername());
|
||||
bindMpMember(openId, unionId, newMember);
|
||||
// 发送会员注册信息
|
||||
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), newMember));
|
||||
return memberTokenGenerate.createToken(newMember, true);
|
||||
}
|
||||
|
||||
@ -245,6 +262,13 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByMemberId(String userId) {
|
||||
LambdaQueryWrapper<Connect> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Connect::getUserId, userId);
|
||||
this.remove(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员绑定 绑定微信小程序
|
||||
* <p>
|
||||
@ -252,9 +276,9 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
* 这样,微信小程序注册之后,其他app 公众号页面,都可以实现绑定自动登录功能
|
||||
* </p>
|
||||
*
|
||||
* @param openId
|
||||
* @param unionId
|
||||
* @param member
|
||||
* @param openId 微信openid
|
||||
* @param unionId 微信unionid
|
||||
* @param member 会员
|
||||
*/
|
||||
private void bindMpMember(String openId, String unionId, Member member) {
|
||||
|
||||
@ -265,7 +289,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
lambdaQueryWrapper.eq(Connect::getUnionId, unionId);
|
||||
lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT.name());
|
||||
List<Connect> connects = this.list(lambdaQueryWrapper);
|
||||
if (connects.size() == 0) {
|
||||
if (connects.isEmpty()) {
|
||||
Connect connect = new Connect();
|
||||
connect.setUnionId(unionId);
|
||||
connect.setUserId(member.getId());
|
||||
@ -274,7 +298,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
|
||||
}
|
||||
}//如果openid 不为空 则为账号绑定openid
|
||||
if (CharSequenceUtil.isNotEmpty(openId)) {
|
||||
LambdaQueryWrapper<Connect> lambdaQueryWrapper = new LambdaQueryWrapper();
|
||||
LambdaQueryWrapper<Connect> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(Connect::getUnionId, openId);
|
||||
lambdaQueryWrapper.eq(Connect::getUnionType, ConnectEnum.WECHAT_MP_OPEN_ID.name());
|
||||
List<Connect> connects = this.list(lambdaQueryWrapper);
|
||||
|
@ -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 = "提成金额")
|
||||
|
@ -73,6 +73,7 @@ public class DistributionCashServiceImpl extends ServiceImpl<DistributionCashMap
|
||||
}
|
||||
//将提现金额存入冻结金额,扣减可提现金额
|
||||
distribution.setCanRebate(CurrencyUtil.sub(distribution.getCanRebate(), applyMoney));
|
||||
distribution.setCommissionFrozen(CurrencyUtil.add(distribution.getCommissionFrozen(), applyMoney));
|
||||
distributionService.updateById(distribution);
|
||||
//提现申请记录
|
||||
DistributionCash distributionCash = new DistributionCash("D" + SnowFlake.getId(), distribution.getId(), applyMoney, distribution.getMemberName());
|
||||
|
@ -94,6 +94,9 @@ public class DistributionOrderServiceImpl extends ServiceImpl<DistributionOrderM
|
||||
//循环店铺流水记录判断是否包含分销商品
|
||||
//包含分销商品则进行记录分销订单、计算分销总额
|
||||
for (StoreFlow storeFlow : storeFlowList) {
|
||||
if (storeFlow.getDistributionRebate() == null || storeFlow.getDistributionRebate() == 0) {
|
||||
continue;
|
||||
}
|
||||
rebate = CurrencyUtil.add(rebate, storeFlow.getDistributionRebate());
|
||||
DistributionOrder distributionOrder = new DistributionOrder(storeFlow);
|
||||
distributionOrder.setDistributionId(order.getDistributionId());
|
||||
|
@ -0,0 +1,17 @@
|
||||
package cn.lili.modules.file.entity.enums;
|
||||
|
||||
import com.aliyun.oss.OSS;
|
||||
|
||||
/**
|
||||
* OssEnum
|
||||
*
|
||||
* @author Chopper
|
||||
* @version v1.0
|
||||
* 2022-06-06 11:23
|
||||
*/
|
||||
public enum OssEnum {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
ALI_OSS, MINIO;
|
||||
}
|
@ -1,16 +1,23 @@
|
||||
package cn.lili.modules.file.plugin;
|
||||
|
||||
import cn.lili.modules.file.entity.enums.OssEnum;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件管理插件
|
||||
* 文件插件接口
|
||||
*
|
||||
* @author Chopper
|
||||
*/
|
||||
public interface FileManagerPlugin {
|
||||
public interface FilePlugin {
|
||||
|
||||
|
||||
/**
|
||||
* 插件名称
|
||||
*/
|
||||
OssEnum pluginName();
|
||||
|
||||
/**
|
||||
* 文件路径上传
|
||||
*
|
@ -0,0 +1,59 @@
|
||||
package cn.lili.modules.file.plugin;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.file.entity.enums.OssEnum;
|
||||
import cn.lili.modules.file.plugin.impl.AliFilePlugin;
|
||||
import cn.lili.modules.file.plugin.impl.MinioFilePlugin;
|
||||
import cn.lili.modules.system.entity.dos.Setting;
|
||||
import cn.lili.modules.system.entity.dto.OssSetting;
|
||||
import cn.lili.modules.system.entity.enums.SettingEnum;
|
||||
import cn.lili.modules.system.service.SettingService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 文件服务抽象工厂 直接返回操作类
|
||||
*
|
||||
* @author Chopper
|
||||
* @version v1.0
|
||||
* 2022-06-06 11:35
|
||||
*/
|
||||
@Component
|
||||
public class FilePluginFactory {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SettingService settingService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取oss client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public FilePlugin filePlugin() {
|
||||
|
||||
OssSetting ossSetting = null;
|
||||
try {
|
||||
Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
|
||||
|
||||
ossSetting = JSONUtil.toBean(setting.getSettingValue(), OssSetting.class);
|
||||
|
||||
|
||||
switch (OssEnum.valueOf(ossSetting.getType())) {
|
||||
|
||||
case MINIO:
|
||||
return new MinioFilePlugin(ossSetting);
|
||||
case ALI_OSS:
|
||||
return new AliFilePlugin(ossSetting);
|
||||
default:
|
||||
throw new ServiceException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,23 +1,17 @@
|
||||
package cn.lili.modules.file.plugin.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.file.plugin.FileManagerPlugin;
|
||||
import cn.lili.modules.system.entity.dos.Setting;
|
||||
import cn.lili.modules.file.entity.enums.OssEnum;
|
||||
import cn.lili.modules.file.plugin.FilePlugin;
|
||||
import cn.lili.modules.system.entity.dto.OssSetting;
|
||||
import cn.lili.modules.system.entity.enums.SettingEnum;
|
||||
import cn.lili.modules.system.service.SettingService;
|
||||
import com.aliyun.oss.ClientException;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.OSSException;
|
||||
import com.aliyun.oss.model.DeleteObjectsRequest;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
@ -29,28 +23,19 @@ import java.util.List;
|
||||
* @author Chopper
|
||||
*/
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AliFileManagerPlugin implements FileManagerPlugin {
|
||||
public class AliFilePlugin implements FilePlugin {
|
||||
|
||||
@Autowired
|
||||
private SettingService settingService;
|
||||
private OssSetting ossSetting;
|
||||
|
||||
/**
|
||||
* 下一个初始化配置参数的时间
|
||||
* 这里为了防止多次调用redis,减少与redis的交互时间
|
||||
*/
|
||||
private static Long nextInitSetting;
|
||||
public AliFilePlugin(OssSetting ossSetting) {
|
||||
this.ossSetting = ossSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂时设定3分账请求一次设置
|
||||
*/
|
||||
private static final Long INTERVAL = 60 * 3 * 1000L;
|
||||
|
||||
/**
|
||||
* 静态设置,最快三分钟更新一次
|
||||
*/
|
||||
private static OssSetting ossSetting;
|
||||
@Override
|
||||
public OssEnum pluginName() {
|
||||
return OssEnum.ALI_OSS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取oss client
|
||||
@ -58,32 +43,12 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
|
||||
* @return
|
||||
*/
|
||||
private OSS getOssClient() {
|
||||
OssSetting ossSetting = getSetting();
|
||||
|
||||
return new OSSClientBuilder().build(
|
||||
ossSetting.getEndPoint(),
|
||||
ossSetting.getAccessKeyId(),
|
||||
ossSetting.getAccessKeySecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private OssSetting getSetting() {
|
||||
//如果没有配置,或者没有下次刷新时间,或者下次刷新时间小于当前时间,则从redis 更新一次
|
||||
if (ossSetting == null || nextInitSetting == null || nextInitSetting < System.currentTimeMillis()) {
|
||||
Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
|
||||
if (setting == null || StrUtil.isBlank(setting.getSettingValue())) {
|
||||
throw new ServiceException(ResultCode.OSS_NOT_EXIST);
|
||||
}
|
||||
nextInitSetting = System.currentTimeMillis() + INTERVAL;
|
||||
ossSetting = new Gson().fromJson(setting.getSettingValue(), OssSetting.class);
|
||||
return ossSetting;
|
||||
}
|
||||
return ossSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置前缀
|
||||
@ -91,7 +56,6 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
|
||||
* @return
|
||||
*/
|
||||
private String getUrlPrefix() {
|
||||
OssSetting ossSetting = getSetting();
|
||||
return "https://" + ossSetting.getBucketName() + "." + ossSetting.getEndPoint() + "/";
|
||||
}
|
||||
|
||||
@ -130,7 +94,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
|
||||
try {
|
||||
ObjectMetadata meta = new ObjectMetadata();
|
||||
meta.setContentType("image/jpg");
|
||||
ossClient.putObject(getSetting().getBucketName(), key, inputStream, meta);
|
||||
ossClient.putObject(ossSetting.getBucketName(), key, inputStream, meta);
|
||||
} catch (OSSException oe) {
|
||||
log.error("Caught an OSSException, which means your request made it to OSS, "
|
||||
+ "but was rejected with an error response for some reason.");
|
||||
@ -161,7 +125,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
|
||||
|
||||
try {
|
||||
ossClient.deleteObjects(
|
||||
new DeleteObjectsRequest(getSetting().getBucketName()).withKeys(key));
|
||||
new DeleteObjectsRequest(ossSetting.getBucketName()).withKeys(key));
|
||||
} catch (OSSException oe) {
|
||||
log.error("Caught an OSSException, which means your request made it to OSS, "
|
||||
+ "but was rejected with an error response for some reason.");
|
@ -0,0 +1,165 @@
|
||||
package cn.lili.modules.file.plugin.impl;
|
||||
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.file.entity.enums.OssEnum;
|
||||
import cn.lili.modules.file.plugin.FilePlugin;
|
||||
import cn.lili.modules.system.entity.dto.OssSetting;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.ErrorResponseException;
|
||||
import io.minio.messages.DeleteObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* MINIO文件插件
|
||||
*
|
||||
* @author liushuai(liushuai711 @ gmail.com)
|
||||
* @version v4.0
|
||||
* @Description:
|
||||
* @since 2022/6/6 17:45
|
||||
*/
|
||||
@Slf4j
|
||||
public class MinioFilePlugin implements FilePlugin {
|
||||
|
||||
private OssSetting ossSetting;
|
||||
|
||||
public MinioFilePlugin(OssSetting ossSetting) {
|
||||
this.ossSetting = ossSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* 桶占位符
|
||||
*/
|
||||
private static final String BUCKET_PARAM = "${bucket}";
|
||||
/**
|
||||
* bucket权限-只读
|
||||
*/
|
||||
private static final String READ_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
|
||||
/**
|
||||
* bucket权限-只读
|
||||
*/
|
||||
private static final String WRITE_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
|
||||
/**
|
||||
* bucket权限-读写
|
||||
*/
|
||||
private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
|
||||
|
||||
|
||||
private MinioClient minioClient;
|
||||
|
||||
|
||||
@Override
|
||||
public OssEnum pluginName() {
|
||||
return OssEnum.MINIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pathUpload(String filePath, String key) {
|
||||
try {
|
||||
return this.inputStreamUpload(new FileInputStream(filePath), key);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inputStreamUpload(InputStream inputStream, String key) {
|
||||
String bucket = "";
|
||||
try {
|
||||
MinioClient client = getOssClient();
|
||||
bucket = ossSetting.getM_bucketName();
|
||||
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
|
||||
.bucket(bucket).stream(inputStream, inputStream.available(), 5 * 1024 * 1024)
|
||||
.object(key)
|
||||
.contentType("image/png" )
|
||||
.build();
|
||||
client.putObject(putObjectArgs);
|
||||
} catch (Exception e) {
|
||||
log.error("上传失败2,", e);
|
||||
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
|
||||
}
|
||||
//拼接出可访问的url地址
|
||||
return ossSetting.getM_frontUrl() + "/" + bucket + "/" + key;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteFile(List<String> key) {
|
||||
if (key == null || key.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
MinioClient ossClient = getOssClient();
|
||||
List<DeleteObject> objectList = key.stream().map(DeleteObject::new).collect(Collectors.toList());
|
||||
ossClient.removeObjects(RemoveObjectsArgs.builder().objects(objectList).bucket(ossSetting.getM_bucketName()).build());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取oss client
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private MinioClient getOssClient() {
|
||||
if (minioClient != null) {
|
||||
return this.minioClient;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (minioClient == null) {
|
||||
//创建客户端
|
||||
this.minioClient = MinioClient.builder()
|
||||
.endpoint(ossSetting.getM_endpoint())
|
||||
.credentials(ossSetting.getM_accessKey(), ossSetting.getM_secretKey())
|
||||
.build();
|
||||
try {
|
||||
//查看对应的bucket是否已经存在,不存在则创建
|
||||
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(ossSetting.getM_bucketName()).build())) {
|
||||
//创建bucket
|
||||
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(ossSetting.getM_bucketName()).build();
|
||||
this.minioClient.makeBucket(makeBucketArgs);
|
||||
setBucketPolicy(this.minioClient, ossSetting.getM_bucketName(), "read-write" );
|
||||
log.info("创建minio桶成功{}", ossSetting.getM_bucketName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//晴空配置
|
||||
minioClient = null;
|
||||
log.error("创建[{}]bucket失败", ossSetting.getM_bucketName());
|
||||
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return minioClient;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新桶权限策略
|
||||
*
|
||||
* @param bucket 桶
|
||||
* @param policy 权限
|
||||
*/
|
||||
public static void setBucketPolicy(MinioClient client, String bucket, String policy) throws Exception {
|
||||
switch (policy) {
|
||||
case "read-only":
|
||||
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
|
||||
break;
|
||||
case "write-only":
|
||||
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
|
||||
break;
|
||||
case "read-write":
|
||||
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).region("public" ).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
|
||||
break;
|
||||
case "none":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -10,7 +10,8 @@ import cn.lili.common.vo.SearchVO;
|
||||
import cn.lili.modules.file.entity.File;
|
||||
import cn.lili.modules.file.entity.dto.FileOwnerDTO;
|
||||
import cn.lili.modules.file.mapper.FileMapper;
|
||||
import cn.lili.modules.file.plugin.FileManagerPlugin;
|
||||
import cn.lili.modules.file.plugin.FilePlugin;
|
||||
import cn.lili.modules.file.plugin.FilePluginFactory;
|
||||
import cn.lili.modules.file.service.FileService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@ -31,7 +32,7 @@ import java.util.List;
|
||||
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {
|
||||
|
||||
@Autowired
|
||||
private FileManagerPlugin fileManagerPlugin;
|
||||
private FilePluginFactory filePluginFactory;
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> ids) {
|
||||
@ -42,7 +43,7 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements Fi
|
||||
List<File> files = this.list(queryWrapper);
|
||||
List<String> keys = new ArrayList<>();
|
||||
files.forEach(item -> keys.add(item.getFileKey()));
|
||||
fileManagerPlugin.deleteFile(keys);
|
||||
filePluginFactory.filePlugin().deleteFile(keys);
|
||||
this.remove(queryWrapper);
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements Fi
|
||||
List<File> files = this.list(queryWrapper);
|
||||
List<String> keys = new ArrayList<>();
|
||||
files.forEach(item -> keys.add(item.getFileKey()));
|
||||
fileManagerPlugin.deleteFile(keys);
|
||||
filePluginFactory.filePlugin().deleteFile(keys);
|
||||
this.remove(queryWrapper);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -7,7 +7,8 @@ import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationFuLuDTO;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsTypeEnum;
|
||||
import cn.lili.mybatis.BaseEntity;
|
||||
@ -108,6 +109,9 @@ public class Goods extends BaseEntity {
|
||||
@ApiModelProperty(value = "运费模板id")
|
||||
private String templateId;
|
||||
|
||||
/**
|
||||
* @see GoodsAuthEnum
|
||||
*/
|
||||
@ApiModelProperty(value = "审核状态")
|
||||
private String authFlag;
|
||||
|
||||
@ -130,6 +134,9 @@ public class Goods extends BaseEntity {
|
||||
@ApiModelProperty(value = "是否为推荐商品", required = true)
|
||||
private Boolean recommend;
|
||||
|
||||
/**
|
||||
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
|
||||
*/
|
||||
@ApiModelProperty(value = "销售模式", required = true)
|
||||
private String salesModel;
|
||||
|
||||
@ -144,83 +151,15 @@ public class Goods extends BaseEntity {
|
||||
@JsonIgnore
|
||||
private String params;
|
||||
|
||||
//福禄所需参数
|
||||
/**
|
||||
* 商品编号
|
||||
*/
|
||||
@Length(max = 30, message = "商品规格编号太长,不能超过30个字符")
|
||||
@ApiModelProperty(value = "商品编号")
|
||||
private String sn;
|
||||
|
||||
/**
|
||||
* 重量
|
||||
*/
|
||||
@ApiModelProperty(value = "重量")
|
||||
@Max(value = 99999999, message = "重量不能超过99999999")
|
||||
private Double weight;
|
||||
|
||||
public Goods() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 福禄
|
||||
* @param goodsOperationDTO
|
||||
*/
|
||||
public Goods(GoodsOperationFuLuDTO goodsOperationDTO) {
|
||||
this.goodsName = goodsOperationDTO.getGoodsName();
|
||||
this.categoryPath = goodsOperationDTO.getCategoryPath();
|
||||
this.storeCategoryPath = goodsOperationDTO.getStoreCategoryPath();
|
||||
this.brandId = goodsOperationDTO.getBrandId();
|
||||
this.sn = goodsOperationDTO.getSn();
|
||||
this.price = goodsOperationDTO.getPrice();
|
||||
this.weight = goodsOperationDTO.getWeight();
|
||||
this.templateId = goodsOperationDTO.getTemplateId();
|
||||
this.recommend = goodsOperationDTO.getRecommend();
|
||||
this.sellingPoint = goodsOperationDTO.getSellingPoint();
|
||||
this.salesModel = goodsOperationDTO.getSalesModel();
|
||||
this.goodsUnit = goodsOperationDTO.getGoodsUnit();
|
||||
this.intro = goodsOperationDTO.getIntro();
|
||||
this.mobileIntro = goodsOperationDTO.getMobileIntro();
|
||||
this.goodsVideo = goodsOperationDTO.getGoodsVideo();
|
||||
this.price = goodsOperationDTO.getPrice();
|
||||
if (goodsOperationDTO.getGoodsParamsDTOList() != null && goodsOperationDTO.getGoodsParamsDTOList().isEmpty()) {
|
||||
this.params = JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsDTOList());
|
||||
}
|
||||
//如果立即上架则
|
||||
this.marketEnable = Boolean.TRUE.equals(goodsOperationDTO.getRelease()) ? GoodsStatusEnum.UPPER.name() : GoodsStatusEnum.DOWN.name();
|
||||
this.goodsType = goodsOperationDTO.getGoodsType();
|
||||
this.grade = 100D;
|
||||
|
||||
//循环sku,判定sku是否有效
|
||||
for (Map<String, Object> sku : goodsOperationDTO.getSkuList()) {
|
||||
//判定参数不能为空
|
||||
if (!sku.containsKey("sn") || sku.get("sn") == null) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_SN_ERROR);
|
||||
}
|
||||
if (!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_PRICE_ERROR);
|
||||
}
|
||||
if (!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_COST_ERROR);
|
||||
}
|
||||
//虚拟商品没有重量字段
|
||||
if (this.goodsType.equals(GoodsTypeEnum.PHYSICAL_GOODS.name()) && (!sku.containsKey("weight") || sku.containsKey("weight") && (StringUtil.isEmpty(sku.get("weight").toString()) || Convert.toDouble(sku.get("weight").toString()) < 0))) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_WEIGHT_ERROR);
|
||||
}
|
||||
if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Goods(GoodsOperationDTO goodsOperationDTO) {
|
||||
this.goodsName = goodsOperationDTO.getGoodsName();
|
||||
this.categoryPath = goodsOperationDTO.getCategoryPath();
|
||||
this.storeCategoryPath = goodsOperationDTO.getStoreCategoryPath();
|
||||
this.brandId = goodsOperationDTO.getBrandId();
|
||||
this.price = goodsOperationDTO.getPrice();
|
||||
this.templateId = goodsOperationDTO.getTemplateId();
|
||||
this.recommend = goodsOperationDTO.getRecommend();
|
||||
this.sellingPoint = goodsOperationDTO.getSellingPoint();
|
||||
@ -244,10 +183,10 @@ public class Goods extends BaseEntity {
|
||||
if (!sku.containsKey("sn") || sku.get("sn") == null) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_SN_ERROR);
|
||||
}
|
||||
if (!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) {
|
||||
if ((!sku.containsKey("price") || StringUtil.isEmpty(sku.get("price").toString()) || Convert.toDouble(sku.get("price")) <= 0) && !goodsOperationDTO.getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_PRICE_ERROR);
|
||||
}
|
||||
if (!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) {
|
||||
if ((!sku.containsKey("cost") || StringUtil.isEmpty(sku.get("cost").toString()) || Convert.toDouble(sku.get("cost")) <= 0) && !goodsOperationDTO.getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())) {
|
||||
throw new ServiceException(ResultCode.GOODS_SKU_COST_ERROR);
|
||||
}
|
||||
//虚拟商品没有重量字段
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品编辑DTO
|
||||
* 商品操作DTO
|
||||
*
|
||||
* @author pikachu
|
||||
* @since 2020-02-24 19:27:20
|
||||
@ -77,13 +77,12 @@ public class GoodsOperationDTO implements Serializable {
|
||||
@Min(value = 0, message = "运费模板值不正确")
|
||||
private String templateId;
|
||||
|
||||
@ApiModelProperty(value = "sku列表")
|
||||
@Valid
|
||||
private List<Map<String, Object>> skuList;
|
||||
|
||||
@ApiModelProperty(value = "卖点")
|
||||
private String sellingPoint;
|
||||
|
||||
/**
|
||||
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
|
||||
*/
|
||||
@ApiModelProperty(value = "销售模式", required = true)
|
||||
private String salesModel;
|
||||
|
||||
@ -112,6 +111,17 @@ public class GoodsOperationDTO implements Serializable {
|
||||
@ApiModelProperty(value = "商品视频")
|
||||
private String goodsVideo;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "sku列表")
|
||||
@Valid
|
||||
private List<Map<String, Object>> skuList;
|
||||
|
||||
/**
|
||||
* 批发商品规则
|
||||
*/
|
||||
@ApiModelProperty(value = "批发商品规则")
|
||||
private List<WholesaleDTO> wholesaleList;
|
||||
|
||||
public String getGoodsName() {
|
||||
//对商品对名称做一个极限处理。这里没有用xss过滤是因为xss过滤为全局过滤,影响很大。
|
||||
// 业务中,全局代码中只有商品名称不能拥有英文逗号,是由于商品名称存在一个数据库联合查询,结果要根据逗号分组
|
||||
|
@ -77,6 +77,12 @@ public class GoodsSearchParams extends PageVO {
|
||||
@ApiModelProperty(value = "商品类型")
|
||||
private String goodsType;
|
||||
|
||||
/**
|
||||
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
|
||||
*/
|
||||
@ApiModelProperty(value = "销售模式", required = true)
|
||||
private String salesModel;
|
||||
|
||||
public <T> QueryWrapper<T> queryWrapper() {
|
||||
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
|
||||
if (CharSequenceUtil.isNotEmpty(goodsId)) {
|
||||
@ -121,6 +127,9 @@ public class GoodsSearchParams extends PageVO {
|
||||
if (CharSequenceUtil.isNotEmpty(goodsType)) {
|
||||
queryWrapper.eq("goods_type", goodsType);
|
||||
}
|
||||
if (CharSequenceUtil.isNotEmpty(salesModel)) {
|
||||
queryWrapper.eq("sales_model", salesModel);
|
||||
}
|
||||
|
||||
queryWrapper.eq("delete_flag", false);
|
||||
this.betweenWrapper(queryWrapper);
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -1,9 +1,11 @@
|
||||
package cn.lili.modules.goods.entity.vos;
|
||||
|
||||
import cn.lili.modules.goods.entity.dos.Goods;
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -14,6 +16,7 @@ import java.util.List;
|
||||
* @since 2020-02-26 23:24:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class GoodsVO extends Goods {
|
||||
|
||||
private static final long serialVersionUID = 6377623919990713567L;
|
||||
@ -29,4 +32,7 @@ public class GoodsVO extends Goods {
|
||||
|
||||
@ApiModelProperty(value = "sku列表")
|
||||
private List<GoodsSkuVO> skuList;
|
||||
|
||||
@ApiModelProperty(value = "批发商品消费规则列表")
|
||||
private List<Wholesale> wholesaleList;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
package cn.lili.modules.goods.mapper;
|
||||
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
@ -23,4 +29,89 @@ public interface GoodsSkuMapper extends BaseMapper<GoodsSku> {
|
||||
@Select("SELECT id FROM li_goods_sku WHERE goods_id = #{goodsId}")
|
||||
List<String> getGoodsSkuIdByGoodsId(String goodsId);
|
||||
|
||||
|
||||
@Insert("replace into li_goods_sku (\n" +
|
||||
"\tid,\n" +
|
||||
"\tgoods_id,\n" +
|
||||
"\tspecs,\n" +
|
||||
"\tsimple_specs,\n" +
|
||||
"\tfreight_template_id,\n" +
|
||||
"\tgoods_name,\n" +
|
||||
"\tsn,\n" +
|
||||
"\tbrand_id,\n" +
|
||||
"\tcategory_path,\n" +
|
||||
"\tgoods_unit,\n" +
|
||||
"\tselling_point,\n" +
|
||||
"\tweight,\n" +
|
||||
"\tmarket_enable,\n" +
|
||||
"\tintro,\n" +
|
||||
"\tprice,\n" +
|
||||
"\tcost,\n" +
|
||||
"\tquantity,\n" +
|
||||
"\tgrade,\n" +
|
||||
"\tthumbnail,\n" +
|
||||
"\tsmall,\n" +
|
||||
"\tstore_category_path,\n" +
|
||||
"\tstore_id,\n" +
|
||||
"\tstore_name,\n" +
|
||||
"\tauth_flag,\n" +
|
||||
"\tself_operated,\n" +
|
||||
"\tmobile_intro,\n" +
|
||||
"\trecommend,\n" +
|
||||
"\tsales_model,\n" +
|
||||
"\tgoods_type,\n" +
|
||||
"\tcreate_by,\n" +
|
||||
"\tcreate_time,\n" +
|
||||
"\tupdate_time,\n" +
|
||||
"\tdelete_flag \n" +
|
||||
")\n" +
|
||||
" VALUES\n" +
|
||||
"(\n" +
|
||||
"\t#{goodsSku.id},\n" +
|
||||
"\t#{goodsSku.goodsId},\n" +
|
||||
"\t#{goodsSku.specs},\n" +
|
||||
"\t#{goodsSku.simpleSpecs},\n" +
|
||||
"\t#{goodsSku.freightTemplateId},\n" +
|
||||
"\t#{goodsSku.goodsName},\n" +
|
||||
"\t#{goodsSku.sn},\n" +
|
||||
"\t#{goodsSku.brandId},\n" +
|
||||
"\t#{goodsSku.categoryPath},\n" +
|
||||
"\t#{goodsSku.goodsUnit},\n" +
|
||||
"\t#{goodsSku.sellingPoint},\n" +
|
||||
"\t#{goodsSku.weight},\n" +
|
||||
"\t#{goodsSku.marketEnable},\n" +
|
||||
"\t#{goodsSku.intro},\n" +
|
||||
"\t#{goodsSku.price},\n" +
|
||||
"\t#{goodsSku.cost},\n" +
|
||||
"\t#{goodsSku.quantity},\n" +
|
||||
"\t#{goodsSku.grade},\n" +
|
||||
"\t#{goodsSku.thumbnail},\n" +
|
||||
"\t#{goodsSku.small},\n" +
|
||||
"\t#{goodsSku.storeCategoryPath},\n" +
|
||||
"\t#{goodsSku.storeId},\n" +
|
||||
"\t#{goodsSku.storeName},\n" +
|
||||
"\t#{goodsSku.authFlag},\n" +
|
||||
"\t#{goodsSku.selfOperated},\n" +
|
||||
"\t#{goodsSku.mobileIntro},\n" +
|
||||
"\t#{goodsSku.recommend},\n" +
|
||||
"\t#{goodsSku.salesModel},\n" +
|
||||
"\t#{goodsSku.goodsType},\n" +
|
||||
"\t#{goodsSku.createBy},\n" +
|
||||
"\t#{goodsSku.createTime},\n" +
|
||||
"\t#{goodsSku.updateTime},\n" +
|
||||
"\t#{goodsSku.deleteFlag}\n" +
|
||||
")")
|
||||
int replaceGoodsSku(@Param("goodsSku") GoodsSku goodsSku);
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询商品skuDTO
|
||||
*
|
||||
* @param page 分页
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 售后VO分页
|
||||
*/
|
||||
@Select("SELECT *,g.params as params FROM li_goods_sku gs inner join li_goods g on gs.goods_id = g.id ${ew.customSqlSegment}")
|
||||
IPage<GoodsSkuDTO> queryByParams(IPage<GoodsSkuDTO> page, @Param(Constants.WRAPPER) Wrapper<GoodsSkuDTO> queryWrapper);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cn.lili.modules.goods.mapper;
|
||||
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
* @since 2022/5/24
|
||||
**/
|
||||
public interface WholesaleMapper extends BaseMapper<Wholesale> {
|
||||
}
|
@ -4,9 +4,6 @@ package cn.lili.modules.goods.service;
|
||||
import cn.lili.modules.goods.entity.dos.Category;
|
||||
import cn.lili.modules.goods.entity.vos.CategoryVO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -16,7 +13,6 @@ import java.util.List;
|
||||
* @author pikachu
|
||||
* @since 2020-03-02 16:44:56
|
||||
*/
|
||||
@CacheConfig(cacheNames = "{category}")
|
||||
public interface CategoryService extends IService<Category> {
|
||||
|
||||
|
||||
@ -35,7 +31,6 @@ public interface CategoryService extends IService<Category> {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Cacheable(key = "#id")
|
||||
Category getCategoryById(String id);
|
||||
|
||||
/**
|
||||
@ -99,7 +94,6 @@ public interface CategoryService extends IService<Category> {
|
||||
* @param category 商品分类信息
|
||||
* @return 修改结果
|
||||
*/
|
||||
@CacheEvict(key = "#category.id")
|
||||
void updateCategory(Category category);
|
||||
|
||||
/**
|
||||
|
@ -36,4 +36,11 @@ public interface GoodsGalleryService extends IService<GoodsGallery> {
|
||||
*/
|
||||
List<GoodsGallery> goodsGalleryList(String goodsId);
|
||||
|
||||
/**
|
||||
* 根据商品 id删除商品相册缩略图
|
||||
*
|
||||
* @param goodsId 商品ID
|
||||
*/
|
||||
void removeByGoodsId(String goodsId);
|
||||
|
||||
}
|
@ -129,6 +129,17 @@ public interface GoodsService extends IService<Goods> {
|
||||
*/
|
||||
Boolean updateGoodsMarketAble(List<String> goodsIds, GoodsStatusEnum goodsStatusEnum, String underReason);
|
||||
|
||||
|
||||
/**
|
||||
* 更新商品上架状态状态
|
||||
*
|
||||
* @param storeId 店铺ID
|
||||
* @param goodsStatusEnum 更新的商品状态
|
||||
* @param underReason 下架原因
|
||||
* @return 更新结果
|
||||
*/
|
||||
Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason);
|
||||
|
||||
/**
|
||||
* 更新商品上架状态状态
|
||||
*
|
||||
|
@ -3,10 +3,14 @@ package cn.lili.modules.goods.service;
|
||||
import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.modules.goods.entity.dos.Goods;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
@ -43,19 +47,18 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
||||
/**
|
||||
* 添加商品sku
|
||||
*
|
||||
* @param skuList sku列表
|
||||
* @param goods 商品信息
|
||||
* @param goods 商品信息
|
||||
* @param goodsOperationDTO 商品操作信息
|
||||
*/
|
||||
void add(List<Map<String, Object>> skuList, Goods goods);
|
||||
void add(Goods goods, GoodsOperationDTO goodsOperationDTO);
|
||||
|
||||
/**
|
||||
* 更新商品sku
|
||||
*
|
||||
* @param skuList sku列表
|
||||
* @param goods 商品信息
|
||||
* @param regeneratorSkuFlag 是否是否重新生成sku
|
||||
* @param goods 商品信息
|
||||
* @param goodsOperationDTO 商品操作信息
|
||||
*/
|
||||
void update(List<Map<String, Object>> skuList, Goods goods, Boolean regeneratorSkuFlag);
|
||||
void update(Goods goods, GoodsOperationDTO goodsOperationDTO);
|
||||
|
||||
/**
|
||||
* 更新商品sku
|
||||
@ -79,6 +82,14 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
||||
*/
|
||||
GoodsSku getGoodsSkuByIdFromCache(String id);
|
||||
|
||||
/**
|
||||
* 从缓存中获取可参与促销商品
|
||||
*
|
||||
* @param skuId skuid
|
||||
* @return 商品详情
|
||||
*/
|
||||
GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId);
|
||||
|
||||
/**
|
||||
* 获取商品sku详情
|
||||
*
|
||||
@ -136,6 +147,16 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
||||
*/
|
||||
IPage<GoodsSku> getGoodsSkuByPage(GoodsSearchParams searchParams);
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询商品sku信息
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param queryWrapper 查询参数
|
||||
* @return 商品sku信息
|
||||
*/
|
||||
IPage<GoodsSkuDTO> getGoodsSkuDTOByPage(Page<GoodsSkuDTO> page, Wrapper<GoodsSkuDTO> queryWrapper);
|
||||
|
||||
/**
|
||||
* 列表查询商品sku信息
|
||||
*
|
||||
@ -151,6 +172,15 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
||||
*/
|
||||
void updateGoodsSkuStatus(Goods goods);
|
||||
|
||||
/**
|
||||
* 更新商品sku状态根据店铺id
|
||||
*
|
||||
* @param storeId 店铺id
|
||||
* @param marketEnable 市场启用状态
|
||||
* @param authFlag 审核状态
|
||||
*/
|
||||
void updateGoodsSkuStatusByStoreId(String storeId, String marketEnable, String authFlag);
|
||||
|
||||
/**
|
||||
* 发送生成ES商品索引
|
||||
*
|
||||
@ -202,4 +232,20 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
||||
* @return 全部skuId的集合
|
||||
*/
|
||||
List<String> getSkuIdsByGoodsId(String goodsId);
|
||||
|
||||
/**
|
||||
* 删除并且新增sku,即覆盖之前信息
|
||||
*
|
||||
* @param goodsSkus 商品sku集合
|
||||
* @return
|
||||
*/
|
||||
boolean deleteAndInsertGoodsSkus(List<GoodsSku> goodsSkus);
|
||||
|
||||
/**
|
||||
* 统计sku总数
|
||||
*
|
||||
* @param storeId 店铺id
|
||||
* @return sku总数
|
||||
*/
|
||||
Long countSkuNum(String storeId);
|
||||
}
|
@ -70,7 +70,7 @@ public interface StudioService extends IService<Studio> {
|
||||
* @param status 直播间状态
|
||||
* @return 直播间分页
|
||||
*/
|
||||
IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status);
|
||||
IPage<StudioVO> studioList(PageVO pageVO, Integer recommend, String status);
|
||||
|
||||
/**
|
||||
* 修改直播间状态
|
||||
|
@ -0,0 +1,28 @@
|
||||
package cn.lili.modules.goods.service;
|
||||
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
* @since 2022/5/24
|
||||
**/
|
||||
public interface WholesaleService extends IService<Wholesale> {
|
||||
|
||||
|
||||
List<Wholesale> findByGoodsId(String goodsId);
|
||||
|
||||
Boolean removeByGoodsId(String goodsId);
|
||||
|
||||
/**
|
||||
* 匹配批发规则
|
||||
*
|
||||
* @param goodsId 商品规则
|
||||
* @param num 数量
|
||||
* @return 批发规则
|
||||
*/
|
||||
Wholesale match(String goodsId, Integer num);
|
||||
|
||||
}
|
@ -19,6 +19,9 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -36,6 +39,7 @@ import java.util.stream.Collectors;
|
||||
* @since 2020-02-23 15:18:56
|
||||
*/
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "{CATEGORY}")
|
||||
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
|
||||
|
||||
private static final String DELETE_FLAG_COLUMN = "delete_flag";
|
||||
@ -60,6 +64,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(key = "#id")
|
||||
public Category getCategoryById(String id) {
|
||||
return this.getById(id);
|
||||
}
|
||||
@ -216,6 +221,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#category.id")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateCategory(Category category) {
|
||||
//判断分类佣金是否正确
|
||||
@ -242,6 +248,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#id")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(String id) {
|
||||
this.removeById(id);
|
||||
@ -253,6 +260,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#categoryId")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateCategoryStatus(String categoryId, Boolean enableOperations) {
|
||||
//禁用子分类
|
||||
@ -335,7 +343,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
return item.getChildren();
|
||||
}
|
||||
if (item.getChildren() != null && !item.getChildren().isEmpty()) {
|
||||
return getChildren(parentId, categoryVOList);
|
||||
return getChildren(parentId, item.getChildren());
|
||||
}
|
||||
}
|
||||
return categoryVOList;
|
||||
@ -346,5 +354,6 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
*/
|
||||
private void removeCache() {
|
||||
cache.remove(CachePrefix.CATEGORY.getPrefix());
|
||||
cache.remove(CachePrefix.CATEGORY_ARRAY.getPrefix());
|
||||
}
|
||||
}
|
@ -75,4 +75,14 @@ public class GoodsGalleryServiceImpl extends ServiceImpl<GoodsGalleryMapper, Goo
|
||||
//根据商品id查询商品相册
|
||||
return this.baseMapper.selectList(new QueryWrapper<GoodsGallery>().eq("goods_id", goodsId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品 id删除商品相册缩略图
|
||||
*
|
||||
* @param goodsId 商品ID
|
||||
*/
|
||||
@Override
|
||||
public void removeByGoodsId(String goodsId) {
|
||||
this.baseMapper.delete(new UpdateWrapper<GoodsGallery>().eq("goods_id", goodsId));
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.lili.modules.goods.serviceimpl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
@ -14,6 +15,7 @@ import cn.lili.common.security.enums.UserEnums;
|
||||
import cn.lili.modules.goods.entity.dos.Category;
|
||||
import cn.lili.modules.goods.entity.dos.Goods;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsGallery;
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationFuLuDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
|
||||
@ -23,10 +25,7 @@ import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsVO;
|
||||
import cn.lili.modules.goods.mapper.GoodsMapper;
|
||||
import cn.lili.modules.goods.service.CategoryService;
|
||||
import cn.lili.modules.goods.service.GoodsGalleryService;
|
||||
import cn.lili.modules.goods.service.GoodsService;
|
||||
import cn.lili.modules.goods.service.GoodsSkuService;
|
||||
import cn.lili.modules.goods.service.*;
|
||||
import cn.lili.modules.member.entity.dos.MemberEvaluation;
|
||||
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
|
||||
import cn.lili.modules.member.service.MemberEvaluationService;
|
||||
@ -111,6 +110,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
@Autowired
|
||||
private FreightTemplateService freightTemplateService;
|
||||
|
||||
@Autowired
|
||||
private WholesaleService wholesaleService;
|
||||
|
||||
@Autowired
|
||||
private Cache<GoodsVO> cache;
|
||||
|
||||
@ -171,7 +173,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
//添加商品
|
||||
this.save(goods);
|
||||
//添加商品sku信息
|
||||
this.goodsSkuService.add(goodsOperationDTO.getSkuList(), goods);
|
||||
this.goodsSkuService.add(goods, goodsOperationDTO);
|
||||
//添加相册
|
||||
if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
|
||||
this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
|
||||
@ -220,7 +222,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
//修改商品
|
||||
this.updateById(goods);
|
||||
//修改商品sku信息
|
||||
this.goodsSkuService.update(goodsOperationDTO.getSkuList(), goods, goodsOperationDTO.getRegeneratorSkuFlag());
|
||||
this.goodsSkuService.update(goods, goodsOperationDTO);
|
||||
//添加相册
|
||||
if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
|
||||
this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
|
||||
@ -302,6 +304,12 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
if (CharSequenceUtil.isNotEmpty(goods.getParams())) {
|
||||
goodsVO.setGoodsParamsDTOList(JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class));
|
||||
}
|
||||
|
||||
List<Wholesale> wholesaleList = wholesaleService.findByGoodsId(goodsId);
|
||||
if (CollUtil.isNotEmpty(wholesaleList)) {
|
||||
goodsVO.setWholesaleList(wholesaleList);
|
||||
}
|
||||
|
||||
cache.put(CachePrefix.GOODS.getPrefix() + goodsId, goodsVO);
|
||||
return goodsVO;
|
||||
}
|
||||
@ -325,6 +333,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean auditGoods(List<String> goodsIds, GoodsAuthEnum goodsAuthEnum) {
|
||||
List<String> goodsCacheKeys = new ArrayList<>();
|
||||
boolean result = false;
|
||||
for (String goodsId : goodsIds) {
|
||||
Goods goods = this.checkExist(goodsId);
|
||||
@ -332,12 +341,13 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
result = this.updateById(goods);
|
||||
goodsSkuService.updateGoodsSkuStatus(goods);
|
||||
//删除之前的缓存
|
||||
cache.remove(CachePrefix.GOODS.getPrefix() + goodsId);
|
||||
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goodsId);
|
||||
//商品审核消息
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_AUDIT.name();
|
||||
//发送mq消息
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goods), RocketmqSendCallbackBuilder.commonCallback());
|
||||
}
|
||||
cache.multiDel(goodsCacheKeys);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -361,13 +371,30 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
LambdaQueryWrapper<Goods> queryWrapper = this.getQueryWrapperByStoreAuthority();
|
||||
queryWrapper.in(Goods::getId, goodsIds);
|
||||
List<Goods> goodsList = this.list(queryWrapper);
|
||||
for (Goods goods : goodsList) {
|
||||
goodsSkuService.updateGoodsSkuStatus(goods);
|
||||
}
|
||||
this.updateGoodsStatus(goodsIds, goodsStatusEnum, goodsList);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
|
||||
this.deleteEsGoods(goodsIds);
|
||||
}
|
||||
/**
|
||||
* 更新商品上架状态状态
|
||||
*
|
||||
* @param storeId 店铺ID
|
||||
* @param goodsStatusEnum 更新的商品状态
|
||||
* @param underReason 下架原因
|
||||
* @return 更新结果
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason) {
|
||||
boolean result;
|
||||
|
||||
LambdaUpdateWrapper<Goods> updateWrapper = this.getUpdateWrapperByStoreAuthority();
|
||||
updateWrapper.set(Goods::getMarketEnable, goodsStatusEnum.name());
|
||||
updateWrapper.set(Goods::getUnderMessage, underReason);
|
||||
updateWrapper.eq(Goods::getStoreId, storeId);
|
||||
result = this.update(updateWrapper);
|
||||
|
||||
//修改规格商品
|
||||
this.goodsSkuService.updateGoodsSkuStatusByStoreId(storeId, goodsStatusEnum.name(), null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -394,12 +421,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(Goods::getId, goodsIds);
|
||||
List<Goods> goodsList = this.list(queryWrapper);
|
||||
for (Goods goods : goodsList) {
|
||||
goodsSkuService.updateGoodsSkuStatus(goods);
|
||||
}
|
||||
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
|
||||
this.deleteEsGoods(goodsIds);
|
||||
}
|
||||
this.updateGoodsStatus(goodsIds, goodsStatusEnum, goodsList);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -417,13 +439,15 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
LambdaQueryWrapper<Goods> queryWrapper = this.getQueryWrapperByStoreAuthority();
|
||||
queryWrapper.in(Goods::getId, goodsIds);
|
||||
List<Goods> goodsList = this.list(queryWrapper);
|
||||
List<String> goodsCacheKeys = new ArrayList<>();
|
||||
for (Goods goods : goodsList) {
|
||||
//修改SKU状态
|
||||
goodsSkuService.updateGoodsSkuStatus(goods);
|
||||
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goods.getId());
|
||||
}
|
||||
|
||||
//删除缓存
|
||||
cache.multiDel(goodsCacheKeys);
|
||||
this.deleteEsGoods(goodsIds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -503,11 +527,43 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
||||
return this.count(
|
||||
new LambdaQueryWrapper<Goods>()
|
||||
.eq(Goods::getStoreId, storeId)
|
||||
.eq(Goods::getDeleteFlag, Boolean.FALSE)
|
||||
.eq(Goods::getAuthFlag, GoodsAuthEnum.PASS.name())
|
||||
.eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 更新店铺商品数量
|
||||
*
|
||||
* @param storeId 信息体
|
||||
*/
|
||||
void updateGoodsNum(String storeId) {
|
||||
Long num = goodsSkuService.countSkuNum(storeId);
|
||||
storeService.updateStoreGoodsNum(storeId, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品状态
|
||||
*
|
||||
* @param goodsIds 商品ID
|
||||
* @param goodsStatusEnum 商品状态
|
||||
* @param goodsList 商品列表
|
||||
*/
|
||||
private void updateGoodsStatus(List<String> goodsIds, GoodsStatusEnum goodsStatusEnum, List<Goods> goodsList) {
|
||||
List<String> goodsCacheKeys = new ArrayList<>();
|
||||
for (Goods goods : goodsList) {
|
||||
goodsCacheKeys.add(CachePrefix.GOODS.getPrefix() + goods.getId());
|
||||
goodsSkuService.updateGoodsSkuStatus(goods);
|
||||
}
|
||||
cache.multiDel(goodsCacheKeys);
|
||||
|
||||
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
|
||||
this.deleteEsGoods(goodsIds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送删除es索引的信息
|
||||
*
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.lili.modules.goods.serviceimpl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
@ -10,25 +9,29 @@ import cn.lili.cache.Cache;
|
||||
import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.common.enums.PromotionTypeEnum;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.event.TransactionCommitSendMQEvent;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.common.properties.RocketmqCustomProperties;
|
||||
import cn.lili.common.security.context.UserContext;
|
||||
import cn.lili.common.utils.SnowFlake;
|
||||
import cn.lili.modules.goods.entity.dos.Goods;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsGallery;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsSkuSpecVO;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
|
||||
import cn.lili.modules.goods.entity.vos.GoodsVO;
|
||||
import cn.lili.modules.goods.entity.vos.SpecValueVO;
|
||||
import cn.lili.modules.goods.event.GeneratorEsGoodsIndexEvent;
|
||||
import cn.lili.modules.goods.mapper.GoodsSkuMapper;
|
||||
import cn.lili.modules.goods.service.CategoryService;
|
||||
import cn.lili.modules.goods.service.GoodsGalleryService;
|
||||
import cn.lili.modules.goods.service.GoodsService;
|
||||
import cn.lili.modules.goods.service.GoodsSkuService;
|
||||
import cn.lili.modules.goods.service.*;
|
||||
import cn.lili.modules.goods.sku.GoodsSkuBuilder;
|
||||
import cn.lili.modules.goods.sku.render.SalesModelRender;
|
||||
import cn.lili.modules.member.entity.dos.FootPrint;
|
||||
import cn.lili.modules.member.entity.dto.EvaluationQueryParams;
|
||||
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
|
||||
@ -37,16 +40,17 @@ import cn.lili.modules.promotion.entity.dos.PromotionGoods;
|
||||
import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams;
|
||||
import cn.lili.modules.promotion.entity.enums.CouponGetEnum;
|
||||
import cn.lili.modules.promotion.service.PromotionGoodsService;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsAttribute;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import cn.lili.modules.search.service.EsGoodsIndexService;
|
||||
import cn.lili.modules.search.utils.EsIndexUtil;
|
||||
import cn.lili.mybatis.util.PageUtil;
|
||||
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
|
||||
import cn.lili.rocketmq.tags.GoodsTagsEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -113,35 +117,42 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Autowired
|
||||
private WholesaleService wholesaleService;
|
||||
|
||||
@Autowired
|
||||
private List<SalesModelRender> salesModelRenders;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(List<Map<String, Object>> skuList, Goods goods) {
|
||||
// 检查是否需要生成索引
|
||||
List<GoodsSku> newSkuList;
|
||||
//如果有规格
|
||||
if (skuList != null && !skuList.isEmpty()) {
|
||||
// 添加商品sku
|
||||
newSkuList = this.addGoodsSku(skuList, goods);
|
||||
} else {
|
||||
public void add(Goods goods, GoodsOperationDTO goodsOperationDTO) {
|
||||
// 是否存在规格
|
||||
if (goodsOperationDTO.getSkuList() == null || goodsOperationDTO.getSkuList().isEmpty()) {
|
||||
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
|
||||
}
|
||||
// 检查是否需要生成索引
|
||||
List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
|
||||
renderGoodsSkuList(goodsSkus, goodsOperationDTO);
|
||||
|
||||
this.updateStock(newSkuList);
|
||||
if (!newSkuList.isEmpty()) {
|
||||
generateEs(goods);
|
||||
if (!goodsSkus.isEmpty()) {
|
||||
this.saveOrUpdateBatch(goodsSkus);
|
||||
this.updateStock(goodsSkus);
|
||||
this.generateEs(goods);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(List<Map<String, Object>> skuList, Goods goods, Boolean regeneratorSkuFlag) {
|
||||
public void update(Goods goods, GoodsOperationDTO goodsOperationDTO) {
|
||||
// 是否存在规格
|
||||
if (skuList == null || skuList.isEmpty()) {
|
||||
if (goodsOperationDTO.getSkuList() == null || goodsOperationDTO.getSkuList().isEmpty()) {
|
||||
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
|
||||
}
|
||||
List<GoodsSku> newSkuList;
|
||||
List<GoodsSku> skuList;
|
||||
//删除旧的sku信息
|
||||
if (Boolean.TRUE.equals(regeneratorSkuFlag)) {
|
||||
if (Boolean.TRUE.equals(goodsOperationDTO.getRegeneratorSkuFlag())) {
|
||||
skuList = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
|
||||
renderGoodsSkuList(skuList, goodsOperationDTO);
|
||||
List<GoodsSkuVO> goodsListByGoodsId = getGoodsListByGoodsId(goods.getId());
|
||||
List<String> oldSkuIds = new ArrayList<>();
|
||||
//删除旧索引
|
||||
@ -149,36 +160,32 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
oldSkuIds.add(goodsSkuVO.getId());
|
||||
cache.remove(GoodsSkuService.getCacheKeys(goodsSkuVO.getId()));
|
||||
}
|
||||
goodsIndexService.deleteIndexByIds(oldSkuIds);
|
||||
this.removeByIds(oldSkuIds);
|
||||
|
||||
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
|
||||
//删除sku相册
|
||||
goodsGalleryService.removeByIds(oldSkuIds);
|
||||
// 添加商品sku
|
||||
newSkuList = this.addGoodsSku(skuList, goods);
|
||||
goodsGalleryService.removeByGoodsId(goods.getId());
|
||||
|
||||
//发送mq消息
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.SKU_DELETE.name();
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(oldSkuIds), RocketmqSendCallbackBuilder.commonCallback());
|
||||
} else {
|
||||
newSkuList = new ArrayList<>();
|
||||
for (Map<String, Object> map : skuList) {
|
||||
GoodsSku sku = new GoodsSku();
|
||||
//设置商品信息
|
||||
goodsInfo(sku, goods);
|
||||
//设置商品规格信息
|
||||
skuInfo(sku, goods, map, null);
|
||||
newSkuList.add(sku);
|
||||
skuList = new ArrayList<>();
|
||||
for (Map<String, Object> map : goodsOperationDTO.getSkuList()) {
|
||||
GoodsSku sku = GoodsSkuBuilder.build(goods, map, goodsOperationDTO);
|
||||
renderGoodsSku(sku, goodsOperationDTO);
|
||||
skuList.add(sku);
|
||||
//如果商品状态值不对,则es索引移除
|
||||
if (goods.getAuthFlag().equals(GoodsAuthEnum.PASS.name()) && goods.getMarketEnable().equals(GoodsStatusEnum.UPPER.name())) {
|
||||
goodsIndexService.deleteIndexById(sku.getId());
|
||||
this.clearCache(sku.getId());
|
||||
}
|
||||
}
|
||||
this.updateBatchById(newSkuList);
|
||||
}
|
||||
this.updateStock(newSkuList);
|
||||
if (GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag()) && !newSkuList.isEmpty()) {
|
||||
generateEs(goods);
|
||||
if (!skuList.isEmpty()) {
|
||||
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
|
||||
this.saveOrUpdateBatch(skuList);
|
||||
this.updateStock(skuList);
|
||||
this.generateEs(goods);
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,6 +238,15 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
return goodsSku;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId) {
|
||||
GoodsSku goodsSku = this.getGoodsSkuByIdFromCache(skuId);
|
||||
if (goodsSku != null && GoodsSalesModeEnum.WHOLESALE.name().equals(goodsSku.getSalesModel())) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_GOODS_DO_NOT_JOIN_WHOLESALE, goodsSku.getGoodsName());
|
||||
}
|
||||
return goodsSku;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getGoodsSkuDetail(String goodsId, String skuId) {
|
||||
Map<String, Object> map = new HashMap<>(16);
|
||||
@ -244,13 +260,16 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
GoodsSku goodsSku = this.getGoodsSkuByIdFromCache(skuId);
|
||||
//如果使用商品ID无法查询SKU则返回错误
|
||||
if (goodsVO == null || goodsSku == null) {
|
||||
//发送mq消息
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name();
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback());
|
||||
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
|
||||
}
|
||||
|
||||
//商品下架||商品未审核通过||商品删除,则提示:商品已下架
|
||||
if (GoodsStatusEnum.DOWN.name().equals(goodsVO.getMarketEnable())
|
||||
|| !GoodsAuthEnum.PASS.name().equals(goodsVO.getAuthFlag())
|
||||
|| Boolean.TRUE.equals(goodsVO.getDeleteFlag())) {
|
||||
if (GoodsStatusEnum.DOWN.name().equals(goodsVO.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goodsVO.getAuthFlag()) || Boolean.TRUE.equals(goodsVO.getDeleteFlag())) {
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name();
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback());
|
||||
throw new ServiceException(ResultCode.GOODS_NOT_EXIST);
|
||||
}
|
||||
|
||||
@ -269,13 +288,10 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
promotionMap = promotionMap.entrySet().stream().parallel().filter(i -> {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(i.getValue());
|
||||
// 过滤活动赠送优惠券和无效时间的活动
|
||||
return (jsonObject.get("getType") == null || jsonObject.get("getType", String.class).equals(CouponGetEnum.FREE.name())) &&
|
||||
(jsonObject.get("startTime") != null && jsonObject.get("startTime", Date.class).getTime() <= System.currentTimeMillis()) &&
|
||||
(jsonObject.get("endTime") == null || jsonObject.get("endTime", Date.class).getTime() >= System.currentTimeMillis());
|
||||
return (jsonObject.get("getType") == null || jsonObject.get("getType", String.class).equals(CouponGetEnum.FREE.name())) && (jsonObject.get("startTime") != null && jsonObject.get("startTime", Date.class).getTime() <= System.currentTimeMillis()) && (jsonObject.get("endTime") == null || jsonObject.get("endTime", Date.class).getTime() >= System.currentTimeMillis());
|
||||
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
|
||||
Optional<Map.Entry<String, Object>> containsPromotion = promotionMap.entrySet().stream().filter(i ->
|
||||
i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst();
|
||||
Optional<Map.Entry<String, Object>> containsPromotion = promotionMap.entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst();
|
||||
if (containsPromotion.isPresent()) {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(containsPromotion.get().getValue());
|
||||
PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams();
|
||||
@ -296,6 +312,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
|
||||
//获取分类
|
||||
String[] split = goodsSkuDetail.getCategoryPath().split(",");
|
||||
map.put("wholesaleList", wholesaleService.findByGoodsId(goodsSkuDetail.getGoodsId()));
|
||||
map.put("categoryName", categoryService.getCategoryNameByIds(Arrays.asList(split)));
|
||||
|
||||
//获取规格信息
|
||||
@ -325,7 +342,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateGoodsSkuStatus(Goods goods) {
|
||||
LambdaUpdateWrapper<GoodsSku> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(GoodsSku::getGoodsId, goods.getId());
|
||||
updateWrapper.eq(CharSequenceUtil.isNotEmpty(goods.getId()), GoodsSku::getGoodsId, goods.getId());
|
||||
updateWrapper.eq(CharSequenceUtil.isNotEmpty(goods.getStoreId()), GoodsSku::getStoreId, goods.getStoreId());
|
||||
updateWrapper.set(GoodsSku::getMarketEnable, goods.getMarketEnable());
|
||||
updateWrapper.set(GoodsSku::getAuthFlag, goods.getAuthFlag());
|
||||
updateWrapper.set(GoodsSku::getDeleteFlag, goods.getDeleteFlag());
|
||||
@ -337,7 +355,32 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
cache.put(GoodsSkuService.getCacheKeys(sku.getId()), sku);
|
||||
}
|
||||
if (!goodsSkus.isEmpty()) {
|
||||
generateEs(goods);
|
||||
this.generateEs(goods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品sku状态根据店铺id
|
||||
*
|
||||
* @param storeId 店铺id
|
||||
* @param marketEnable 市场启用状态
|
||||
* @param authFlag 审核状态
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateGoodsSkuStatusByStoreId(String storeId, String marketEnable, String authFlag) {
|
||||
LambdaUpdateWrapper<GoodsSku> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(GoodsSku::getStoreId, storeId);
|
||||
updateWrapper.set(CharSequenceUtil.isNotEmpty(marketEnable), GoodsSku::getMarketEnable, marketEnable);
|
||||
updateWrapper.set(CharSequenceUtil.isNotEmpty(authFlag), GoodsSku::getAuthFlag, authFlag);
|
||||
boolean update = this.update(updateWrapper);
|
||||
if (Boolean.TRUE.equals(update)) {
|
||||
if (GoodsStatusEnum.UPPER.name().equals(marketEnable)) {
|
||||
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_STORE_GOODS_INDEX.name(), storeId));
|
||||
} else if (GoodsStatusEnum.DOWN.name().equals(marketEnable)) {
|
||||
cache.vagueDel(CachePrefix.GOODS_SKU.getPrefix());
|
||||
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.STORE_GOODS_DELETE.name(), storeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -362,7 +405,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
|
||||
@Override
|
||||
public List<GoodsSkuVO> getGoodsListByGoodsId(String goodsId) {
|
||||
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId));
|
||||
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId).orderByAsc(GoodsSku::getGoodsName));
|
||||
return this.getGoodsSkuVOList(list);
|
||||
}
|
||||
|
||||
@ -423,6 +466,11 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
return this.page(PageUtil.initPage(searchParams), searchParams.queryWrapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<GoodsSkuDTO> getGoodsSkuDTOByPage(Page<GoodsSkuDTO> page, Wrapper<GoodsSkuDTO> queryWrapper) {
|
||||
return this.baseMapper.queryByParams(page, queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表查询商品sku信息
|
||||
*
|
||||
@ -481,18 +529,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateGoodsStuck(List<GoodsSku> goodsSkus) {
|
||||
//商品id集合 hashset 去重复
|
||||
Set<String> goodsIds = new HashSet<>();
|
||||
for (GoodsSku sku : goodsSkus) {
|
||||
goodsIds.add(sku.getGoodsId());
|
||||
}
|
||||
Map<String, List<GoodsSku>> groupByGoodsIds = goodsSkus.stream().collect(Collectors.groupingBy(GoodsSku::getGoodsId));
|
||||
//获取相关的sku集合
|
||||
LambdaQueryWrapper<GoodsSku> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.in(GoodsSku::getGoodsId, goodsIds);
|
||||
lambdaQueryWrapper.in(GoodsSku::getGoodsId, groupByGoodsIds.keySet());
|
||||
List<GoodsSku> goodsSkuList = this.list(lambdaQueryWrapper);
|
||||
|
||||
//统计每个商品的库存
|
||||
for (String goodsId : goodsIds) {
|
||||
for (String goodsId : groupByGoodsIds.keySet()) {
|
||||
//库存
|
||||
Integer quantity = 0;
|
||||
for (GoodsSku goodsSku : goodsSkuList) {
|
||||
@ -530,10 +574,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
|
||||
|
||||
//修改规格索引,发送mq消息
|
||||
Map<String, Object> updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(
|
||||
MapUtil.builder(new HashMap<String, Object>()).put("id", goodsSku.getId()).build(),
|
||||
MapUtil.builder(new HashMap<String, Object>()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum)
|
||||
.put("grade", grade).build());
|
||||
Map<String, Object> updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(MapUtil.builder(new HashMap<String, Object>()).put("id", goodsSku.getId()).build(), MapUtil.builder(new HashMap<String, Object>()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum).put("grade", grade).build());
|
||||
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_FIELD.name();
|
||||
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(updateIndexFieldsMap), RocketmqSendCallbackBuilder.commonCallback());
|
||||
|
||||
@ -558,12 +599,38 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
* @param goods 商品信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void generateEs(Goods goods) {
|
||||
// 不生成没有审核通过且没有上架的商品
|
||||
if (!GoodsStatusEnum.UPPER.name().equals(goods.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) {
|
||||
return;
|
||||
}
|
||||
applicationEventPublisher.publishEvent(new GeneratorEsGoodsIndexEvent("生成商品索引事件", goods.getId()));
|
||||
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_GOODS_INDEX.name(), goods.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteAndInsertGoodsSkus(List<GoodsSku> goodsSkus) {
|
||||
int count = 0;
|
||||
for (GoodsSku skus : goodsSkus) {
|
||||
if (CharSequenceUtil.isEmpty(skus.getId())) {
|
||||
skus.setId(SnowFlake.getIdStr());
|
||||
}
|
||||
count = this.baseMapper.replaceGoodsSku(skus);
|
||||
}
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countSkuNum(String storeId) {
|
||||
LambdaQueryWrapper<GoodsSku> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
queryWrapper
|
||||
.eq(GoodsSku::getStoreId, storeId)
|
||||
.eq(GoodsSku::getDeleteFlag, Boolean.FALSE)
|
||||
.eq(GoodsSku::getAuthFlag, GoodsAuthEnum.PASS.name())
|
||||
.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
|
||||
return this.count(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -584,152 +651,64 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
||||
|
||||
|
||||
/**
|
||||
* 增加sku集合
|
||||
* 批量渲染商品sku
|
||||
*
|
||||
* @param skuList sku列表
|
||||
* @param goods 商品信息
|
||||
* @param goodsSkuList sku集合
|
||||
* @param goodsOperationDTO 商品操作DTO
|
||||
*/
|
||||
List<GoodsSku> addGoodsSku(List<Map<String, Object>> skuList, Goods goods) {
|
||||
List<GoodsSku> skus = new ArrayList<>();
|
||||
for (Map<String, Object> skuVO : skuList) {
|
||||
Map<String, Object> resultMap = this.add(skuVO, goods);
|
||||
GoodsSku goodsSku = (GoodsSku) resultMap.get("goodsSku");
|
||||
if (goods.getSelfOperated() != null) {
|
||||
goodsSku.setSelfOperated(goods.getSelfOperated());
|
||||
}
|
||||
goodsSku.setGoodsType(goods.getGoodsType());
|
||||
skus.add(goodsSku);
|
||||
cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity());
|
||||
void renderGoodsSkuList(List<GoodsSku> goodsSkuList, GoodsOperationDTO goodsOperationDTO) {
|
||||
// 商品销售模式渲染器
|
||||
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderBatch(goodsSkuList, goodsOperationDTO));
|
||||
for (GoodsSku goodsSku : goodsSkuList) {
|
||||
extendOldSkuValue(goodsSku);
|
||||
this.renderImages(goodsSku);
|
||||
}
|
||||
this.saveBatch(skus);
|
||||
return skus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品规格
|
||||
* 渲染商品sku
|
||||
*
|
||||
* @param map 规格属性
|
||||
* @param goods 商品
|
||||
* @return 规格商品
|
||||
* @param goodsSku sku
|
||||
* @param goodsOperationDTO 商品操作DTO
|
||||
*/
|
||||
private Map<String, Object> add(Map<String, Object> map, Goods goods) {
|
||||
Map<String, Object> resultMap = new HashMap<>(2);
|
||||
GoodsSku sku = new GoodsSku();
|
||||
|
||||
//商品索引
|
||||
EsGoodsIndex esGoodsIndex = new EsGoodsIndex();
|
||||
|
||||
//设置商品信息
|
||||
goodsInfo(sku, goods);
|
||||
//设置商品规格信息
|
||||
skuInfo(sku, goods, map, esGoodsIndex);
|
||||
|
||||
esGoodsIndex.setGoodsSku(sku);
|
||||
resultMap.put("goodsSku", sku);
|
||||
resultMap.put("goodsIndex", esGoodsIndex);
|
||||
return resultMap;
|
||||
void renderGoodsSku(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
|
||||
extendOldSkuValue(goodsSku);
|
||||
// 商品销售模式渲染器
|
||||
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderSingle(goodsSku, goodsOperationDTO));
|
||||
this.renderImages(goodsSku);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置规格商品的商品信息
|
||||
* 将原sku的一些不会直接传递的值放到新的sku中
|
||||
*
|
||||
* @param sku 规格
|
||||
* @param goods 商品
|
||||
* @param goodsSku 商品sku
|
||||
*/
|
||||
private void goodsInfo(GoodsSku sku, Goods goods) {
|
||||
//商品基本信息
|
||||
sku.setGoodsId(goods.getId());
|
||||
|
||||
sku.setSellingPoint(goods.getSellingPoint());
|
||||
sku.setCategoryPath(goods.getCategoryPath());
|
||||
sku.setBrandId(goods.getBrandId());
|
||||
sku.setMarketEnable(goods.getMarketEnable());
|
||||
sku.setIntro(goods.getIntro());
|
||||
sku.setMobileIntro(goods.getMobileIntro());
|
||||
sku.setGoodsUnit(goods.getGoodsUnit());
|
||||
sku.setGrade(100D);
|
||||
//商品状态
|
||||
sku.setAuthFlag(goods.getAuthFlag());
|
||||
sku.setSalesModel(goods.getSalesModel());
|
||||
//卖家信息
|
||||
sku.setStoreId(goods.getStoreId());
|
||||
sku.setStoreName(goods.getStoreName());
|
||||
sku.setStoreCategoryPath(goods.getStoreCategoryPath());
|
||||
sku.setFreightTemplateId(goods.getTemplateId());
|
||||
sku.setRecommend(goods.getRecommend());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置商品规格信息
|
||||
*
|
||||
* @param sku 规格商品
|
||||
* @param goods 商品
|
||||
* @param map 规格信息
|
||||
* @param esGoodsIndex 商品索引
|
||||
*/
|
||||
private void skuInfo(GoodsSku sku, Goods goods, Map<String, Object> map, EsGoodsIndex esGoodsIndex) {
|
||||
|
||||
//规格简短信息
|
||||
StringBuilder simpleSpecs = new StringBuilder();
|
||||
//商品名称
|
||||
StringBuilder goodsName = new StringBuilder(goods.getGoodsName());
|
||||
//规格商品缩略图
|
||||
String thumbnail = "";
|
||||
String small = "";
|
||||
//规格值
|
||||
Map<String, Object> specMap = new HashMap<>(16);
|
||||
//商品属性
|
||||
List<EsGoodsAttribute> attributes = new ArrayList<>();
|
||||
|
||||
//获取规格信息
|
||||
for (Map.Entry<String, Object> spec : map.entrySet()) {
|
||||
//保存规格信息
|
||||
if (("id").equals(spec.getKey()) || ("sn").equals(spec.getKey()) || ("cost").equals(spec.getKey())
|
||||
|| ("price").equals(spec.getKey()) || ("quantity").equals(spec.getKey())
|
||||
|| ("weight").equals(spec.getKey())) {
|
||||
continue;
|
||||
} else {
|
||||
specMap.put(spec.getKey(), spec.getValue());
|
||||
if (("images").equals(spec.getKey())) {
|
||||
//设置规格商品缩略图
|
||||
List<Map<String, String>> images = (List<Map<String, String>>) spec.getValue();
|
||||
if (images == null || images.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
//设置规格商品缩略图
|
||||
//如果规格没有图片,则用商品图片复盖。有则增加规格图片,放在商品图片集合之前
|
||||
if (CharSequenceUtil.isNotEmpty(spec.getValue().toString())) {
|
||||
thumbnail = goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getThumbnail();
|
||||
small = goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getSmall();
|
||||
}
|
||||
} else {
|
||||
if (spec.getValue() != null) {
|
||||
//设置商品名称
|
||||
goodsName.append(" ").append(spec.getValue());
|
||||
//规格简短信息
|
||||
simpleSpecs.append(" ").append(spec.getValue());
|
||||
}
|
||||
}
|
||||
private void extendOldSkuValue(GoodsSku goodsSku) {
|
||||
if (CharSequenceUtil.isNotEmpty(goodsSku.getGoodsId())) {
|
||||
GoodsSku oldSku = this.getGoodsSkuByIdFromCache(goodsSku.getId());
|
||||
if (oldSku != null) {
|
||||
goodsSku.setCommentNum(oldSku.getCommentNum());
|
||||
goodsSku.setViewCount(oldSku.getViewCount());
|
||||
goodsSku.setBuyCount(oldSku.getBuyCount());
|
||||
goodsSku.setGrade(oldSku.getGrade());
|
||||
}
|
||||
}
|
||||
//设置规格信息
|
||||
sku.setGoodsName(goodsName.toString());
|
||||
sku.setThumbnail(thumbnail);
|
||||
sku.setSmall(small);
|
||||
}
|
||||
|
||||
//规格信息
|
||||
sku.setId(Convert.toStr(map.get("id"), ""));
|
||||
sku.setSn(Convert.toStr(map.get("sn")));
|
||||
sku.setWeight(Convert.toDouble(map.get("weight"), 0D));
|
||||
sku.setPrice(Convert.toDouble(map.get("price"), 0D));
|
||||
sku.setCost(Convert.toDouble(map.get("cost"), 0D));
|
||||
sku.setQuantity(Convert.toInt(map.get("quantity"), 0));
|
||||
sku.setSpecs(JSONUtil.toJsonStr(specMap));
|
||||
sku.setSimpleSpecs(simpleSpecs.toString());
|
||||
|
||||
if (esGoodsIndex != null) {
|
||||
//商品索引
|
||||
esGoodsIndex.setAttrList(attributes);
|
||||
/**
|
||||
* 渲染sku图片
|
||||
*
|
||||
* @param goodsSku sku
|
||||
*/
|
||||
void renderImages(GoodsSku goodsSku) {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(goodsSku.getSpecs());
|
||||
List<Map<String, String>> images = jsonObject.get("images", List.class);
|
||||
if (images != null && !images.isEmpty()) {
|
||||
GoodsGallery goodsGallery = goodsGalleryService.getGoodsGallery(images.get(0).get("url"));
|
||||
goodsSku.setBig(goodsGallery.getOriginal());
|
||||
goodsSku.setOriginal(goodsGallery.getOriginal());
|
||||
goodsSku.setThumbnail(goodsGallery.getThumbnail());
|
||||
goodsSku.setSmall(goodsGallery.getSmall());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
|
||||
StoreGoodsLabelVO storeGoodsLabelVO = new StoreGoodsLabelVO(storeGoodsLabel.getId(), storeGoodsLabel.getLabelName(), storeGoodsLabel.getLevel(), storeGoodsLabel.getSortOrder());
|
||||
List<StoreGoodsLabelVO> storeGoodsLabelVOChildList = new ArrayList<>();
|
||||
list.stream()
|
||||
.filter(label -> label.getParentId().equals(storeGoodsLabel.getId()))
|
||||
.filter(label -> label.getParentId() != null && label.getParentId().equals(storeGoodsLabel.getId()))
|
||||
.forEach(storeGoodsLabelChild -> storeGoodsLabelVOChildList.add(new StoreGoodsLabelVO(storeGoodsLabelChild.getId(), storeGoodsLabelChild.getLabelName(), storeGoodsLabelChild.getLevel(), storeGoodsLabelChild.getSortOrder())));
|
||||
storeGoodsLabelVO.setChildren(storeGoodsLabelVOChildList);
|
||||
storeGoodsLabelVOList.add(storeGoodsLabelVO);
|
||||
@ -66,7 +66,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
|
||||
storeGoodsLabelVOList.sort(Comparator.comparing(StoreGoodsLabelVO::getSortOrder));
|
||||
|
||||
if (!storeGoodsLabelVOList.isEmpty()) {
|
||||
cache.put(CachePrefix.CATEGORY.getPrefix() + storeId + "tree", storeGoodsLabelVOList);
|
||||
cache.put(CachePrefix.CATEGORY.getPrefix() + storeId, storeGoodsLabelVOList);
|
||||
}
|
||||
return storeGoodsLabelVOList;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.lili.modules.goods.serviceimpl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
@ -32,12 +33,15 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -117,7 +121,7 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
|
||||
rocketmqCustomProperties.getPromotionTopic());
|
||||
|
||||
//直播间结束
|
||||
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.START.name());
|
||||
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.END.name());
|
||||
this.timeTrigger.edit(
|
||||
TimeExecuteConstant.BROADCAST_EXECUTOR,
|
||||
broadcastMessage,
|
||||
@ -209,15 +213,27 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status) {
|
||||
public IPage<StudioVO> studioList(PageVO pageVO, Integer recommend, String status) {
|
||||
QueryWrapper queryWrapper = new QueryWrapper<Studio>()
|
||||
.eq(recommend != null, "recommend", true)
|
||||
.eq(status != null, "status", status)
|
||||
.eq(CharSequenceUtil.isNotEmpty(status), "status", status)
|
||||
.orderByDesc("create_time");
|
||||
if (UserContext.getCurrentUser() != null && UserContext.getCurrentUser().getRole().equals(UserEnums.STORE)) {
|
||||
queryWrapper.eq("store_id", UserContext.getCurrentUser().getStoreId());
|
||||
}
|
||||
return this.page(PageUtil.initPage(pageVO), queryWrapper);
|
||||
Page page = this.page(PageUtil.initPage(pageVO), queryWrapper);
|
||||
List<Studio> records = page.getRecords();
|
||||
List<StudioVO> studioVOS = new ArrayList<>();
|
||||
for (Studio record : records) {
|
||||
StudioVO studioVO = new StudioVO();
|
||||
//获取直播间信息
|
||||
BeanUtil.copyProperties(record, studioVO);
|
||||
//获取直播间商品信息
|
||||
studioVO.setCommodityList(commodityMapper.getCommodityByRoomId(studioVO.getRoomId()));
|
||||
studioVOS.add(studioVO);
|
||||
}
|
||||
page.setRecords(studioVOS);
|
||||
return page;
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,65 @@
|
||||
package cn.lili.modules.goods.serviceimpl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import cn.lili.modules.goods.mapper.WholesaleMapper;
|
||||
import cn.lili.modules.goods.service.WholesaleService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
* @since 2022/5/24
|
||||
**/
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "{wholesale}_")
|
||||
public class WholesaleServiceImpl extends ServiceImpl<WholesaleMapper, Wholesale> implements WholesaleService {
|
||||
|
||||
@Autowired
|
||||
private Cache<List<Wholesale>> cache;
|
||||
|
||||
@Override
|
||||
@Cacheable(key = "#goodsId")
|
||||
public List<Wholesale> findByGoodsId(String goodsId) {
|
||||
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Wholesale::getGoodsId, goodsId);
|
||||
return this.list(queryWrapper).stream().sorted(Comparator.comparing(Wholesale::getNum)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(key = "#goodsId")
|
||||
public Boolean removeByGoodsId(String goodsId) {
|
||||
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Wholesale::getGoodsId, goodsId);
|
||||
cache.remove("{wholesale}_" + goodsId);
|
||||
return this.remove(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wholesale match(String goodsId, Integer num) {
|
||||
List<Wholesale> wholesaleList = cache.get("{wholesale}_" + goodsId);
|
||||
if (wholesaleList == null) {
|
||||
wholesaleList = this.findByGoodsId(goodsId);
|
||||
cache.put("{wholesale}_" + goodsId, wholesaleList);
|
||||
}
|
||||
List<Wholesale> matchList = wholesaleList.stream()
|
||||
.filter(wholesale -> wholesale.getNum() <= num)
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(matchList)) {
|
||||
return matchList.get(matchList.size() - 1);
|
||||
} else if (CollUtil.isNotEmpty(wholesaleList) && CollUtil.isEmpty(matchList)) {
|
||||
return wholesaleList.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package cn.lili.modules.goods.sku;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.modules.goods.entity.dos.Goods;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
* @since 2022/5/20
|
||||
**/
|
||||
@Component
|
||||
public class GoodsSkuBuilder {
|
||||
|
||||
|
||||
private static final String IMAGES_KEY = "images";
|
||||
|
||||
|
||||
/**
|
||||
* 构建商品sku
|
||||
*
|
||||
* @param goods 商品
|
||||
* @param skuInfo sku信息列表
|
||||
* @param goodsOperationDTO 商品操作信息(如需处理额外信息传递,不需可传空)
|
||||
* @return 商品sku
|
||||
*/
|
||||
public static GoodsSku build(Goods goods, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
|
||||
GoodsSku goodsSku = new GoodsSku(goods);
|
||||
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
|
||||
return goodsSku;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量构建商品sku
|
||||
*
|
||||
* @param goods 商品
|
||||
* @param goodsOperationDTO 商品操作信息
|
||||
* @return 商品sku
|
||||
*/
|
||||
public static List<GoodsSku> buildBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
|
||||
return builderBatch(goods, goodsOperationDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从已有的商品sku中构建商品sku
|
||||
*
|
||||
* @param goodsSku 原商品sku
|
||||
* @param skuInfo sku信息列表
|
||||
* @param goodsOperationDTO 商品操作信息(如需处理额外信息传递,不需可传空)
|
||||
* @return 商品sku
|
||||
*/
|
||||
public static GoodsSku build(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
|
||||
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
|
||||
return goodsSku;
|
||||
}
|
||||
|
||||
private static void builderSingle(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
|
||||
Assert.notNull(goodsSku, "goodsSku不能为空");
|
||||
Assert.notEmpty(skuInfo, "skuInfo不能为空");
|
||||
//规格简短信息
|
||||
StringBuilder simpleSpecs = new StringBuilder();
|
||||
//商品名称
|
||||
StringBuilder goodsName = new StringBuilder(goodsOperationDTO.getGoodsName());
|
||||
//规格值
|
||||
Map<String, Object> specMap = new HashMap<>(16);
|
||||
|
||||
// 原始规格项
|
||||
String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight"};
|
||||
//获取规格信息
|
||||
for (Map.Entry<String, Object> spec : skuInfo.entrySet()) {
|
||||
//保存新增规格信息
|
||||
if (!CollUtil.contains(Arrays.asList(ignoreOriginKeys), spec.getKey()) && spec.getValue() != null) {
|
||||
specMap.put(spec.getKey(), spec.getValue());
|
||||
if (!spec.getKey().equals(IMAGES_KEY)) {
|
||||
//设置商品名称
|
||||
goodsName.append(" ").append(spec.getValue());
|
||||
//规格简短信息
|
||||
simpleSpecs.append(" ").append(spec.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
//设置规格信息
|
||||
goodsSku.setGoodsName(goodsName.toString());
|
||||
|
||||
|
||||
//规格信息
|
||||
goodsSku.setId(Convert.toStr(skuInfo.get("id"), ""));
|
||||
goodsSku.setSn(Convert.toStr(skuInfo.get("sn")));
|
||||
goodsSku.setWeight(Convert.toDouble(skuInfo.get("weight"), 0D));
|
||||
goodsSku.setPrice(Convert.toDouble(skuInfo.get("price"), 0D));
|
||||
goodsSku.setCost(Convert.toDouble(skuInfo.get("cost"), 0D));
|
||||
goodsSku.setQuantity(Convert.toInt(skuInfo.get("quantity"), 0));
|
||||
goodsSku.setSpecs(JSONUtil.toJsonStr(specMap));
|
||||
goodsSku.setSimpleSpecs(simpleSpecs.toString());
|
||||
}
|
||||
|
||||
private static List<GoodsSku> builderBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
|
||||
Assert.notEmpty(goodsOperationDTO.getSkuList(), "goodsOperationDTO.getSkuList()不能为空");
|
||||
Assert.notNull(goods, "goods不能为空");
|
||||
List<GoodsSku> goodsSkus = new ArrayList<>();
|
||||
for (Map<String, Object> skuInfo : goodsOperationDTO.getSkuList()) {
|
||||
GoodsSku goodsSku = new GoodsSku(goods);
|
||||
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
|
||||
goodsSkus.add(goodsSku);
|
||||
}
|
||||
return goodsSkus;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.lili.modules.goods.sku.render;
|
||||
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 根据商品销售模型渲染商品sku
|
||||
*
|
||||
* @author paulG
|
||||
* @since 2022/5/20
|
||||
**/
|
||||
public interface SalesModelRender {
|
||||
|
||||
|
||||
String getSalesMode();
|
||||
|
||||
void renderSingle(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO);
|
||||
|
||||
void renderBatch(List<GoodsSku> goodsSkus, GoodsOperationDTO goodsOperationDTO);
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package cn.lili.modules.goods.sku.render.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dos.Wholesale;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||
import cn.lili.modules.goods.entity.dto.WholesaleDTO;
|
||||
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
|
||||
import cn.lili.modules.goods.service.WholesaleService;
|
||||
import cn.lili.modules.goods.sku.render.SalesModelRender;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author paulG
|
||||
* @since 2022/5/24
|
||||
**/
|
||||
@Component
|
||||
public class WholesaleSaleModelRenderImpl implements SalesModelRender {
|
||||
/**
|
||||
* 批发商品
|
||||
*/
|
||||
@Autowired
|
||||
private WholesaleService wholesaleService;
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void renderSingle(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
|
||||
Assert.notEmpty(goodsOperationDTO.getWholesaleList(), "批发规则不能为空");
|
||||
this.checkWholesaleList(goodsOperationDTO.getWholesaleList(), goodsSku);
|
||||
List<Wholesale> collect = goodsOperationDTO.getWholesaleList().stream().sorted(Comparator.comparing(Wholesale::getPrice)).collect(Collectors.toList());
|
||||
wholesaleService.removeByGoodsId(goodsSku.getGoodsId());
|
||||
wholesaleService.saveOrUpdateBatch(collect);
|
||||
goodsSku.setPrice(collect.get(0).getPrice());
|
||||
goodsSku.setCost(collect.get(0).getPrice());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void renderBatch(List<GoodsSku> goodsSkus, GoodsOperationDTO goodsOperationDTO) {
|
||||
Assert.notEmpty(goodsOperationDTO.getWholesaleList(), "批发规则不能为空");
|
||||
this.checkWholesaleList(goodsOperationDTO.getWholesaleList(), goodsSkus.get(0));
|
||||
List<Wholesale> collect = goodsOperationDTO.getWholesaleList().stream().sorted(Comparator.comparing(Wholesale::getPrice)).collect(Collectors.toList());
|
||||
for (GoodsSku skus : goodsSkus) {
|
||||
skus.setPrice(collect.get(0).getPrice());
|
||||
skus.setCost(collect.get(0).getPrice());
|
||||
}
|
||||
wholesaleService.removeByGoodsId(goodsSkus.get(0).getGoodsId());
|
||||
wholesaleService.saveOrUpdateBatch(collect);
|
||||
}
|
||||
|
||||
private void checkWholesaleList(List<WholesaleDTO> wholesaleList, GoodsSku goodsSku) {
|
||||
if (CollUtil.isEmpty(wholesaleList)) {
|
||||
throw new ServiceException(ResultCode.MUST_HAVE_SALES_MODEL);
|
||||
}
|
||||
for (WholesaleDTO wholesaleDTO : wholesaleList) {
|
||||
if (wholesaleDTO.getPrice() == null || wholesaleDTO.getPrice() <= 0 || wholesaleDTO.getNum() == null || wholesaleDTO.getNum() <= 0) {
|
||||
throw new ServiceException(ResultCode.HAVE_INVALID_SALES_MODEL);
|
||||
}
|
||||
if (CharSequenceUtil.isEmpty(wholesaleDTO.getGoodsId())) {
|
||||
wholesaleDTO.setGoodsId(goodsSku.getGoodsId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSalesMode() {
|
||||
return GoodsSalesModeEnum.WHOLESALE.name();
|
||||
}
|
||||
}
|
@ -42,4 +42,8 @@ public class MemberSign extends BaseIdEntity {
|
||||
@ApiModelProperty(value = "连续签到天数")
|
||||
private Integer signDay;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "签到日 为数字 从现在减去19700101 的日期")
|
||||
private Integer day;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -12,7 +12,7 @@ import lombok.Data;
|
||||
@Data
|
||||
public class EvaluationNumberVO {
|
||||
|
||||
@ApiModelProperty(value = "全部商品")
|
||||
@ApiModelProperty(value = "全部评价")
|
||||
private Integer all;
|
||||
|
||||
@ApiModelProperty(value = "好评数量")
|
||||
|
@ -18,17 +18,6 @@ import java.util.List;
|
||||
* @since 2020-02-25 14:10:16
|
||||
*/
|
||||
public interface FootprintMapper extends BaseMapper<FootPrint> {
|
||||
|
||||
/**
|
||||
* 获取用户足迹的SkuId分页
|
||||
*
|
||||
* @param page 分页
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 用户足迹的SkuId分页
|
||||
*/
|
||||
@Select("select sku_id from li_foot_print ${ew.customSqlSegment} ")
|
||||
List<String> footprintSkuIdList(IPage<String> page, @Param(Constants.WRAPPER) Wrapper<FootPrint> queryWrapper);
|
||||
|
||||
/**
|
||||
* 删除超过100条后的记录
|
||||
*
|
||||
|
@ -38,7 +38,7 @@ public interface MemberEvaluationMapper extends BaseMapper<MemberEvaluation> {
|
||||
* @param goodsId 商品ID
|
||||
* @return 会员评价
|
||||
*/
|
||||
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} and status='OPEN' GROUP BY grade")
|
||||
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} and status='OPEN' and delete_flag = false GROUP BY grade")
|
||||
List<Map<String, Object>> getEvaluationNumber(String goodsId);
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@ package cn.lili.modules.member.service;
|
||||
import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.modules.member.entity.dos.FootPrint;
|
||||
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
@ -44,7 +45,7 @@ public interface FootprintService extends IService<FootPrint> {
|
||||
* @param pageVO 分页
|
||||
* @return 会员浏览历史列表
|
||||
*/
|
||||
List<EsGoodsIndex> footPrintPage(PageVO pageVO);
|
||||
IPage<EsGoodsIndex> footPrintPage(PageVO pageVO);
|
||||
|
||||
/**
|
||||
* 获取当前会员的浏览记录数量
|
||||
|
@ -25,6 +25,11 @@ import java.util.Map;
|
||||
*/
|
||||
public interface MemberService extends IService<Member> {
|
||||
|
||||
/**
|
||||
* 默认密码
|
||||
*/
|
||||
static String DEFAULT_PASSWORD = "111111";
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户信息
|
||||
*
|
||||
@ -92,6 +97,29 @@ public interface MemberService extends IService<Member> {
|
||||
*/
|
||||
Member modifyPass(String memberId, String oldPassword, String newPassword);
|
||||
|
||||
/**
|
||||
* 是否可以初始化密码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean canInitPass();
|
||||
|
||||
/**
|
||||
* 初始化密码
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 操作结果
|
||||
*/
|
||||
void initPass(String password);
|
||||
|
||||
/**
|
||||
* 注销账号
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 操作结果
|
||||
*/
|
||||
void cancellation(String password);
|
||||
|
||||
/**
|
||||
* 注册会员
|
||||
*
|
||||
@ -257,6 +285,7 @@ public interface MemberService extends IService<Member> {
|
||||
|
||||
/**
|
||||
* 获取用户VO
|
||||
*
|
||||
* @param id 会员id
|
||||
* @return 用户VO
|
||||
*/
|
||||
|
@ -9,16 +9,18 @@ import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||
import cn.lili.modules.search.service.EsGoodsSearchService;
|
||||
import cn.lili.mybatis.util.PageUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 会员浏览历史业务层实现
|
||||
@ -29,9 +31,7 @@ import java.util.Objects;
|
||||
@Service
|
||||
public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, FootPrint> implements FootprintService {
|
||||
|
||||
/**
|
||||
* es商品业务层
|
||||
*/
|
||||
|
||||
@Autowired
|
||||
private EsGoodsSearchService esGoodsSearchService;
|
||||
|
||||
@ -74,20 +74,33 @@ public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, FootPrint
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EsGoodsIndex> footPrintPage(PageVO pageVO) {
|
||||
public IPage<EsGoodsIndex> footPrintPage(PageVO pageVO) {
|
||||
|
||||
LambdaQueryWrapper<FootPrint> lambdaQueryWrapper = Wrappers.lambdaQuery();
|
||||
lambdaQueryWrapper.eq(FootPrint::getMemberId, UserContext.getCurrentUser().getId());
|
||||
lambdaQueryWrapper.eq(FootPrint::getDeleteFlag, false);
|
||||
lambdaQueryWrapper.orderByDesc(FootPrint::getUpdateTime);
|
||||
List<String> skuIdList = this.baseMapper.footprintSkuIdList(PageUtil.initPage(pageVO), lambdaQueryWrapper);
|
||||
if (!skuIdList.isEmpty()) {
|
||||
List<EsGoodsIndex> list = esGoodsSearchService.getEsGoodsBySkuIds(skuIdList);
|
||||
lambdaQueryWrapper.orderByDesc(FootPrint::getCreateTime);
|
||||
IPage<FootPrint> footPrintPages = this.page(PageUtil.initPage(pageVO), lambdaQueryWrapper);
|
||||
|
||||
|
||||
//定义结果
|
||||
IPage<EsGoodsIndex> esGoodsIndexIPage = new Page<>();
|
||||
|
||||
if (footPrintPages.getRecords() == null || footPrintPages.getRecords().isEmpty()) {
|
||||
return esGoodsIndexIPage;
|
||||
} else {
|
||||
List<EsGoodsIndex> list = esGoodsSearchService.getEsGoodsBySkuIds(
|
||||
footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()));
|
||||
//去除为空的商品数据
|
||||
list.removeIf(Objects::isNull);
|
||||
return list;
|
||||
|
||||
esGoodsIndexIPage.setPages(footPrintPages.getPages());
|
||||
esGoodsIndexIPage.setRecords(list);
|
||||
esGoodsIndexIPage.setTotal(footPrintPages.getTotal());
|
||||
esGoodsIndexIPage.setSize(footPrintPages.getSize());
|
||||
esGoodsIndexIPage.setCurrent(footPrintPages.getCurrent());
|
||||
return esGoodsIndexIPage;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user