diff --git a/DB/version4.2.4toMASTER.sql b/DB/version4.2.4toMASTER.sql deleted file mode 100644 index a00128f7..00000000 --- a/DB/version4.2.4toMASTER.sql +++ /dev/null @@ -1,51 +0,0 @@ -/** 增加签到日期 **/ -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 '批发规则表'; - -ALTER TABLE li_wholesale - ADD template_id bigint DEFAULT NULL COMMENT '商品模版id'; - -/** 店铺--默认页面是否开启**/ -ALTER TABLE li_store ADD page_show bit(1) DEFAULT NULL COMMENT '默认页面是否开启'; \ No newline at end of file diff --git a/DB/version4.2.5toMASTER.sql b/DB/version4.2.5toMASTER.sql new file mode 100644 index 00000000..1a211ecd --- /dev/null +++ b/DB/version4.2.5toMASTER.sql @@ -0,0 +1,82 @@ + +/** 优惠券活动增加领取周期字段 **/ +ALTER TABLE li_coupon_activity ADD coupon_frequency_enum varchar(255) COMMENT '领取周期'; +-- 会员优惠券标识 +CREATE TABLE `li_member_coupon_sign` ( + `id` bigint NOT NULL, + `coupon_activity_Id` bigint NULL DEFAULT NULL COMMENT '优惠券活动id', + `member_id` bigint NULL DEFAULT NULL COMMENT '会员id', + `invalid_time` datetime NULL DEFAULT NULL COMMENT '过期时间', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC; + +/** + IM聊天 + */ +CREATE TABLE `li_im_talk` ( + `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `delete_flag` bit(1) DEFAULT NULL COMMENT '删除标志', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者', + `update_time` datetime(6) DEFAULT NULL COMMENT '修改时间', + `user_id1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户1Id', + `user_id2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户2Id', + `name1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户1名称', + `name2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户2名称', + `face1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户1头像', + `face2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户2头像', + `top1` bit(1) DEFAULT NULL COMMENT '用户1置顶标识', + `top2` bit(1) DEFAULT NULL COMMENT '用户2置顶标识', + `disable1` bit(1) DEFAULT NULL COMMENT '用户1禁用标识', + `disable2` bit(1) DEFAULT NULL COMMENT '用户2禁用标识', + `store_flag1` bit(1) DEFAULT NULL COMMENT '用户1店铺标识', + `store_flag2` bit(1) DEFAULT NULL COMMENT '用户2店铺标识', + `last_talk_time` datetime DEFAULT NULL COMMENT '最后聊天时间', + `last_talk_message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '最后的消息', + `last_message_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '最后消息类型', + `talk_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '聊天Id', + `tenant_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '坐席Id', + `tenant_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '坐席名称', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +/** + IM消息 + */ +CREATE TABLE `li_im_message` ( + `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `delete_flag` bit(1) DEFAULT NULL COMMENT '删除标识', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '修改者', + `update_time` datetime(6) DEFAULT NULL COMMENT '修改标识', + `from_user` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发送用户Id', + `to_user` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '接收用户Id', + `is_read` bit(1) DEFAULT NULL COMMENT '已读标识', + `message_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '聊天类型', + `text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '聊天内容', + `talk_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '聊天Id', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + + +/** + 订单增加自提信息 + */ +ALTER TABLE li_order ADD `store_address_path` varchar(255) DEFAULT NULL; +ALTER TABLE li_order ADD `store_address_center` varchar(255) DEFAULT NULL; +ALTER TABLE li_order ADD `store_address_mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL; + +/** + 店铺是否开启自提 + */ +ALTER TABLE li_store ADD `self_pick_flag` bit(1) DEFAULT NULL; +/** + 历史足迹增加店铺Id + */ +ALTER TABLE li_foot_print ADD `store_id` varchar(255) DEFAULT NULL COMMENT '店铺ID'; \ No newline at end of file diff --git a/buyer-api/src/main/java/cn/lili/controller/distribution/DistributionGoodsBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/distribution/DistributionGoodsBuyerController.java index cbc01db4..31048556 100644 --- a/buyer-api/src/main/java/cn/lili/controller/distribution/DistributionGoodsBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/distribution/DistributionGoodsBuyerController.java @@ -54,22 +54,22 @@ public class DistributionGoodsBuyerController { @PreventDuplicateSubmissions @ApiOperation(value = "选择分销商品") @ApiImplicitParams({ - @ApiImplicitParam(name = "distributionGoodsId", value = "分销ID", required = true, dataType = "String", paramType = "path"), + @ApiImplicitParam(name = "distributionGoodsId", value = "分销ID", required = true, dataType = "String", paramType = "path"), @ApiImplicitParam(name = "checked", value = "是否选择", required = true, dataType = "boolean", paramType = "query") }) @GetMapping(value = "/checked/{distributionGoodsId}") public ResultMessage distributionCheckGoods( - @NotNull(message = "分销商品不能为空") @PathVariable("distributionGoodsId") String distributionGoodsId,Boolean checked) { - Boolean result=false; - if(checked){ - result=distributionSelectedGoodsService.add(distributionGoodsId); - }else { - result=distributionSelectedGoodsService.delete(distributionGoodsId); + @NotNull(message = "分销商品不能为空") @PathVariable("distributionGoodsId") String distributionGoodsId, Boolean checked) { + Boolean result = false; + if (checked) { + result = distributionSelectedGoodsService.add(distributionGoodsId); + } else { + result = distributionSelectedGoodsService.delete(distributionGoodsId); } //判断操作结果 - if(result){ + if (result) { return ResultUtil.success(ResultCode.SUCCESS); - }else{ + } else { throw new ServiceException(ResultCode.ERROR); } diff --git a/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java b/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java index e5de7c6b..480b8823 100644 --- a/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java +++ b/buyer-api/src/main/java/cn/lili/controller/member/FootprintController.java @@ -1,14 +1,17 @@ package cn.lili.controller.member; import cn.lili.common.enums.ResultUtil; +import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; +import cn.lili.modules.member.entity.dto.FootPrintQueryParams; 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; +import org.apache.catalina.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -35,8 +38,9 @@ public class FootprintController { @ApiOperation(value = "分页获取") @GetMapping - public ResultMessage> getByPage(PageVO page) { - return ResultUtil.data(footprintService.footPrintPage(page)); + public ResultMessage> getByPage(FootPrintQueryParams params) { + params.setMemberId(UserContext.getCurrentUser().getId()); + return ResultUtil.data(footprintService.footPrintPage(params)); } @ApiOperation(value = "根据id删除") @@ -61,4 +65,10 @@ public class FootprintController { return ResultUtil.data(footprintService.getFootprintNum()); } + + @GetMapping("/history") + @ApiOperation(value = "获取会员的历史足迹") + public ResultMessage> getMemberHistory(FootPrintQueryParams params) { + return ResultUtil.data(footprintService.footPrintPage(params)); + } } diff --git a/buyer-api/src/main/java/cn/lili/controller/order/CartController.java b/buyer-api/src/main/java/cn/lili/controller/order/CartController.java index f78e4d78..005a1c0c 100644 --- a/buyer-api/src/main/java/cn/lili/controller/order/CartController.java +++ b/buyer-api/src/main/java/cn/lili/controller/order/CartController.java @@ -189,20 +189,38 @@ public class CartController { } } + @ApiOperation(value = "选择自提地址") + @ApiImplicitParams({ + @ApiImplicitParam(name = "storeAddressId", value = "自提地址id ", required = true, paramType = "query"), + @ApiImplicitParam(name = "way", value = "购物车类型 ", paramType = "query") + }) + @GetMapping("/storeAddress") + public ResultMessage shippingSelfPickAddress(@NotNull(message = "自提地址ID不能为空") String storeAddressId, + String way) { + try { + cartService.shippingSelfAddress(storeAddressId, way); + return ResultUtil.success(); + } catch (ServiceException se) { + log.error(ResultCode.SHIPPING_NOT_APPLY.message(), se); + throw new ServiceException(ResultCode.SHIPPING_NOT_APPLY); + } catch (Exception e) { + log.error(ResultCode.CART_ERROR.message(), e); + throw new ServiceException(ResultCode.CART_ERROR); + } + } + @ApiOperation(value = "选择配送方式") @ApiImplicitParams({ @ApiImplicitParam(name = "shippingMethod", value = "配送方式:SELF_PICK_UP(自提)," + "LOCAL_TOWN_DELIVERY(同城配送)," + "LOGISTICS(物流) ", required = true, paramType = "query"), - @ApiImplicitParam(name = "selleId", value = "店铺id", paramType = "query"), @ApiImplicitParam(name = "way", value = "购物车类型 ", paramType = "query") }) - @GetMapping("/shippingMethod") + @PutMapping("/shippingMethod") public ResultMessage shippingMethod(@NotNull(message = "配送方式不能为空") String shippingMethod, - String selleId, String way) { try { - cartService.shippingMethod(selleId, shippingMethod, way); + cartService.shippingMethod( shippingMethod, way); return ResultUtil.success(); } catch (ServiceException se) { log.error(se.getMsg(), se); @@ -213,6 +231,21 @@ public class CartController { } } + @ApiOperation(value = "获取用户可选择的物流方式") + @ApiImplicitParams({ + @ApiImplicitParam(name = "way", value = "购物车类型 ", paramType = "query") + }) + @GetMapping("/shippingMethodList") + public ResultMessage shippingMethodList(String way) { + try { + return ResultUtil.data(cartService.shippingMethodList(way)); + } + catch (Exception e) { + e.printStackTrace(); + return ResultUtil.error(ResultCode.ERROR); + } + } + @ApiOperation(value = "选择发票") @ApiImplicitParams({ @ApiImplicitParam(name = "way", value = "购物车购买:CART/立即购买:BUY_NOW/拼团购买:PINTUAN / 积分购买:POINT ", required = true, paramType = "query"), diff --git a/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java index 08251f15..1dfcb000 100644 --- a/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java @@ -128,5 +128,4 @@ public class OrderBuyerController { return ResultUtil.data(orderService.invoice(orderSn)); } - } diff --git a/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java index 5a9e86b5..8615bf34 100644 --- a/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/passport/MemberBuyerController.java @@ -3,6 +3,8 @@ package cn.lili.controller.passport; import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.ResultUtil; import cn.lili.common.exception.ServiceException; +import cn.lili.common.security.AuthUser; +import cn.lili.common.security.context.UserContext; import cn.lili.common.security.enums.UserEnums; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.member.entity.dos.Member; @@ -264,4 +266,18 @@ public class MemberBuyerController { return ResultUtil.data(this.memberService.refreshToken(refreshToken)); } + @GetMapping("/getImUser") + @ApiOperation(value = "获取用户信息") + public ResultMessage getImUser() { + AuthUser authUser = UserContext.getCurrentUser(); + return ResultUtil.data(memberService.getById(authUser.getId())); + } + + @GetMapping("/getImUserDetail/{memberId}") + @ApiImplicitParam(name = "memberId", value = "店铺Id", required = true, dataType = "String", paramType = "path") + @ApiOperation(value = "获取用户信息") + public ResultMessage getImUserDetail(@PathVariable String memberId) { + return ResultUtil.data(memberService.getById(memberId)); + } + } diff --git a/buyer-api/src/main/java/cn/lili/controller/promotion/CouponBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/promotion/CouponBuyerController.java index 4d0dfed4..e505cb58 100644 --- a/buyer-api/src/main/java/cn/lili/controller/promotion/CouponBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/promotion/CouponBuyerController.java @@ -7,11 +7,14 @@ import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.promotion.entity.dos.MemberCoupon; +import cn.lili.modules.promotion.entity.dto.CouponActivityTrigger; import cn.lili.modules.promotion.entity.dto.search.CouponSearchParams; import cn.lili.modules.promotion.entity.dto.search.MemberCouponSearchParams; +import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum; import cn.lili.modules.promotion.entity.enums.CouponGetEnum; import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.entity.vos.CouponVO; +import cn.lili.modules.promotion.service.CouponActivityService; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.MemberCouponService; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -26,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.NotNull; +import java.util.List; import java.util.Objects; /** @@ -45,12 +49,30 @@ public class CouponBuyerController { @Autowired private CouponService couponService; + /** + * 优惠券活动 + */ + @Autowired + private CouponActivityService couponActivityService; + /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; + @GetMapping("/activity") + @ApiOperation(value = "自动领取优惠券") + public ResultMessage> activity() { + return ResultUtil.data(couponActivityService.trigger( + CouponActivityTrigger.builder() + .couponActivityTypeEnum(CouponActivityTypeEnum.AUTO_COUPON) + .nickName(UserContext.getCurrentUser().getNickName()) + .userId(UserContext.getCurrentUser().getId()) + .build()) + ); + } + @GetMapping @ApiOperation(value = "获取可领取优惠券列表") public ResultMessage> getCouponList(CouponSearchParams queryParam, PageVO page) { diff --git a/buyer-api/src/main/java/cn/lili/controller/store/StoreAddressBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/store/StoreAddressBuyerController.java new file mode 100644 index 00000000..a51acdf4 --- /dev/null +++ b/buyer-api/src/main/java/cn/lili/controller/store/StoreAddressBuyerController.java @@ -0,0 +1,53 @@ +package cn.lili.controller.store; + +import cn.lili.common.enums.ResultUtil; +import cn.lili.common.security.OperationalJudgment; +import cn.lili.common.security.context.UserContext; +import cn.lili.common.vo.PageVO; +import cn.lili.common.vo.ResultMessage; +import cn.lili.modules.store.entity.dos.StoreAddress; +import cn.lili.modules.store.service.StoreAddressService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Objects; + +/** + * 买家端,商家地址(自提点)接口 + * + * @author chc + * @since 2022/6/2114:46 + */ +@RestController +@Api(tags = "买家端,商家地址(自提点)接口") +@RequestMapping("/buyer/store/address") +public class StoreAddressBuyerController { + + /** + * 店铺自提点 + */ + @Autowired + private StoreAddressService storeAddressService; + + @ApiOperation(value = "获取商家自提点分页") + @ApiImplicitParam(name = "storeId", value = "店铺Id", required = true, dataType = "String", paramType = "path") + @GetMapping("/page/{storeId}") + public ResultMessage> get(PageVO pageVo,@PathVariable String storeId) { + return ResultUtil.data(storeAddressService.getStoreAddress(storeId, pageVo)); + } + + @ApiOperation(value = "获取商家自提点信息") + @ApiImplicitParam(name = "id", value = "自提点ID", required = true, paramType = "path") + @GetMapping("/{id}") + public ResultMessage get(@PathVariable String id) { + StoreAddress address = OperationalJudgment.judgment(storeAddressService.getById(id)); + return ResultUtil.data(address); + } +} diff --git a/buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java index 6e6a7ca7..35bdfbd2 100644 --- a/buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java @@ -1,11 +1,13 @@ package cn.lili.controller.store; import cn.lili.common.enums.ResultUtil; +import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.goods.entity.vos.StoreGoodsLabelVO; import cn.lili.modules.goods.service.StoreGoodsLabelService; +import cn.lili.modules.store.entity.dos.Store; import cn.lili.modules.store.entity.dto.StoreBankDTO; import cn.lili.modules.store.entity.dto.StoreCompanyDTO; import cn.lili.modules.store.entity.dto.StoreOtherInfoDTO; @@ -57,6 +59,20 @@ public class StoreBuyerController { return ResultUtil.data(storeService.findByConditionPage(entity, page)); } + @GetMapping("/store") + @ApiOperation(value = "im-获取店铺信息") + public ResultMessage getStoreUser() { + AuthUser authUser = UserContext.getCurrentUser(); + return ResultUtil.data(storeService.getById(authUser.getStoreId())); + } + + @GetMapping("/store/{storeId}") + @ApiImplicitParam(name = "storeId", value = "店铺Id", required = true, dataType = "String", paramType = "path") + @ApiOperation(value = "im-店铺ID获取店铺信息") + public ResultMessage getStoreUserDetail(@PathVariable String storeId) { + return ResultUtil.data(storeService.getById(storeId)); + } + @ApiOperation(value = "通过id获取店铺信息") @ApiImplicitParam(name = "id", value = "店铺ID", required = true, paramType = "path") @GetMapping(value = "/get/detail/{id}") diff --git a/buyer-api/src/main/resources/application.yml b/buyer-api/src/main/resources/application.yml index f3a7a5a6..04c87cf4 100644 --- a/buyer-api/src/main/resources/application.yml +++ b/buyer-api/src/main/resources/application.yml @@ -265,6 +265,8 @@ lili: order-group: lili_order_group member-topic: lili_member_topic member-group: lili_member_group + store-topic: lili_store_topic + store-group: lili_store_group other-topic: lili_other_topic other-group: lili_other_group notice-topic: lili_notice_topic diff --git a/consumer/src/main/java/cn/lili/event/MemberInfoChangeEvent.java b/consumer/src/main/java/cn/lili/event/MemberInfoChangeEvent.java new file mode 100644 index 00000000..51dbd391 --- /dev/null +++ b/consumer/src/main/java/cn/lili/event/MemberInfoChangeEvent.java @@ -0,0 +1,17 @@ +package cn.lili.event; + +import cn.lili.modules.member.entity.dos.Member; + +/** + * @author chc + * @since 2022/6/2114:46 + */ +public interface MemberInfoChangeEvent { + + /** + * 会员信息更改消息 + * + * @param member 会员信息 + */ + void memberInfoChange(Member member); +} diff --git a/consumer/src/main/java/cn/lili/event/StoreSettingChangeEvent.java b/consumer/src/main/java/cn/lili/event/StoreSettingChangeEvent.java new file mode 100644 index 00000000..53fb83b6 --- /dev/null +++ b/consumer/src/main/java/cn/lili/event/StoreSettingChangeEvent.java @@ -0,0 +1,18 @@ +package cn.lili.event; + + +import cn.lili.modules.store.entity.dos.Store; + +/** + * @author chc + * @since 2022/6/2114:46 + */ +public interface StoreSettingChangeEvent { + + /** + * 店铺信息更改消息 + * + * @param store 店铺信息 + */ + void storeSettingChange(Store store); +} diff --git a/consumer/src/main/java/cn/lili/event/impl/DistributionOrderExecute.java b/consumer/src/main/java/cn/lili/event/impl/DistributionOrderExecute.java index 7b9f138a..4edd7f41 100644 --- a/consumer/src/main/java/cn/lili/event/impl/DistributionOrderExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/DistributionOrderExecute.java @@ -44,8 +44,9 @@ public class DistributionOrderExecute implements OrderStatusChangeEvent, EveryDa public void orderChange(OrderMessage orderMessage) { switch (orderMessage.getNewStatus()) { - //订单带校验/订单代发货,则记录分销信息 + //订单带校验/订单代发货/待自提,则记录分销信息 case TAKE: + case STAY_PICKED_UP: case UNDELIVERED: { //记录分销订单 distributionOrderService.calculationDistribution(orderMessage.getOrderSn()); diff --git a/consumer/src/main/java/cn/lili/event/impl/ImTalkExecute.java b/consumer/src/main/java/cn/lili/event/impl/ImTalkExecute.java new file mode 100644 index 00000000..b631589f --- /dev/null +++ b/consumer/src/main/java/cn/lili/event/impl/ImTalkExecute.java @@ -0,0 +1,60 @@ +package cn.lili.event.impl; + +import cn.lili.event.MemberInfoChangeEvent; +import cn.lili.event.StoreSettingChangeEvent; +import cn.lili.modules.im.entity.dos.ImTalk; +import cn.lili.modules.im.service.ImTalkService; +import cn.lili.modules.member.entity.dos.Member; +import cn.lili.modules.store.entity.dos.Store; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * Im对话消息 + * + * @author chc + * @since 2022/6/2114:46 + */ +@Service +public class ImTalkExecute implements MemberInfoChangeEvent, StoreSettingChangeEvent { + + @Autowired + private ImTalkService imTalkService; + + @Override + public void memberInfoChange(Member member) { + //当与UserId1相等时 + List imTalkList1 = imTalkService.list(new LambdaQueryWrapper().eq(ImTalk::getUserId1, member.getId())); + for (ImTalk imTalk : imTalkList1) { + imTalk.setName1(member.getNickName()); + imTalk.setFace1(member.getFace()); + } + imTalkService.updateBatchById(imTalkList1); + List imTalkList2 = imTalkService.list(new LambdaQueryWrapper().eq(ImTalk::getUserId2, member.getId())); + for (ImTalk imTalk : imTalkList2) { + imTalk.setName2(member.getNickName()); + imTalk.setFace2(member.getFace()); + } + imTalkService.updateBatchById(imTalkList2); + } + + @Override + public void storeSettingChange(Store store) { + //当与UserId1相等时 + List imTalkList1 = imTalkService.list(new LambdaQueryWrapper().eq(ImTalk::getUserId1, store.getId())); + for (ImTalk imTalk : imTalkList1) { + imTalk.setName1(store.getStoreName()); + imTalk.setFace1(store.getStoreLogo()); + } + imTalkService.updateBatchById(imTalkList1); + List imTalkList2 = imTalkService.list(new LambdaQueryWrapper().eq(ImTalk::getUserId2, store.getId())); + for (ImTalk imTalk : imTalkList2) { + imTalk.setName2(store.getStoreName()); + imTalk.setFace2(store.getStoreLogo()); + } + imTalkService.updateBatchById(imTalkList2); + } +} diff --git a/consumer/src/main/java/cn/lili/event/impl/RegisteredCouponActivityExecute.java b/consumer/src/main/java/cn/lili/event/impl/RegisteredCouponActivityExecute.java index a103b767..ccd14038 100644 --- a/consumer/src/main/java/cn/lili/event/impl/RegisteredCouponActivityExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/RegisteredCouponActivityExecute.java @@ -1,18 +1,17 @@ package cn.lili.event.impl; +import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.cache.Cache; +import cn.lili.cache.CachePrefix; import cn.lili.event.MemberRegisterEvent; import cn.lili.modules.member.entity.dos.Member; -import cn.lili.modules.promotion.entity.dos.CouponActivity; +import cn.lili.modules.member.service.MemberService; +import cn.lili.modules.promotion.entity.dto.CouponActivityTrigger; import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum; -import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.service.CouponActivityService; -import cn.lili.modules.promotion.tools.PromotionTools; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.List; - /** * 注册赠券活动 * @@ -25,6 +24,12 @@ public class RegisteredCouponActivityExecute implements MemberRegisterEvent { @Autowired private CouponActivityService couponActivityService; + + @Autowired + private MemberService memberService; + @Autowired + private Cache cache; + /** * 获取进行中的注册赠券的优惠券活动 * 发送注册赠券 @@ -33,9 +38,22 @@ public class RegisteredCouponActivityExecute implements MemberRegisterEvent { */ @Override public void memberRegister(Member member) { - List couponActivities = couponActivityService.list(new QueryWrapper() - .eq("coupon_activity_type", CouponActivityTypeEnum.REGISTERED.name()) - .and(PromotionTools.queryPromotionStatus(PromotionsStatusEnum.START))); - couponActivityService.registered(couponActivities, member); + //用户注册赠券 + couponActivityService.trigger(CouponActivityTrigger.builder() + .nickName(member.getNickName()) + .userId(member.getId()) + .couponActivityTypeEnum(CouponActivityTypeEnum.REGISTERED) + .build()); + //邀请人赠券 + String memberId = (String) cache.get(CachePrefix.INVITER.getPrefix() + member.getId()); + if (CharSequenceUtil.isNotEmpty(memberId)) { + //邀请人 + Member inviter = memberService.getById(memberId); + couponActivityService.trigger(CouponActivityTrigger.builder() + .nickName(inviter.getNickName()) + .userId(inviter.getId()) + .couponActivityTypeEnum(CouponActivityTypeEnum.INVITE_NEW) + .build()); + } } } diff --git a/consumer/src/main/java/cn/lili/event/impl/VerificationOrderExecute.java b/consumer/src/main/java/cn/lili/event/impl/VerificationOrderExecute.java index 008a2fc2..a0b50055 100644 --- a/consumer/src/main/java/cn/lili/event/impl/VerificationOrderExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/VerificationOrderExecute.java @@ -31,7 +31,7 @@ public class VerificationOrderExecute implements OrderStatusChangeEvent { @Override public void orderChange(OrderMessage orderMessage) { //订单状态为待核验,添加订单添加核验码 - if (orderMessage.getNewStatus().equals(OrderStatusEnum.TAKE)) { + if (orderMessage.getNewStatus().equals(OrderStatusEnum.TAKE) || orderMessage.getNewStatus().equals(OrderStatusEnum.STAY_PICKED_UP)) { //获取订单信息 Order order = orderService.getBySn(orderMessage.getOrderSn()); //获取随机数,判定是否存在 diff --git a/consumer/src/main/java/cn/lili/event/impl/WechatMessageExecute.java b/consumer/src/main/java/cn/lili/event/impl/WechatMessageExecute.java index cbab13e4..58fd2e27 100644 --- a/consumer/src/main/java/cn/lili/event/impl/WechatMessageExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/WechatMessageExecute.java @@ -42,6 +42,7 @@ public class WechatMessageExecute implements OrderStatusChangeEvent, TradeEvent case PAID: case UNDELIVERED: case DELIVERED: + case STAY_PICKED_UP: case COMPLETED: try { wechatMessageUtil.sendWechatMessage(orderMessage.getOrderSn()); diff --git a/consumer/src/main/java/cn/lili/listener/MemberMessageListener.java b/consumer/src/main/java/cn/lili/listener/MemberMessageListener.java index ab767f10..2e384744 100644 --- a/consumer/src/main/java/cn/lili/listener/MemberMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/MemberMessageListener.java @@ -1,10 +1,8 @@ package cn.lili.listener; import cn.hutool.json.JSONUtil; -import cn.lili.event.MemberLoginEvent; -import cn.lili.event.MemberPointChangeEvent; -import cn.lili.event.MemberRegisterEvent; -import cn.lili.event.MemberWithdrawalEvent; +import cn.lili.event.*; +import cn.lili.event.impl.ImTalkExecute; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.entity.dos.MemberSign; import cn.lili.modules.member.entity.dto.MemberPointMessage; @@ -58,6 +56,9 @@ public class MemberMessageListener implements RocketMQListener { @Autowired private List memberLoginEvents; + @Autowired + private List memberInfoChangeEvents; + @Override public void onMessage(MessageExt messageExt) { @@ -110,6 +111,20 @@ public class MemberMessageListener implements RocketMQListener { } } break; + //会员信息更改 + case MEMBER_INFO_EDIT: + for (MemberInfoChangeEvent memberInfoChangeEvent : memberInfoChangeEvents) { + try { + Member member = JSONUtil.toBean(new String(messageExt.getBody()), Member.class); + memberInfoChangeEvent.memberInfoChange(member); + } catch (Exception e) { + log.error("会员{},在{}业务中,提现事件执行异常", + new String(messageExt.getBody()), + memberInfoChangeEvent.getClass().getName(), + e); + } + } + break; //会员提现 case MEMBER_WITHDRAWAL: for (MemberWithdrawalEvent memberWithdrawalEvent : memberWithdrawalEvents) { diff --git a/consumer/src/main/java/cn/lili/listener/StoreMessageListener.java b/consumer/src/main/java/cn/lili/listener/StoreMessageListener.java new file mode 100644 index 00000000..243de85f --- /dev/null +++ b/consumer/src/main/java/cn/lili/listener/StoreMessageListener.java @@ -0,0 +1,51 @@ +package cn.lili.listener; + +import cn.hutool.json.JSONUtil; +import cn.lili.event.MemberRegisterEvent; +import cn.lili.event.StoreSettingChangeEvent; +import cn.lili.modules.member.entity.dos.Member; +import cn.lili.modules.store.entity.dos.Store; +import cn.lili.rocketmq.tags.StoreTagsEnum; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 店铺消息 + * @author chc + * @since 2022/6/2114:46 + */ +@Component +@Slf4j +@RocketMQMessageListener(topic = "${lili.data.rocketmq.store-topic}", consumerGroup = "${lili.data.rocketmq.store-group}") +public class StoreMessageListener implements RocketMQListener { + @Autowired + private List storeSettingChangeEventList; + + @Override + public void onMessage(MessageExt messageExt) { + switch (StoreTagsEnum.valueOf(messageExt.getTags())){ + //修改店铺 + case EDIT_STORE_SETTING: + for (StoreSettingChangeEvent storeSettingChangeEvent : storeSettingChangeEventList) { + try { + Store store = JSONUtil.toBean(new String(messageExt.getBody()), Store.class); + storeSettingChangeEvent.storeSettingChange(store); + } catch (Exception e) { + log.error("会员{},在{}业务中,状态修改事件执行异常", + new String(messageExt.getBody()), + storeSettingChangeEvent.getClass().getName(), + e); + } + } + break; + default: + break; + } + } +} diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/MemberCouponSignEverydayExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/MemberCouponSignEverydayExecute.java new file mode 100644 index 00000000..13a5e7a3 --- /dev/null +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/MemberCouponSignEverydayExecute.java @@ -0,0 +1,45 @@ +package cn.lili.timetask.handler.impl.promotion; + +import cn.lili.common.enums.PromotionTypeEnum; +import cn.lili.modules.promotion.entity.dos.Seckill; +import cn.lili.modules.promotion.service.MemberCouponSignService; +import cn.lili.modules.promotion.service.SeckillService; +import cn.lili.modules.promotion.tools.PromotionTools; +import cn.lili.modules.search.service.EsGoodsIndexService; +import cn.lili.modules.system.entity.dos.Setting; +import cn.lili.modules.system.entity.dto.SeckillSetting; +import cn.lili.modules.system.entity.enums.SettingEnum; +import cn.lili.modules.system.service.SettingService; +import cn.lili.timetask.handler.EveryDayExecute; +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 促销活动每日定时器 + * + * @author Chopper + * @since 2021/3/18 3:23 下午 + */ +@Slf4j +@Component +public class MemberCouponSignEverydayExecute implements EveryDayExecute { + + @Autowired + private MemberCouponSignService memberCouponSignService; + + /** + * 将已过期的促销活动置为结束 + */ + @Override + public void execute() { + try { + memberCouponSignService.clean(); + } catch (Exception e) { + log.error("清除领取优惠券标记异常", e); + } + + } + +} diff --git a/consumer/src/main/resources/application.yml b/consumer/src/main/resources/application.yml index ae49a9b8..f3c3ed20 100644 --- a/consumer/src/main/resources/application.yml +++ b/consumer/src/main/resources/application.yml @@ -260,6 +260,8 @@ lili: order-group: lili_order_group member-topic: lili_member_topic member-group: lili_member_group + store-topic: lili_store_topic + store-group: lili_store_group other-topic: lili_other_topic other-group: lili_other_group notice-topic: lili_notice_topic diff --git a/framework/pom.xml b/framework/pom.xml index da681cb3..5e0b4b74 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -51,7 +51,10 @@ - + + org.springframework.boot + spring-boot-starter-websocket + org.springframework.boot spring-boot-starter-web diff --git a/framework/src/main/java/cn/lili/cache/CachePrefix.java b/framework/src/main/java/cn/lili/cache/CachePrefix.java index bfa31f49..c1481c65 100644 --- a/framework/src/main/java/cn/lili/cache/CachePrefix.java +++ b/framework/src/main/java/cn/lili/cache/CachePrefix.java @@ -208,6 +208,10 @@ public enum CachePrefix { * 促销活动 */ PROMOTION, + /** + * 当前优惠券活动 + */ + CURRENT_COUPON_ACTIVITY, /** * 促销活动 */ @@ -236,6 +240,10 @@ public enum CachePrefix { * 积分商品缓存key前缀 */ STORE_ID_EXCHANGE, + /** + * 会员领取标记 + */ + MEMBER_COUPON_SIGN, //================交易================= @@ -441,6 +449,10 @@ public enum CachePrefix { * 分销员 */ DISTRIBUTION, + /** + * 邀请人 + */ + INVITER, /** * 找回手机 @@ -503,12 +515,11 @@ public enum CachePrefix { /** * 扫码登录 + * * @param str * @return */ - QR_CODE_LOGIN_SESSION - - ; + QR_CODE_LOGIN_SESSION; public static String removePrefix(String str) { diff --git a/framework/src/main/java/cn/lili/cache/impl/RedisCache.java b/framework/src/main/java/cn/lili/cache/impl/RedisCache.java index a5e8aeec..ac56702b 100644 --- a/framework/src/main/java/cn/lili/cache/impl/RedisCache.java +++ b/framework/src/main/java/cn/lili/cache/impl/RedisCache.java @@ -185,7 +185,7 @@ public class RedisCache implements Cache { public Long counter(Object key) { HyperLogLogOperations operations = redisTemplate.opsForHyperLogLog(); - //add 方法对应 PFADD 命令 + //add 方法对应 PFCOUNT 命令 return operations.size(key); } diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index 6acf99dd..1693f24e 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -193,6 +193,7 @@ public enum ResultCode { ORDER_NOT_USER(31007, "非当前会员的订单"), ORDER_TAKE_ERROR(31008, "当前订单无法核销"), MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"), + STORE_ADDRESS_NOT_EXIST(31009,"订单没有自提地址,请先选择自提地址"), ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"), ORDER_NOT_SUPPORT_DISTRIBUTION(31011, "购物车中包含不支持配送的商品,请重新选择收货地址,或者重新选择商品"), ORDER_NOT_EXIST_VALID(31041, "购物车中无有效商品,请检查购物车内商品,或者重新选择商品"), @@ -280,6 +281,7 @@ public enum ResultCode { PROMOTION_ACTIVITY_GOODS_ERROR(40009, "当前活动已经开始无法添加商品"), PROMOTION_ACTIVITY_ERROR(400010, "当前促销活动不存在"), PROMOTION_LOG_EXIST(40011, "活动已参加,已发重复参加"), + APPLY_END_TIME_ERROR(40012, "参与截至时间不能小于当前时间,不能大于活动开始时间"), /** * 优惠券 @@ -301,6 +303,7 @@ public enum ResultCode { COUPON_SCOPE_ERROR(41014, "指定商品范围关联id无效!"), COUPON_MEMBER_NOT_EXIST(41015, "没有当前会员优惠券"), COUPON_MEMBER_STATUS_ERROR(41016, "当前会员优惠券已过期/作废无法变更状态!"), + COUPON_RANGE_ERROR(41017, "优惠券使用时间范围错误"), SPECIAL_CANT_USE(41019, "特殊商品不能使用优惠券,不能使用"), @@ -308,7 +311,7 @@ public enum ResultCode { COUPON_DELETE_ERROR(41021, "删除优惠券失败"), COUPON_ACTIVITY_NOT_EXIST(41022, "当前优惠券活动不存在"), COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"), - COUPON_ACTIVITY_MAX_NUM(41024, "优惠券活动赠券数量最多为3"), + COUPON_ACTIVITY_MAX_NUM(41024, "优惠券活动赠券数量最多为5"), COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"), @@ -373,6 +376,7 @@ public enum ResultCode { COUPON_ACTIVITY_ITEM_ERROR(46003, "优惠券活动必须指定优惠券,不能为空"), COUPON_ACTIVITY_ITEM_MUST_NUM_ERROR(46004, "优惠券活动最多指定10个优惠券"), COUPON_ACTIVITY_ITEM_NUM_ERROR(46005, "赠券数量必须大于0"), + COUPON_ACTIVITY_ITEM_NUM_MAX_VALUE_2(46006, "赠券数量最大为2"), /** * 其他促销 @@ -444,6 +448,7 @@ public enum ResultCode { ALIPAY_EXCEPTION(70003, "支付宝支付错误,请稍后重试"), ALIPAY_PARAMS_EXCEPTION(70004, "支付宝参数异常"), LOGISTICS_NOT_SETTING(70005, "您还未配置快递查询"), + LOGISTICS_CHECK_SETTING(70005, "操作失败,请检查您的快递鸟配置"), ORDER_SETTING_ERROR(70006, "系统订单配置异常"), ALI_SMS_SETTING_ERROR(70007, "您还未配置阿里云短信"), SMS_SIGN_EXIST_ERROR(70008, "短信签名已存在"), diff --git a/framework/src/main/java/cn/lili/common/security/AuthUser.java b/framework/src/main/java/cn/lili/common/security/AuthUser.java index f49f2051..819ae6e6 100644 --- a/framework/src/main/java/cn/lili/common/security/AuthUser.java +++ b/framework/src/main/java/cn/lili/common/security/AuthUser.java @@ -3,6 +3,7 @@ package cn.lili.common.security; import cn.lili.common.security.enums.UserEnums; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serializable; @@ -10,6 +11,7 @@ import java.io.Serializable; * @author Chopper */ @Data +@NoArgsConstructor @AllArgsConstructor public class AuthUser implements Serializable { @@ -68,6 +70,12 @@ public class AuthUser implements Serializable { */ private Boolean isSuper = false; + /** + * 租户id + */ + private String tenantId; + + public AuthUser(String username, String id, String nickName, String face, UserEnums role) { this.username = username; this.face = face; @@ -85,7 +93,7 @@ public class AuthUser implements Serializable { this.nickName = nickName; } - public AuthUser(String username, String id, UserEnums manager, String nickName, Boolean isSuper, String clerkId,String face) { + public AuthUser(String username, String id, UserEnums manager, String nickName, Boolean isSuper, String clerkId, String face) { this.username = username; this.id = id; this.role = manager; diff --git a/framework/src/main/java/cn/lili/common/security/context/UserContext.java b/framework/src/main/java/cn/lili/common/security/context/UserContext.java index 78d3e5a6..a1c86cae 100644 --- a/framework/src/main/java/cn/lili/common/security/context/UserContext.java +++ b/framework/src/main/java/cn/lili/common/security/context/UserContext.java @@ -7,6 +7,7 @@ import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.enums.SecurityEnum; import cn.lili.common.security.token.SecretKeyUtil; +import cn.lili.common.utils.StringUtils; import com.google.gson.Gson; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; @@ -101,4 +102,21 @@ public class UserContext { return null; } } + + + /** + * 写入邀请人信息 + */ + public static void settingInviter(String memberId, Cache cache) { + if (RequestContextHolder.getRequestAttributes() != null) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + //邀请人id + String inviterId = request.getHeader(SecurityEnum.INVITER.getValue()); + if (StringUtils.isNotEmpty(inviterId)) { + cache.put(CachePrefix.INVITER.getPrefix() + memberId, inviterId); + } + } + } + + } diff --git a/framework/src/main/java/cn/lili/common/security/enums/SecurityEnum.java b/framework/src/main/java/cn/lili/common/security/enums/SecurityEnum.java index c89a3f4b..ad49e685 100644 --- a/framework/src/main/java/cn/lili/common/security/enums/SecurityEnum.java +++ b/framework/src/main/java/cn/lili/common/security/enums/SecurityEnum.java @@ -10,7 +10,7 @@ public enum SecurityEnum { /** * 存在与header中的token参数头 名 */ - HEADER_TOKEN("accessToken"), USER_CONTEXT("userContext"), JWT_SECRET("secret"), UUID("uuid"); + HEADER_TOKEN("accessToken"), USER_CONTEXT("userContext"), JWT_SECRET("secret"), UUID("uuid"), INVITER("inviter"); String value; diff --git a/framework/src/main/java/cn/lili/common/security/enums/UserEnums.java b/framework/src/main/java/cn/lili/common/security/enums/UserEnums.java index 07d86b64..919b6693 100644 --- a/framework/src/main/java/cn/lili/common/security/enums/UserEnums.java +++ b/framework/src/main/java/cn/lili/common/security/enums/UserEnums.java @@ -14,7 +14,8 @@ public enum UserEnums { MEMBER("会员"), STORE("商家"), MANAGER("管理员"), - SYSTEM("系统"); + SYSTEM("系统"), + SEAT("坐席"); private final String role; UserEnums(String role) { diff --git a/framework/src/main/java/cn/lili/common/swagger/Swagger2Config.java b/framework/src/main/java/cn/lili/common/swagger/Swagger2Config.java index e604498b..3b795d22 100644 --- a/framework/src/main/java/cn/lili/common/swagger/Swagger2Config.java +++ b/framework/src/main/java/cn/lili/common/swagger/Swagger2Config.java @@ -81,6 +81,32 @@ public class Swagger2Config { .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); } + @Bean + public Docket orderRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName("订单") + .apiInfo(apiInfo()).select() + //扫描所有有注解的api,用这种方式更灵活 +// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + .apis(RequestHandlerSelectors.basePackage("cn.lili.controller.order")) + .paths(PathSelectors.any()) + .build() + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); + } + + @Bean + public Docket imRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName("im") + .apiInfo(apiInfo()).select() + //扫描所有有注解的api,用这种方式更灵活 + .apis(RequestHandlerSelectors.basePackage("cn.lili.controller.im")) + .paths(PathSelectors.any()) + .build() + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); + } @Bean public Docket memberRestApi() { diff --git a/framework/src/main/java/cn/lili/common/utils/DateUtil.java b/framework/src/main/java/cn/lili/common/utils/DateUtil.java index ec6c5ef4..1e0a10e7 100644 --- a/framework/src/main/java/cn/lili/common/utils/DateUtil.java +++ b/framework/src/main/java/cn/lili/common/utils/DateUtil.java @@ -26,15 +26,16 @@ public class DateUtil { * @return 今天开始时间 */ public static Long getDayOfStart() { - return DateUtil.getDateline()/(60*24*60); + return DateUtil.getDateline() / (60 * 24 * 60); } + /** * 指定日的开始时间 * * @return 指定日时间 */ public static Long getDayOfStart(Date date) { - return date.getTime()/(60*24*60); + return date.getTime() / (60 * 24 * 60); } /** @@ -349,6 +350,22 @@ public class DateUtil { return getDateline(mon, STANDARD_FORMAT); } + /** + * 获取当前天的结束时间 + * + * @return 当前天的开始时间 + */ + public static Date getCurrentDayStartTime() { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) - 1); + return cal.getTime(); + } + /** * 获取当前天的结束时间 * @@ -366,6 +383,21 @@ public class DateUtil { return cal.getTime(); } + /** + * 获取干净的时间 + * + * @return 时间对象 + */ + public static Calendar getCleanCalendar() { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal; + } + /** * 获取延时时间(秒) * diff --git a/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java b/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java index 9929ff20..f5c9fb4f 100644 --- a/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java +++ b/framework/src/main/java/cn/lili/elasticsearch/BaseElasticsearchService.java @@ -325,7 +325,7 @@ public abstract class BaseElasticsearchService { " }\n" + " },\n" + " \"promotionMapJson\": {\n" + - " \"type\": \"text\"\n" + + " \"type\": \"keyword\"\n" + " },\n" + " \"thumbnail\": {\n" + " \"type\": \"text\",\n" + diff --git a/framework/src/main/java/cn/lili/modules/connect/config/AuthConfig.java b/framework/src/main/java/cn/lili/modules/connect/config/AuthConfig.java index 4378893c..b75b1e5a 100644 --- a/framework/src/main/java/cn/lili/modules/connect/config/AuthConfig.java +++ b/framework/src/main/java/cn/lili/modules/connect/config/AuthConfig.java @@ -77,11 +77,7 @@ public class AuthConfig { /** * 针对国外服务可以单独设置代理 * HttpConfig config = new HttpConfig(); -<<<<<<< HEAD - * config.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("106.124.130.167", 10080))); -======= * config.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080))); ->>>>>>> ae0c4aea12996d3d72eca7c6ccdc97922373e4d7 * config.setTimeout(15000); * * @since 1.15.5 diff --git a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java index 942bf897..3b7a9577 100644 --- a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java @@ -246,7 +246,17 @@ public class ConnectServiceImpl extends ServiceImpl impl Member newMember = new Member("m" + phone, "111111", phone, params.getNickName(), params.getImage()); memberService.save(newMember); newMember = memberService.findByUsername(newMember.getUsername()); + + //判定有没有邀请人并且写入 + UserContext.settingInviter(newMember.getId(), cache); + bindMpMember(openId, unionId, newMember); + + + //判定有没有邀请人并且写入 + UserContext.settingInviter(newMember.getId(), cache); + + // 发送会员注册信息 applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), newMember)); return memberTokenGenerate.createToken(newMember, true); diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/vos/DraftGoodsVO.java b/framework/src/main/java/cn/lili/modules/goods/entity/vos/DraftGoodsVO.java index ecb45353..6593342e 100644 --- a/framework/src/main/java/cn/lili/modules/goods/entity/vos/DraftGoodsVO.java +++ b/framework/src/main/java/cn/lili/modules/goods/entity/vos/DraftGoodsVO.java @@ -5,6 +5,7 @@ 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 +15,7 @@ import java.util.List; * @author pikachu * @since 2020-02-26 23:24:13 */ +@EqualsAndHashCode(callSuper = true) @Data public class DraftGoodsVO extends DraftGoods { diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java index c97c2d0d..8410e414 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/CategoryServiceImpl.java @@ -241,12 +241,7 @@ public class CategoryServiceImpl extends ServiceImpl i } } UpdateWrapper updateWrapper = new UpdateWrapper<>(); - updateWrapper.eq("id", category.getId()) - .set("name", category.getName()) - .set("image", category.getImage()) - .set("sort_order", category.getSortOrder()) - .set(DELETE_FLAG_COLUMN, category.getDeleteFlag()) - .set("commission_rate", category.getCommissionRate()); + updateWrapper.eq("id", category.getId()); this.baseMapper.update(category, updateWrapper); removeCache(); } diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java index 84236cda..2cc364b1 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java @@ -327,7 +327,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl i //记录用户足迹 if (UserContext.getCurrentUser() != null) { - FootPrint footPrint = new FootPrint(UserContext.getCurrentUser().getId(), goodsId, skuId); + FootPrint footPrint = new FootPrint(UserContext.getCurrentUser().getId(), goodsIndex.getStoreId(), goodsId, skuId); String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.VIEW_GOODS.name(); rocketMQTemplate.asyncSend(destination, footPrint, RocketmqSendCallbackBuilder.commonCallback()); } @@ -508,6 +508,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl i List goodsSkus = new ArrayList<>(); goodsSkus.add(goodsSku); this.updateGoodsStuck(goodsSkus); + this.promotionGoodsService.updatePromotionGoodsStock(goodsSku.getId(), quantity); } } diff --git a/framework/src/main/java/cn/lili/modules/im/config/CustomSpringConfigurator.java b/framework/src/main/java/cn/lili/modules/im/config/CustomSpringConfigurator.java new file mode 100644 index 00000000..d9f825c0 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/config/CustomSpringConfigurator.java @@ -0,0 +1,34 @@ +package cn.lili.modules.im.config; + + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import javax.websocket.server.ServerEndpointConfig; + +/** + * CustomSpringConfigurator + * + * @author Chopper + * @version v1.0 + * 2021-12-31 11:53 + */ +public class CustomSpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware { + + /** + * Spring application context. + */ + private static volatile BeanFactory context; + + @Override + public T getEndpointInstance(Class clazz) throws InstantiationException { + return context.getBean(clazz); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + CustomSpringConfigurator.context = applicationContext; + } +} diff --git a/framework/src/main/java/cn/lili/modules/im/config/WebSocketConfigurator.java b/framework/src/main/java/cn/lili/modules/im/config/WebSocketConfigurator.java new file mode 100644 index 00000000..c6de471b --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/config/WebSocketConfigurator.java @@ -0,0 +1,24 @@ +package cn.lili.modules.im.config; + + +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * WebSocketConfigurator + * + * @author Chopper + * @version v1.0 + * 2021-12-31 11:53 + */ +@ConditionalOnWebApplication +@Configuration +public class WebSocketConfigurator { + + @Bean + public CustomSpringConfigurator customSpringConfigurator() { + // This is just to get context + return new CustomSpringConfigurator(); + } +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dos/ImMessage.java b/framework/src/main/java/cn/lili/modules/im/entity/dos/ImMessage.java new file mode 100644 index 00000000..f381faca --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dos/ImMessage.java @@ -0,0 +1,69 @@ +package cn.lili.modules.im.entity.dos; + +import cn.lili.common.utils.SnowFlake; +import cn.lili.modules.im.entity.enums.MessageTypeEnum; +import cn.lili.modules.im.entity.vo.MessageOperation; +import cn.lili.mybatis.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + * @author Chopper + */ +@Data +@TableName("li_im_message") +@ApiModel(value = "Im消息") +@NoArgsConstructor +@AllArgsConstructor +public class ImMessage extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 发送者 + */ + private String fromUser; + + /** + * 接收者 + */ + private String toUser; + + /** + * 已阅 + */ + private Boolean isRead; + + /** + * 消息类型 + */ + private MessageTypeEnum messageType; + + /** + * 聊天id + */ + private String talkId; + + /** + * 消息实体 + */ + private String text; + + + public ImMessage(MessageOperation messageOperation){ + this.setFromUser(messageOperation.getFrom()); + this.setMessageType(messageOperation.getMessageType()); + this.setIsRead(false); + this.setText(messageOperation.getContext()); + this.setTalkId(messageOperation.getTalkId()); + this.setCreateTime(new Date()); + this.setToUser(messageOperation.getTo()); + this.setId(SnowFlake.getIdStr()); + } + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dos/ImTalk.java b/framework/src/main/java/cn/lili/modules/im/entity/dos/ImTalk.java new file mode 100644 index 00000000..56ffe258 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dos/ImTalk.java @@ -0,0 +1,102 @@ +package cn.lili.modules.im.entity.dos; + + +import cn.lili.common.utils.SnowFlake; +import cn.lili.mybatis.BaseTenantEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @author Chopper + */ +@Data +@TableName("li_im_talk") +@ApiModel(value = "聊天") +@NoArgsConstructor +@AllArgsConstructor +public class ImTalk extends BaseTenantEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("用户1 id") + private String userId1; + + @ApiModelProperty("用户2 id") + private String userId2; + + @ApiModelProperty("用户1置顶") + private Boolean top1; + + @ApiModelProperty("用户2置顶") + private Boolean top2; + + @ApiModelProperty("用户1 不可见") + private Boolean disable1; + + @ApiModelProperty("用户2 不可见") + private Boolean disable2; + + @ApiModelProperty("用户1名字") + private String name1; + + @ApiModelProperty("用户2名字") + private String name2; + + @ApiModelProperty("用户1头像") + private String face1; + + @ApiModelProperty("用户2头像") + private String face2; + + @ApiModelProperty("用户1的店铺标识") + private Boolean storeFlag1; + + @ApiModelProperty("用户2的店铺标识") + private Boolean storeFlag2; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "最后聊天时间", hidden = true) + private Date lastTalkTime; + + @ApiModelProperty(value = "最后聊天内容") + private String lastTalkMessage; + + @ApiModelProperty(value = "最后发送消息类型") + private String lastMessageType; + + @ApiModelProperty(value = "坐席Id") + private String tenantId; + + @ApiModelProperty(value = "坐席名称") + private String tenantName; + + + public ImTalk(String userId1, String userId2, + String face1, String face2, + String name1, String name2 + ) { + this.userId1 = userId1; + this.userId2 = userId2; + this.top1 = false; + this.top2 = false; + this.disable1 = false; + this.disable2 = false; + this.storeFlag1 = false; + this.storeFlag2 = false; + this.setId(SnowFlake.getIdStr()); + this.lastTalkTime = new Date(); + this.face1 = face1; + this.face2 = face2; + this.name1 = name1; + this.name2 = name2; + } +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dos/QA.java b/framework/src/main/java/cn/lili/modules/im/entity/dos/QA.java new file mode 100644 index 00000000..0d6bd3f2 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dos/QA.java @@ -0,0 +1,31 @@ +package cn.lili.modules.im.entity.dos; + +import cn.lili.mybatis.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 问题答案 + * + * @author Chopper + * @version v1.0 + * 2022-02-09 17:59 + */ +@Data +@TableName("li_qa") +@ApiModel(value = "租户问答") +@NoArgsConstructor +public class QA extends BaseEntity { + + @ApiModelProperty(value = "租户id") + private Integer tenantId; + + @ApiModelProperty(value = "问题") + private String question; + + @ApiModelProperty(value = "答案") + private String answer; +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dos/Seat.java b/framework/src/main/java/cn/lili/modules/im/entity/dos/Seat.java new file mode 100644 index 00000000..40bdfd84 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dos/Seat.java @@ -0,0 +1,47 @@ +package cn.lili.modules.im.entity.dos; + +import cn.lili.mybatis.BaseTenantEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; + +/** + * 坐席 + * + * @author Chopper + * @version v1.0 + * 2022-02-09 17:08 + */ +@Data +@TableName("li_seat") +@ApiModel(value = "坐席") +@NoArgsConstructor +public class Seat extends BaseTenantEntity { + + @ApiModelProperty(value = "租户id") + private String tenantId; + + @ApiModelProperty(value = "坐席用户名") + private String username; + + @ApiModelProperty(value = "会员头像") + private String face; + + @ApiModelProperty(value = "坐席密码") + private String password; + + @ApiModelProperty(value = "昵称") + private String nickName; + + @ApiModelProperty(value = "坐席状态") + private Boolean disabled; + + @NotEmpty(message = "手机号码不能为空") + @ApiModelProperty(value = "手机号码", required = true) + private String mobile; + +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dos/SeatSetting.java b/framework/src/main/java/cn/lili/modules/im/entity/dos/SeatSetting.java new file mode 100644 index 00000000..a462ce7e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dos/SeatSetting.java @@ -0,0 +1,36 @@ +package cn.lili.modules.im.entity.dos; + +import cn.lili.mybatis.BaseTenantEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 坐席设置 + * + * @author Chopper + * @version v1.0 + * 2022-02-09 17:55 + */ +@Data +@TableName("li_seat_setting") +@ApiModel(value = "坐席设置") +@NoArgsConstructor +public class SeatSetting extends BaseTenantEntity { + + @ApiModelProperty(value = "租户idid") + private String tenantId; + + @ApiModelProperty(value = "欢迎语") + private String welcome; + + @ApiModelProperty(value = "离线自动回复") + private String outLineAutoReply; + + @ApiModelProperty(value = "长时间自动回复") + private String longTermAutoReply; + + +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dto/ImQueryParams.java b/framework/src/main/java/cn/lili/modules/im/entity/dto/ImQueryParams.java new file mode 100644 index 00000000..8dc1f0fa --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dto/ImQueryParams.java @@ -0,0 +1,36 @@ +package cn.lili.modules.im.entity.dto; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.common.vo.PageVO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author chc + * @since 2022/6/2114:46 + */ +@Data +@ApiModel +public class ImQueryParams extends PageVO { + + @ApiModelProperty("用户Id") + private String memberId; + + @ApiModelProperty("店铺Id") + private String storeId; + + public QueryWrapper queryWrapper() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (CharSequenceUtil.isNotEmpty(memberId)) { + queryWrapper.eq("member_id", memberId); + } + if (CharSequenceUtil.isNotEmpty(storeId)) { + queryWrapper.eq("store_id", storeId); + } + queryWrapper.eq("delete_flag",false); + queryWrapper.orderByDesc("create_time"); + return queryWrapper; + } +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/dto/MessageQueryParams.java b/framework/src/main/java/cn/lili/modules/im/entity/dto/MessageQueryParams.java new file mode 100644 index 00000000..372522c1 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/dto/MessageQueryParams.java @@ -0,0 +1,50 @@ +package cn.lili.modules.im.entity.dto; + +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.common.utils.StringUtils; +import cn.lili.common.vo.PageVO; +import cn.lili.modules.im.entity.dos.ImMessage; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.Data; + +/** + * MessageQueryParams + * + * @author Chopper + * @version v1.0 + * 2022-01-20 17:16 + */ +@Data +public class MessageQueryParams extends PageVO { + /** + * 聊天窗口 + */ + private String talkId; + /** + * 最后一个消息 + */ + private String lastMessageId; + /** + * 获取消息数量 + */ + private Integer num; + + public LambdaQueryWrapper initQueryWrapper() { + if (StringUtils.isEmpty(talkId)) { + throw new ServiceException(ResultCode.ERROR); + } + if (num == null || num > 50) { + num = 50; + } + + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ImMessage::getTalkId, talkId); + if (StringUtils.isNotEmpty(lastMessageId)) { + lambdaQueryWrapper.lt(ImMessage::getId, lastMessageId); + } + lambdaQueryWrapper.orderByDesc(ImMessage::getCreateTime); +// lambdaQueryWrapper.last("limit " + num); + return lambdaQueryWrapper; + } +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageResultType.java b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageResultType.java new file mode 100644 index 00000000..c557a45e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageResultType.java @@ -0,0 +1,30 @@ +package cn.lili.modules.im.entity.enums; + +/** + * 返回消息类型枚举 + * + * @author liushuai + */ +public enum MessageResultType { + /** + * 返回消息类型枚举 + *

+ * 好友列表 + * 增加好友 + * 消息 + * 阅读消息 + * 未读消息 + * 历史消息 + * 系统提示 + * 下线提醒 + */ + FRIENDS, + ADD_FRIENDS, + MESSAGE, + READ_MESSAGE, + UN_READ, + HISTORY, + SYSTEM_TIPS, + OFFLINE + +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageStatusEnum.java b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageStatusEnum.java new file mode 100644 index 00000000..687c814c --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageStatusEnum.java @@ -0,0 +1,31 @@ +package cn.lili.modules.im.entity.enums; + +/** + * 消息的类型 + * + * @author liushuai(liushuai711 @ gmail.com) + * @version v4.0 + * @Description: + * @since 2022/2/10 16:36 + */ +public enum MessageStatusEnum { + //socket刚打开时发送的消息,这个一般是是刚打开socket链接,进行登录,传入token用 + CONNECT, + //心跳类型的消息,此种类型的消息只有 type 、 text 两种属性 + HEARTBEAT, + //用户打开一个对话框,准备跟某人聊天时 + OPEN, + //客服进行自动回复。客户端发起这种类型请求,则是在拉取对方是否有自动回复,如果有,服务端就会给客户端发送过自动回复的信息 + AUTO_REPLY, + //正常收发消息沟通,文字、表情等沟通 + MSG, + //扩展。比如发送商品、发送订单 + EXTEND, + //系统提示,如提示 对方已离线 + SYSTEM, + //服务端发送到客户端,用于设置客户端的用户信息。会吧 com.xnx3.yunkefu.core.vo.bean.User 传过去 + SET_USER, + //结束服务 + CLOSE_SERVICE; + +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageTypeEnum.java b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageTypeEnum.java new file mode 100644 index 00000000..6b06d3b7 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/enums/MessageTypeEnum.java @@ -0,0 +1,23 @@ +package cn.lili.modules.im.entity.enums; + +/** + * 消息类型 + * + * @author liushuai + */ +public enum MessageTypeEnum { + /** + * 消息类型枚举 + *

+ * 普通消息 + * 图片 + * 语音 + * 视频 + */ + MESSAGE, + PICTURE, + VOICE, + GOODS, + ORDER, + VIDEO +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/enums/OnlineStatusEnum.java b/framework/src/main/java/cn/lili/modules/im/entity/enums/OnlineStatusEnum.java new file mode 100644 index 00000000..837a4493 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/enums/OnlineStatusEnum.java @@ -0,0 +1,14 @@ +package cn.lili.modules.im.entity.enums; + +/** + * 坐席在线状态 + * + * @author Chopper + * @version v1.0 + * 2022-02-10 16:37 + */ +public enum OnlineStatusEnum { + // 在线/下线 + ONLINE, + OUTLINE; +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/enums/OperationType.java b/framework/src/main/java/cn/lili/modules/im/entity/enums/OperationType.java new file mode 100644 index 00000000..5909222e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/enums/OperationType.java @@ -0,0 +1,26 @@ +package cn.lili.modules.im.entity.enums; + +/** + * 操作类型枚举 + * + * @author liushuai + */ +public enum OperationType { + /** + * 消息类型枚举 + *

+ * 心跳检测 + * 发起聊天 + * 发起消息 + * 查询历史消息 + * 阅读消息 + * 查询未读消息 + */ + PING, + CREATE, + MESSAGE, + HISTORY, + READ, + UNREAD, + +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/vo/ImTalkVO.java b/framework/src/main/java/cn/lili/modules/im/entity/vo/ImTalkVO.java new file mode 100644 index 00000000..6d80a8be --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/vo/ImTalkVO.java @@ -0,0 +1,82 @@ +package cn.lili.modules.im.entity.vo; + +import cn.lili.modules.im.entity.dos.ImTalk; +import cn.lili.mybatis.BaseTenantEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @author Chopper + */ +@Data +@ApiModel(value = "聊天") +public class ImTalkVO extends BaseTenantEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + private String id; + + @ApiModelProperty("用户 id") + private String userId; + + @ApiModelProperty("置顶") + private Boolean top; + + @ApiModelProperty("用户 不可见") + private Boolean disable; + + @ApiModelProperty("用户名字") + private String name; + + @ApiModelProperty("用户头像") + private String face; + + @ApiModelProperty("店铺标识") + private Boolean storeFlag; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "最后聊天时间", hidden = true) + private Date lastTalkTime; + + @ApiModelProperty(value = "最后聊天内容") + private String lastTalkMessage; + + @ApiModelProperty(value = "最后发送消息类型") + private String lastMessageType; + + @ApiModelProperty(value = "未读数量") + private Long unread; + + public ImTalkVO() { + + } + + public ImTalkVO(ImTalk imTalk, String currentUser) { + if (imTalk.getUserId2().equals(currentUser)) { + userId = imTalk.getUserId1(); + top = imTalk.getTop1(); + disable = imTalk.getDisable1(); + name = imTalk.getName1(); + face = imTalk.getFace1(); + storeFlag = imTalk.getStoreFlag1(); + } else { + userId = imTalk.getUserId2(); + top = imTalk.getTop2(); + disable = imTalk.getDisable2(); + name = imTalk.getName2(); + face = imTalk.getFace2(); + storeFlag = imTalk.getStoreFlag2(); + } + lastTalkMessage = imTalk.getLastTalkMessage(); + lastTalkTime = imTalk.getLastTalkTime(); + lastMessageType = imTalk.getLastMessageType(); + id = imTalk.getId(); + } +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageOperation.java b/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageOperation.java new file mode 100644 index 00000000..b4360bc6 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageOperation.java @@ -0,0 +1,53 @@ +package cn.lili.modules.im.entity.vo; + +import cn.lili.common.utils.StringUtils; +import cn.lili.modules.im.entity.enums.MessageTypeEnum; +import cn.lili.modules.im.entity.enums.OperationType; +import lombok.Data; + +/** + * @author liushuai + */ +@Data +public class MessageOperation { + + /** + * 消息类型 + */ + private OperationType operationType; + /** + * 与某人聊天记录 + */ + private String to; + + /** + * 发送者 + */ + private String from; + + /** + * 聊天id + */ + private String talkId; + + /** + * 消息类型 + */ + private MessageTypeEnum messageType; + /** + * 消息内容 + */ + private String context; + + public void setOperationType(String operationType) { + if (!StringUtils.isEmpty(operationType)) { + this.operationType = OperationType.valueOf(operationType); + } + } + + public void setMessageType(String messageType) { + if (!StringUtils.isEmpty(messageType)) { + this.messageType = MessageTypeEnum.valueOf(messageType); + } + } +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageVO.java b/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageVO.java new file mode 100644 index 00000000..120abc1a --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/vo/MessageVO.java @@ -0,0 +1,28 @@ +package cn.lili.modules.im.entity.vo; + +import cn.lili.modules.im.entity.enums.MessageResultType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +/** + * MessageVO + * + * @author Chopper + * @version v1.0 + * 2021-12-30 15:51 + */ +@Data +@Builder +@AllArgsConstructor +public class MessageVO { + + /** + * 消息类型 + */ + private MessageResultType messageResultType; + /** + * 消息内容 + */ + private Object result; +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/vo/ReadMessage.java b/framework/src/main/java/cn/lili/modules/im/entity/vo/ReadMessage.java new file mode 100644 index 00000000..bbeb7d11 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/vo/ReadMessage.java @@ -0,0 +1,17 @@ +package cn.lili.modules.im.entity.vo; + +import lombok.Data; + +import java.util.List; + +/** + * ReadMessage + * + * @author Chopper + * @version v1.0 + * 2021-12-31 11:13 + */ +@Data +public class ReadMessage { + private List readMessageList; +} diff --git a/framework/src/main/java/cn/lili/modules/im/entity/vo/SeatVO.java b/framework/src/main/java/cn/lili/modules/im/entity/vo/SeatVO.java new file mode 100644 index 00000000..d1df9d1c --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/entity/vo/SeatVO.java @@ -0,0 +1,22 @@ +package cn.lili.modules.im.entity.vo; + +import cn.lili.modules.im.entity.dos.Seat; +import lombok.Data; + +/** + * 客服VO + * + * @author Chopper + * @version v1.0 + * 2022-02-10 15:02 + */ +@Data +public class SeatVO extends Seat { + + /** + * 在线状态 + */ + private String onlineStatus; + + +} diff --git a/framework/src/main/java/cn/lili/modules/im/mapper/ImMessageMapper.java b/framework/src/main/java/cn/lili/modules/im/mapper/ImMessageMapper.java new file mode 100644 index 00000000..e82b0cac --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/mapper/ImMessageMapper.java @@ -0,0 +1,12 @@ +package cn.lili.modules.im.mapper; + +import cn.lili.modules.im.entity.dos.ImMessage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * Im消息 Dao层 + * @author Chopper + */ +public interface ImMessageMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/mapper/ImTalkMapper.java b/framework/src/main/java/cn/lili/modules/im/mapper/ImTalkMapper.java new file mode 100644 index 00000000..d5f0d2b1 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/mapper/ImTalkMapper.java @@ -0,0 +1,12 @@ +package cn.lili.modules.im.mapper; + +import cn.lili.modules.im.entity.dos.ImTalk; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 聊天 Dao层 + * @author Chopper + */ +public interface ImTalkMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/mapper/QAMapper.java b/framework/src/main/java/cn/lili/modules/im/mapper/QAMapper.java new file mode 100644 index 00000000..f5592316 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/mapper/QAMapper.java @@ -0,0 +1,16 @@ +package cn.lili.modules.im.mapper; + + +import cn.lili.modules.im.entity.dos.QA; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 问答处理层 + * + * @author pikachu + * @since 2020-02-18 15:18:56 + */ +public interface QAMapper extends BaseMapper { + + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/mapper/SeatMapper.java b/framework/src/main/java/cn/lili/modules/im/mapper/SeatMapper.java new file mode 100644 index 00000000..98d7b6ae --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/mapper/SeatMapper.java @@ -0,0 +1,16 @@ +package cn.lili.modules.im.mapper; + + +import cn.lili.modules.im.entity.dos.Seat; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 坐席处理层 + * + * @author pikachu + * @since 2020-02-18 15:18:56 + */ +public interface SeatMapper extends BaseMapper { + + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/mapper/SeatSettingMapper.java b/framework/src/main/java/cn/lili/modules/im/mapper/SeatSettingMapper.java new file mode 100644 index 00000000..9e130ef3 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/mapper/SeatSettingMapper.java @@ -0,0 +1,16 @@ +package cn.lili.modules.im.mapper; + + +import cn.lili.modules.im.entity.dos.SeatSetting; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 坐席设置处理层 + * + * @author pikachu + * @since 2020-02-18 15:18:56 + */ +public interface SeatSettingMapper extends BaseMapper { + + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/service/ImMessageService.java b/framework/src/main/java/cn/lili/modules/im/service/ImMessageService.java new file mode 100644 index 00000000..57fee7cc --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/service/ImMessageService.java @@ -0,0 +1,63 @@ +package cn.lili.modules.im.service; + +import cn.lili.modules.im.entity.dos.ImMessage; +import cn.lili.modules.im.entity.dto.MessageQueryParams; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * Im消息 业务层 + * + * @author Chopper + */ +public interface ImMessageService extends IService { + + /** + * 阅读消息 + * + * @param talkId + * @param accessToken + */ + void read(String talkId, String accessToken); + + /** + * 未读消息列表 + * + * @param accessToken + */ + List unReadMessages(String accessToken); + + /** + * 历史消息 + * + * @param accessToken + * @param to + */ + List historyMessage(String accessToken, String to); + + /** + * 是否有新消息 + * @param accessToken + * @return + */ + Boolean hasNewMessage(String accessToken); + + /** + * 分页获取消息列表 + * @param messageQueryParams 查询条件 + * @return 消息列表 + */ + List getList(MessageQueryParams messageQueryParams); + + /** + * 获取所有未读消息 + * @return + */ + Long unreadMessageCount(); + + /** + * 清空所有未读消息 + */ + void cleanUnreadMessage(); +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/service/ImTalkService.java b/framework/src/main/java/cn/lili/modules/im/service/ImTalkService.java new file mode 100644 index 00000000..427750fd --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/service/ImTalkService.java @@ -0,0 +1,51 @@ +package cn.lili.modules.im.service; + +import cn.lili.modules.im.entity.dos.ImTalk; +import cn.lili.modules.im.entity.vo.ImTalkVO; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * 聊天 业务层 + * + * @author Chopper + */ +public interface ImTalkService extends IService { + + /** + * 获取与某人的聊天框 + * + * @param userId1 + * @param userId2 + * @return + */ + ImTalk getTalkByUser(String userId1, String userId2); + + /** + * 置顶消息 + * + * @param id + * @param top + */ + void top(String id, Boolean top); + + /** + * 禁用(前端不做展示)聊天 + * + * @param id + */ + void disable(String id); + + /** + * 获取用户聊天列表 + * @return + */ + List getUserTalkList(String userName); + + /** + * 获取商家聊天列表 + * @return + */ + List getStoreTalkList(); +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/service/QAService.java b/framework/src/main/java/cn/lili/modules/im/service/QAService.java new file mode 100644 index 00000000..49f8572b --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/service/QAService.java @@ -0,0 +1,25 @@ +package cn.lili.modules.im.service; + + +import cn.lili.common.vo.PageVO; +import cn.lili.modules.im.entity.dos.QA; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * 问答 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +public interface QAService extends IService { + + /** + * 查询店铺问题 + * @param word + * @param pageVO + * @return + */ + IPage getStoreQA(String word, PageVO pageVO); + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/service/SeatService.java b/framework/src/main/java/cn/lili/modules/im/service/SeatService.java new file mode 100644 index 00000000..b0cf8eac --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/service/SeatService.java @@ -0,0 +1,60 @@ +package cn.lili.modules.im.service; + + +import cn.lili.common.security.token.Token; +import cn.lili.modules.im.entity.dos.Seat; +import cn.lili.modules.im.entity.vo.SeatVO; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + * 坐席业务 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +public interface SeatService extends IService { + + + /** + * 获取坐席列表 + * + * @param storeId 店铺id + * @return + */ + List seatVoList(String storeId); + + /** + * 坐席登录 + * + * @param username + * @param password + * @return + */ + Token usernameLogin(String username, String password); + + /** + * 快捷登录code 生成 + * + * @param username 用户名 + * @return + */ + String createQuickLoginCode(String username); + + /** + * 快捷登录 + * + * @param code + * @return + */ + Token quickLogin(String code); + + /** + * 查询坐席 + * + * @param username + * @return + */ + Seat findByUsername(String username); +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/service/SeatSettingService.java b/framework/src/main/java/cn/lili/modules/im/service/SeatSettingService.java new file mode 100644 index 00000000..364ba10f --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/service/SeatSettingService.java @@ -0,0 +1,30 @@ +package cn.lili.modules.im.service; + +import cn.lili.modules.im.entity.dos.SeatSetting; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * 坐席设置业务 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +public interface SeatSettingService extends IService { + + + /** + * 根据店铺id获取坐席配置 + * + * @param storeId + * @return + */ + SeatSetting getSetting(String storeId); + + /** + * 根据店铺修改坐席设置 + * + * @param seatSetting 坐席设置 + * @return + */ + SeatSetting updateByStore(SeatSetting seatSetting); +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImMessageServiceImpl.java b/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImMessageServiceImpl.java new file mode 100644 index 00000000..c216c282 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImMessageServiceImpl.java @@ -0,0 +1,143 @@ +package cn.lili.modules.im.serviceimpl; + +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.common.security.AuthUser; +import cn.lili.common.security.context.UserContext; +import cn.lili.modules.im.entity.dos.ImMessage; +import cn.lili.modules.im.entity.dto.MessageQueryParams; +import cn.lili.modules.im.mapper.ImMessageMapper; +import cn.lili.modules.im.service.ImMessageService; +import cn.lili.modules.im.service.ImTalkService; +import cn.lili.mybatis.util.PageUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * Im消息 业务实现 + * + * @author Chopper + */ +@Service +@Transactional(rollbackFor = Exception.class) +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ImMessageServiceImpl extends ServiceImpl implements ImMessageService { + + @Autowired + private ImTalkService imTalkService; + + @Override + public void read(String talkId, String accessToken) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + String userId = UserContext.getAuthUser(accessToken).getId(); + updateWrapper.eq(ImMessage::getTalkId, talkId); + updateWrapper.eq(ImMessage::getToUser, userId); + updateWrapper.set(ImMessage::getIsRead, true); + this.update(updateWrapper); + } + + @Override + public List unReadMessages(String accessToken) { + String userId = UserContext.getAuthUser(accessToken).getId(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ImMessage::getToUser, userId); + queryWrapper.eq(ImMessage::getIsRead, false); + return this.list(queryWrapper); + } + + @Override + public List historyMessage(String accessToken, String to) { + String userId = UserContext.getAuthUser(accessToken).getId(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.and(i -> i.eq(ImMessage::getToUser, userId).and(j -> j.eq(ImMessage::getFromUser, to))); + queryWrapper.or(i -> i.eq(ImMessage::getToUser, to).and(j -> j.eq(ImMessage::getFromUser, userId))); + queryWrapper.orderByDesc(ImMessage::getCreateTime); + return this.list(queryWrapper); + } + + @Override + public Boolean hasNewMessage(String accessToken) { + String userId = UserContext.getAuthUser(accessToken).getId(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ImMessage::getIsRead, false); + queryWrapper.eq(ImMessage::getToUser, userId); + return this.list(queryWrapper).size() > 0; + + } + + @Override + public List getList(MessageQueryParams messageQueryParams) { + List messageList = this.page(PageUtil.initPage(messageQueryParams), messageQueryParams.initQueryWrapper()).getRecords(); + ListSort(messageList); + readMessage(messageList); + return messageList; + } + + @Override + public Long unreadMessageCount() { + AuthUser currentUser = UserContext.getCurrentUser(); + if(currentUser == null){ + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + return this.count(new LambdaQueryWrapper().eq(ImMessage::getToUser,currentUser.getId()).eq(ImMessage::getIsRead,false)); + } + + @Override + public void cleanUnreadMessage() { + AuthUser currentUser = UserContext.getCurrentUser(); + if(currentUser == null){ + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + this.update(new LambdaUpdateWrapper().eq(ImMessage::getToUser,currentUser.getId()).set(ImMessage::getIsRead,true)); + } + + /** + * 根据时间倒叙 + * + * @param list + */ + private static void ListSort(List list) { + list.sort(new Comparator() { + @Override + public int compare(ImMessage e1, ImMessage e2) { + try { + if (e1.getCreateTime().before(e2.getCreateTime())) { + return -1; + } else { + return 1; + } + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + }); + } + + + /** + * 阅读消息 + * + * @param messageList 消息列表 + */ + private void readMessage(List messageList) { + if (messageList.size() > 0) { + for (ImMessage imMessage : messageList) { + if(Boolean.FALSE.equals(imMessage.getIsRead())){ + imMessage.setIsRead(true); + } + } + } + this.updateBatchById(messageList); + } + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImTalkServiceImpl.java b/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImTalkServiceImpl.java new file mode 100644 index 00000000..2b24c8bb --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/serviceimpl/ImTalkServiceImpl.java @@ -0,0 +1,187 @@ +package cn.lili.modules.im.serviceimpl; + +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.common.security.AuthUser; +import cn.lili.common.security.context.UserContext; +import cn.lili.common.security.enums.UserEnums; +import cn.lili.modules.im.entity.dos.ImMessage; +import cn.lili.modules.im.entity.dos.ImTalk; +import cn.lili.modules.im.entity.vo.ImTalkVO; +import cn.lili.modules.im.mapper.ImTalkMapper; +import cn.lili.modules.im.service.ImMessageService; +import cn.lili.modules.im.service.ImTalkService; +import cn.lili.modules.member.entity.dos.Member; +import cn.lili.modules.member.service.MemberService; +import cn.lili.modules.store.entity.dos.Store; +import cn.lili.modules.store.service.StoreService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.stringtemplate.v4.ST; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 聊天 业务实现 + * + * @author Chopper + */ +@Service +@Transactional(rollbackFor = Exception.class) +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class ImTalkServiceImpl extends ServiceImpl implements ImTalkService { + + @Autowired + private MemberService memberService; + + @Autowired + private StoreService storeService; + + @Autowired + private ImMessageService imMessageService; + + @Override + public ImTalk getTalkByUser(String userId1, String userId2) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ImTalk::getUserId2, userId2); + queryWrapper.eq(ImTalk::getUserId1, userId1); + ImTalk imTalk = this.getOne(queryWrapper); + AuthUser currentUser = UserContext.getCurrentUser(); + //如果没有聊天,则创建聊天 + if (imTalk == null) { + // 没有登录的这个账户信息 + if (currentUser == null) { + return null; + } + //当自己为店铺时 + if(UserEnums.STORE.equals(currentUser.getRole())){ + Store selfStore = storeService.getById(userId1); + //没有这个用户信息 + Member other = memberService.getById(userId2); + if(other == null){ + return null; + } + //自己为店铺其他人必定为用户 + imTalk = new ImTalk(userId1, userId2, selfStore.getStoreLogo(), other.getFace(), selfStore.getStoreName(), other.getNickName()); + imTalk.setStoreFlag1(true); + }else if(UserEnums.MEMBER.equals(currentUser.getRole())){ + //没有这个店铺信息 + Member self = memberService.getById(userId1); + Member otherMember = memberService.getById(userId2); + Store otherStore = storeService.getById(userId2); + if(otherStore != null){ + imTalk = new ImTalk(userId1, userId2, self.getFace(), otherStore.getStoreLogo(), self.getNickName(), otherStore.getStoreName()); + imTalk.setStoreFlag2(true); + }else if (otherMember != null){ + imTalk = new ImTalk(userId1, userId2, self.getFace(), otherMember.getFace(), self.getNickName(), otherMember.getNickName()); + }else{ + return null; + } + } + this.save(imTalk); + } else { + imTalk = check(imTalk); + } + return imTalk; + } + + /** + * 发起聊天后,如果聊天不可见为true,则需要修正 + * + * @param imTalk + */ + private ImTalk check(ImTalk imTalk) { + if (imTalk.getDisable1() || imTalk.getDisable2()) { + imTalk.setDisable1(false); + imTalk.setDisable2(false); + this.updateById(imTalk); + + } + return imTalk; + } + + @Override + public void top(String id, Boolean top) { + ImTalk imTalk = this.getById(id); + if (imTalk.getUserId1().equals(UserContext.getCurrentUser().getId())) { + imTalk.setTop1(top); + } else if (imTalk.getUserId2().equals(UserContext.getCurrentUser().getId())) { + imTalk.setTop2(top); + } else { + throw new ServiceException(ResultCode.ERROR); + } + this.updateById(imTalk); + } + + @Override + public void disable(String id) { + ImTalk imTalk = this.getById(id); + if (imTalk.getUserId1().equals(UserContext.getCurrentUser().getId())) { + imTalk.setDisable1(true); + this.updateById(imTalk); + } else if (imTalk.getUserId2().equals(UserContext.getCurrentUser().getId())) { + imTalk.setDisable2(true); + this.updateById(imTalk); + } + } + + @Override + public List getUserTalkList(String userName) { + AuthUser authUser = UserContext.getCurrentUser(); + if(authUser == null){ + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.and(wq->{ + wq.like(ImTalk::getName1, userName).or().like(ImTalk::getName2,userName); + }); + queryWrapper.and(wq->{ + wq.like(ImTalk::getUserId1, authUser.getId()).or().like(ImTalk::getUserId2,authUser.getId()); + }); + queryWrapper.orderByDesc(ImTalk::getLastTalkTime); + List imTalks = this.list(queryWrapper); + List imTalkVOList = imTalks.stream().map(imTalk -> { + return new ImTalkVO(imTalk, authUser.getId()); + }).collect(Collectors.toList()); + getUnread(imTalkVOList); + return imTalkVOList; + } + + @Override + public List getStoreTalkList() { + AuthUser authUser = UserContext.getCurrentUser(); + if(authUser == null){ + throw new ServiceException(ResultCode.STORE_NOT_LOGIN_ERROR); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.and(wq->{ + wq.like(ImTalk::getUserId1, authUser.getStoreId()).or().like(ImTalk::getUserId2,authUser.getStoreId()); + }); + queryWrapper.orderByDesc(ImTalk::getLastTalkTime); + List imTalks = this.list(queryWrapper); + + List imTalkVOList = imTalks.stream().map(imTalk -> { + return new ImTalkVO(imTalk, authUser.getStoreId()); + }).collect(Collectors.toList()); + getUnread(imTalkVOList); + return imTalkVOList; + } + + /** + * 获取未读消息数量 + * @param imTalkVOList + */ + private void getUnread(List imTalkVOList){ + if(imTalkVOList.size() > 0){ + for (ImTalkVO imTalkVO : imTalkVOList) { + long count = imMessageService.count(new LambdaQueryWrapper().eq(ImMessage::getFromUser, imTalkVO.getUserId()).eq(ImMessage::getIsRead, false)); + imTalkVO.setUnread(count); + } + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/serviceimpl/QAServiceImpl.java b/framework/src/main/java/cn/lili/modules/im/serviceimpl/QAServiceImpl.java new file mode 100644 index 00000000..2ee78fbc --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/serviceimpl/QAServiceImpl.java @@ -0,0 +1,32 @@ +package cn.lili.modules.im.serviceimpl; + +import cn.lili.common.security.context.UserContext; +import cn.lili.common.vo.PageVO; +import cn.lili.modules.im.entity.dos.QA; +import cn.lili.modules.im.mapper.QAMapper; +import cn.lili.modules.im.service.QAService; +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.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 坐席业务层实现 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class QAServiceImpl extends ServiceImpl implements QAService { + + @Override + public IPage getStoreQA(String word, PageVO pageVo) { + LambdaQueryWrapper qaLambdaQueryWrapper = new LambdaQueryWrapper<>(); + qaLambdaQueryWrapper.eq(QA::getTenantId, UserContext.getCurrentUser().getTenantId()); + qaLambdaQueryWrapper.like(QA::getQuestion, word); + return this.page(PageUtil.initPage(pageVo), qaLambdaQueryWrapper); + } +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatServiceImpl.java b/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatServiceImpl.java new file mode 100644 index 00000000..cac28af1 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatServiceImpl.java @@ -0,0 +1,111 @@ +package cn.lili.modules.im.serviceimpl; + +import cn.lili.cache.Cache; +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.common.security.token.Token; +import cn.lili.common.utils.StringUtils; +import cn.lili.modules.im.entity.dos.Seat; +import cn.lili.modules.im.entity.enums.OnlineStatusEnum; +import cn.lili.modules.im.entity.vo.SeatVO; +import cn.lili.modules.im.mapper.SeatMapper; +import cn.lili.modules.im.service.SeatService; +import cn.lili.modules.im.token.SeatTokenGenerate; +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.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * 坐席业务层实现 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class SeatServiceImpl extends ServiceImpl implements SeatService { + + + @Autowired + private SeatTokenGenerate seatTokenGenerate; + + @Autowired + private Cache cache; + + /** + * 快捷登录缓存前缀 + */ + private static String prefix = "{quick_login}_"; + + + @Override + public List seatVoList(String storeId) { + + LambdaQueryWrapper seatLambdaQueryWrapper = new LambdaQueryWrapper<>(); + seatLambdaQueryWrapper.eq(Seat::getTenantId, storeId); + List list = this.list(seatLambdaQueryWrapper); + + //转换模型为VO + List results = list.stream().map(item -> (SeatVO) item).collect(Collectors.toList()); + //填充坐席当前状态 + //todo + results.forEach(item -> { + item.setOnlineStatus(OnlineStatusEnum.ONLINE.name()); + }); + return results; + } + + @Override + public Token usernameLogin(String username, String password) { + + Seat seat = this.findByUsername(username); + //判断用户是否存在 + if (seat == null || !seat.getDisabled()) { + throw new ServiceException(ResultCode.ERROR); + } + //判断密码是否输入正确 + if (!new BCryptPasswordEncoder().matches(password, seat.getPassword())) { + throw new ServiceException(ResultCode.ERROR); + } + return seatTokenGenerate.createToken(seat, true); + } + + @Override + public String createQuickLoginCode(String username) { + String code = UUID.randomUUID().toString(); + cache.put(prefix + code, username, 20L); + return code; + } + + @Override + public Token quickLogin(String code) { + String username = cache.get(prefix + code); + cache.remove(prefix + code); + if (StringUtils.isEmpty(username)) { + throw new ServiceException(ResultCode.ERROR); + } + return seatTokenGenerate.createToken(findByUsername(username), true); + } + + /** + * 查询坐席 + * + * @param username + * @return + */ + @Override + public Seat findByUsername(String username) { + LambdaQueryWrapper seatLambdaQueryWrapper = new LambdaQueryWrapper<>(); + seatLambdaQueryWrapper.eq(Seat::getUsername, username); + return this.getOne(seatLambdaQueryWrapper); + } + + +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatSettingServiceImpl.java b/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatSettingServiceImpl.java new file mode 100644 index 00000000..e5ec4a8e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/serviceimpl/SeatSettingServiceImpl.java @@ -0,0 +1,48 @@ +package cn.lili.modules.im.serviceimpl; + +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.modules.im.entity.dos.SeatSetting; +import cn.lili.modules.im.mapper.SeatSettingMapper; +import cn.lili.modules.im.service.SeatSettingService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 坐席设置业务层实现 + * + * @author pikachu + * @since 2020-02-18 16:18:56 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class SeatSettingServiceImpl extends ServiceImpl implements SeatSettingService { + @Override + public SeatSetting getSetting(String storeId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SeatSetting::getTenantId, storeId); + SeatSetting seatSetting = this.baseMapper.selectOne(queryWrapper); + if (seatSetting == null) { + seatSetting = new SeatSetting(); + seatSetting.setOutLineAutoReply("您好,我现在不在线,请您留下关键内容和联系方式,我看到后会立马回电。"); + seatSetting.setLongTermAutoReply("您好,我正在查阅相关资料,请您稍等。"); + seatSetting.setWelcome("您好,请问有什么可以帮您?"); + seatSetting.setTenantId(storeId); + this.save(seatSetting); + } + return seatSetting; + } + + @Override + public SeatSetting updateByStore(SeatSetting seatSetting) { + SeatSetting oldSetting = this.baseMapper.selectById(seatSetting.getId()); + if (oldSetting.getTenantId().equals(seatSetting.getTenantId())) { + this.updateById(seatSetting); + } else { + throw new ServiceException(ResultCode.ERROR); + } + return seatSetting; + } +} \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/im/token/SeatTokenGenerate.java b/framework/src/main/java/cn/lili/modules/im/token/SeatTokenGenerate.java new file mode 100644 index 00000000..482bcded --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/im/token/SeatTokenGenerate.java @@ -0,0 +1,42 @@ +package cn.lili.modules.im.token; + +import cn.lili.common.security.AuthUser; +import cn.lili.common.security.enums.UserEnums; +import cn.lili.common.security.token.Token; +import cn.lili.common.security.token.TokenUtil; +import cn.lili.common.security.token.base.AbstractTokenGenerate; +import cn.lili.modules.im.entity.dos.Seat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 会员token生成 + * + * @author Chopper + * @version v4.0 + * @since 2020/11/16 10:50 + */ +@Component +public class SeatTokenGenerate extends AbstractTokenGenerate { + @Autowired + private TokenUtil tokenUtil; + + @Override + public Token createToken(Seat seat, Boolean longTerm) { + AuthUser authUser = new AuthUser( + seat.getUsername(), + seat.getId(), + seat.getNickName(), + seat.getFace(), + UserEnums.SEAT); + authUser.setTenantId(seat.getTenantId()); + //登陆成功生成token + return tokenUtil.createToken(seat.getUsername(), authUser, longTerm, UserEnums.SEAT); + } + + @Override + public Token refreshToken(String refreshToken) { + return tokenUtil.refreshToken(refreshToken, UserEnums.SEAT); + } + +} diff --git a/framework/src/main/java/cn/lili/modules/kdBrid/serviceImpl/KdNiaoServiceImpl.java b/framework/src/main/java/cn/lili/modules/kdBrid/serviceImpl/KdNiaoServiceImpl.java index 2e8c1efd..482fcf2d 100644 --- a/framework/src/main/java/cn/lili/modules/kdBrid/serviceImpl/KdNiaoServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/kdBrid/serviceImpl/KdNiaoServiceImpl.java @@ -26,7 +26,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.google.gson.Gson; -import groovy.util.logging.Slf4j; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -88,7 +88,7 @@ public class KdNiaoServiceImpl implements KdNiaoService { @Override - @OrderLogPoint(description = "'订单['+#orderSn+']发货,发货单号['+#logisticsNo+'],已打印电子面单'", orderSn = "#orderSn") + @OrderLogPoint(description = "'订单['+#orderSn+']发货,打印电子面单'", orderSn = "#orderSn") @Transactional(rollbackFor = Exception.class) public String createElectronicsFaceSheet(String orderSn, String logisticsId) throws Exception { //电子面单模板 @@ -194,10 +194,12 @@ public class KdNiaoServiceImpl implements KdNiaoService { params.put("DataType", "2"); // 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数 String result = sendPost(ReqURL, params); - + if(CharSequenceUtil.isEmpty(result) || CharSequenceUtil.isBlank(result)){ + throw new ServiceException(ResultCode.LOGISTICS_CHECK_SETTING); + } //根据公司业务处理返回的信息...... JSONObject obj = JSONObject.parseObject(result); - + log.info("电子面单响应:{}",result); if(!"100".equals(obj.getString("ResultCode"))){ return obj.getString("Reason"); } diff --git a/framework/src/main/java/cn/lili/modules/member/entity/dos/FootPrint.java b/framework/src/main/java/cn/lili/modules/member/entity/dos/FootPrint.java index 7b42ea3f..355df4a3 100644 --- a/framework/src/main/java/cn/lili/modules/member/entity/dos/FootPrint.java +++ b/framework/src/main/java/cn/lili/modules/member/entity/dos/FootPrint.java @@ -6,6 +6,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -15,6 +16,7 @@ import lombok.NoArgsConstructor; * @author Chopper * @since 2020/11/17 7:22 下午 */ +@EqualsAndHashCode(callSuper = true) @Data @TableName("li_foot_print") @ApiModel(value = "浏览历史") @@ -28,6 +30,9 @@ public class FootPrint extends BaseEntity { @ApiModelProperty(value = "会员ID") private String memberId; + @ApiModelProperty(value = "店铺Id") + private String storeId; + @ApiModelProperty(value = "商品ID") private String goodsId; diff --git a/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberEvaluation.java b/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberEvaluation.java index 90be3361..9ec652d2 100644 --- a/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberEvaluation.java +++ b/framework/src/main/java/cn/lili/modules/member/entity/dos/MemberEvaluation.java @@ -1,9 +1,9 @@ package cn.lili.modules.member.entity.dos; +import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.enums.SwitchEnum; import cn.lili.common.security.sensitive.Sensitive; import cn.lili.common.security.sensitive.enums.SensitiveStrategy; -import cn.lili.common.utils.StringUtils; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.member.entity.dto.MemberEvaluationDTO; import cn.lili.modules.order.order.entity.dos.Order; @@ -131,7 +131,7 @@ public class MemberEvaluation extends BaseEntity { //设置订单编号 this.orderNo = order.getSn(); //是否包含图片 - this.haveImage = StringUtils.isNotEmpty(memberEvaluationDTO.getImages()); + this.haveImage = CharSequenceUtil.isNotEmpty(memberEvaluationDTO.getImages()); //默认开启评价 this.status = SwitchEnum.OPEN.name(); } diff --git a/framework/src/main/java/cn/lili/modules/member/entity/dto/FootPrintQueryParams.java b/framework/src/main/java/cn/lili/modules/member/entity/dto/FootPrintQueryParams.java new file mode 100644 index 00000000..d2a5ec50 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/member/entity/dto/FootPrintQueryParams.java @@ -0,0 +1,36 @@ +package cn.lili.modules.member.entity.dto; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.common.vo.PageVO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author chc + * @since 2022/6/2114:46 + */ +@Data +@ApiModel +public class FootPrintQueryParams extends PageVO { + + @ApiModelProperty("用户Id") + private String memberId; + + @ApiModelProperty("店铺Id") + private String storeId; + + public QueryWrapper queryWrapper() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (CharSequenceUtil.isNotEmpty(memberId)) { + queryWrapper.eq("member_id", memberId); + } + if (CharSequenceUtil.isNotEmpty(storeId)) { + queryWrapper.eq("store_id", storeId); + } + queryWrapper.eq("delete_flag",false); + queryWrapper.orderByDesc("create_time"); + return queryWrapper; + } +} diff --git a/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java b/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java index 3005ce96..a3ff318e 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/FootprintService.java @@ -2,6 +2,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.member.entity.dto.FootPrintQueryParams; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; @@ -42,10 +43,10 @@ public interface FootprintService extends IService { /** * 获取会员浏览历史分页 * - * @param pageVO 分页 + * @param params 分页 * @return 会员浏览历史列表 */ - IPage footPrintPage(PageVO pageVO); + IPage footPrintPage(FootPrintQueryParams params); /** * 获取当前会员的浏览记录数量 @@ -53,4 +54,5 @@ public interface FootprintService extends IService { * @return 当前会员的浏览记录数量 */ long getFootprintNum(); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java index 025c16bc..1b1d8be8 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java @@ -252,7 +252,6 @@ public interface MemberService extends IService { void logout(UserEnums userEnums); /** - * <<<<<<< HEAD * 修改会员是否拥有店铺 * * @param haveStore 是否拥有店铺 diff --git a/framework/src/main/java/cn/lili/modules/member/service/StoreLogisticsService.java b/framework/src/main/java/cn/lili/modules/member/service/StoreLogisticsService.java index 1ff93589..f4842ddf 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/StoreLogisticsService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/StoreLogisticsService.java @@ -89,5 +89,4 @@ public interface StoreLogisticsService extends IService { */ List getCloseStoreLogistics(String storeId); - } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/ClerkServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/ClerkServiceImpl.java index 609654f4..730890ac 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/ClerkServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/ClerkServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.context.UserContext; -import cn.lili.common.utils.BeanUtil; import cn.lili.common.utils.StringUtils; import cn.lili.common.vo.PageVO; import cn.lili.modules.member.entity.dos.Clerk; @@ -20,7 +19,6 @@ import cn.lili.modules.member.service.*; import cn.lili.mybatis.util.PageUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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; @@ -60,9 +58,8 @@ public class ClerkServiceImpl extends ServiceImpl implements clerkVOQueryWrapper.eq(StringUtils.isNotEmpty(clerkQueryDTO.getDepartmentId()), "li_clerk.department_id", clerkQueryDTO.getDepartmentId()); clerkVOQueryWrapper.like(StringUtils.isNotEmpty(clerkQueryDTO.getClerkName()), "li_clerk.clerk_name", clerkQueryDTO.getClerkName()); clerkVOQueryWrapper.like(StringUtils.isNotEmpty(clerkQueryDTO.getMobile()), "m.mobile", clerkQueryDTO.getMobile()); - IPage clerkPage = this.baseMapper.selectClerkPage(PageUtil.initPage(page), clerkVOQueryWrapper); - return clerkPage; + return this.baseMapper.selectClerkPage(PageUtil.initPage(page), clerkVOQueryWrapper); /*Page clerkPage = page(initPage, initWrapper); diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java index cfbbc554..f0c92f6c 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java @@ -3,6 +3,7 @@ package cn.lili.modules.member.serviceimpl; import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.PageVO; import cn.lili.modules.member.entity.dos.FootPrint; +import cn.lili.modules.member.entity.dto.FootPrintQueryParams; import cn.lili.modules.member.mapper.FootprintMapper; import cn.lili.modules.member.service.FootprintService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; @@ -43,19 +44,17 @@ public class FootprintServiceImpl extends ServiceImpl oldPrints = list(queryWrapper); if (oldPrints != null && !oldPrints.isEmpty()) { FootPrint oldPrint = oldPrints.get(0); - oldPrint.setSkuId(footPrint.getSkuId()); - this.updateById(oldPrint); - return oldPrint; - } else { - footPrint.setCreateTime(new Date()); - this.save(footPrint); - //删除超过100条后的记录 - this.baseMapper.deleteLastFootPrint(footPrint.getMemberId()); - return footPrint; + this.removeById(oldPrint.getId()); } + footPrint.setCreateTime(new Date()); + this.save(footPrint); + //删除超过100条后的记录 + this.baseMapper.deleteLastFootPrint(footPrint.getMemberId()); + return footPrint; } @Override @@ -74,15 +73,8 @@ public class FootprintServiceImpl extends ServiceImpl footPrintPage(PageVO pageVO) { - - LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); - lambdaQueryWrapper.eq(FootPrint::getMemberId, UserContext.getCurrentUser().getId()); - lambdaQueryWrapper.eq(FootPrint::getDeleteFlag, false); - lambdaQueryWrapper.orderByDesc(FootPrint::getCreateTime); - IPage footPrintPages = this.page(PageUtil.initPage(pageVO), lambdaQueryWrapper); - - + public IPage footPrintPage(FootPrintQueryParams params) { + IPage footPrintPages = this.page(PageUtil.initPage(params), params.queryWrapper()); //定义结果 IPage esGoodsIndexIPage = new Page<>(); @@ -90,7 +82,7 @@ public class FootprintServiceImpl extends ServiceImpl list = esGoodsSearchService.getEsGoodsBySkuIds( - footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()), pageVO); + footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()), params); esGoodsIndexIPage.setPages(footPrintPages.getPages()); esGoodsIndexIPage.setRecords(list); diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java index a21b89ad..4060e39c 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java @@ -40,6 +40,7 @@ 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.mybatis.util.PageUtil; +import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.MemberTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; @@ -47,6 +48,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -94,6 +96,9 @@ public class MemberServiceImpl extends ServiceImpl impleme @Autowired private RocketmqCustomProperties rocketmqCustomProperties; + @Autowired + private RocketMQTemplate rocketMQTemplate; + @Autowired private ApplicationEventPublisher applicationEventPublisher; /** @@ -287,6 +292,8 @@ public class MemberServiceImpl extends ServiceImpl impleme member.setId(SnowFlake.getIdStr()); //保存会员 this.save(member); + + // 发送会员注册信息 applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), member)); } @@ -299,6 +306,9 @@ public class MemberServiceImpl extends ServiceImpl impleme BeanUtil.copyProperties(memberEditDTO, member); //修改会员 this.updateById(member); + String destination = rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_INFO_EDIT.name(); + //发送订单变更mq消息 + rocketMQTemplate.asyncSend(destination, member, RocketmqSendCallbackBuilder.commonCallback()); return member; } diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java index 3dc52820..2134109c 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberSignServiceImpl.java @@ -73,7 +73,7 @@ public class MemberSignServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MemberSign::getMemberId, authUser.getId()); List signSize = this.baseMapper.getTodayMemberSign(queryWrapper); - if (signSize.size() > 0) { + if (signSize.isEmpty()) { throw new ServiceException(ResultCode.MEMBER_SIGN_REPEAT); } //当前签到天数的前一天日期 diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/StoreLogisticsServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/StoreLogisticsServiceImpl.java index 281fbca4..254e178b 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/StoreLogisticsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/StoreLogisticsServiceImpl.java @@ -45,7 +45,7 @@ public class StoreLogisticsServiceImpl extends ServiceImpl lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.eq(StoreLogistics::getLogisticsId, logisticsId); lambdaQueryWrapper.eq(StoreLogistics::getStoreId, storeId); @@ -58,15 +58,15 @@ public class StoreLogisticsServiceImpl extends ServiceImpl().eq(StoreLogistics::getStoreId,storeId).eq(StoreLogistics::getLogisticsId,logisticsId)); + return this.getOne(new LambdaQueryWrapper().eq(StoreLogistics::getStoreId, storeId).eq(StoreLogistics::getLogisticsId, logisticsId)); } @Override public List getOpenStoreLogistics(String storeId) { List openStoreLogistics = this.baseMapper.getOpenStoreLogistics(storeId); - for(StoreLogisticsVO storeLogisticsVO:openStoreLogistics){ + for (StoreLogisticsVO storeLogisticsVO : openStoreLogistics) { storeLogisticsVO.setSelected("1"); } return openStoreLogistics; @@ -78,19 +78,19 @@ public class StoreLogisticsServiceImpl extends ServiceImpl lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.eq(StoreLogistics::getLogisticsId, logisticsId); lambdaQueryWrapper.eq(StoreLogistics::getStoreId, storeId); - StoreLogistics storeLogistics=null; + StoreLogistics storeLogistics = null; if (this.getOne(lambdaQueryWrapper) == null) { - storeLogistics=new StoreLogistics(storeLogisticsCustomerDTO); - storeLogistics.setStoreId(storeId); - storeLogistics.setLogisticsId(logisticsId); - this.save(storeLogistics); - return storeLogistics; - } + storeLogistics = new StoreLogistics(storeLogisticsCustomerDTO); + storeLogistics.setStoreId(storeId); + storeLogistics.setLogisticsId(logisticsId); + this.save(storeLogistics); + return storeLogistics; + } return null; } diff --git a/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java index 22d9b33d..c6724bc4 100644 --- a/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/aftersale/serviceimpl/AfterSaleServiceImpl.java @@ -455,7 +455,10 @@ public class AfterSaleServiceImpl extends ServiceImpl()); this.setCouponList(new ArrayList<>()); this.setGiftList(new ArrayList<>()); diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java index d00b1bec..61ebe0ac 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java @@ -36,10 +36,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; /** @@ -108,29 +105,36 @@ public class CheckDataRender implements CartRenderStep { //缓存中的商品信息 GoodsSku dataSku = goodsSkuService.getGoodsSkuByIdFromCache(cartSkuVO.getGoodsSku().getId()); - Map promotionMap = promotionGoodsService.getCurrentGoodsPromotion(dataSku, tradeDTO.getCartTypeEnum().name()); - //商品有效性判定 - if (dataSku == null || dataSku.getUpdateTime().after(cartSkuVO.getGoodsSku().getUpdateTime())) { - //商品失效,将商品移除并重新填充商品 - cartSkuVOS.remove(cartSkuVO); - //设置新商品 - CartSkuVO newCartSkuVO = new CartSkuVO(dataSku,promotionMap); - newCartSkuVO.setCartType(tradeDTO.getCartTypeEnum()); - newCartSkuVO.setNum(cartSkuVO.getNum()); - newCartSkuVO.setSubTotal(CurrencyUtil.mul(newCartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); - cartSkuVOS.add(newCartSkuVO); - continue; - } + + //商品上架状态判定 - if (!GoodsAuthEnum.PASS.name().equals(dataSku.getAuthFlag()) || !GoodsStatusEnum.UPPER.name().equals(dataSku.getMarketEnable())) { - //设置购物车未选中 - cartSkuVO.setChecked(false); - //设置购物车此sku商品已失效 - cartSkuVO.setInvalid(true); - //设置失效消息 - cartSkuVO.setErrorMessage("商品已下架"); + boolean checkGoodsStatus = dataSku == null || !GoodsAuthEnum.PASS.name().equals(dataSku.getAuthFlag()) || !GoodsStatusEnum.UPPER.name().equals(dataSku.getMarketEnable()); + //商品有效性判定 + boolean checkGoodsValid = dataSku != null && dataSku.getUpdateTime() != null && dataSku.getUpdateTime().after(cartSkuVO.getGoodsSku().getUpdateTime()); + + Map promotionMap = dataSku != null ? promotionGoodsService.getCurrentGoodsPromotion(dataSku, tradeDTO.getCartTypeEnum().name()) : null; + + log.info("dataSku: {}, goodsSku: {}", dataSku, cartSkuVO.getGoodsSku()); + if (checkGoodsStatus || checkGoodsValid) { + if (checkGoodsStatus) { + //设置购物车未选中 + cartSkuVO.setChecked(false); + //设置购物车此sku商品已失效 + cartSkuVO.setInvalid(true); + //设置失效消息 + cartSkuVO.setErrorMessage("商品已下架"); + } + if (checkGoodsValid) { + CartSkuVO newCartSkuVO = new CartSkuVO(dataSku,promotionMap); + newCartSkuVO.setCartType(tradeDTO.getCartTypeEnum()); + newCartSkuVO.setNum(cartSkuVO.getNum()); + newCartSkuVO.setSubTotal(CurrencyUtil.mul(newCartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); + cartSkuVO = newCartSkuVO; + log.info("商品信息已更新,更新后的商品信息为:{}", cartSkuVO); + } continue; } + //商品库存判定 if (dataSku.getQuantity() < cartSkuVO.getNum()) { //设置购物车未选中 @@ -160,35 +164,37 @@ public class CheckDataRender implements CartRenderStep { private void groupStore(TradeDTO tradeDTO) { //渲染的购物车 List cartList = new ArrayList<>(); - - //根据店铺分组 - Map> storeCollect = tradeDTO.getSkuList().stream().collect(Collectors.groupingBy(CartSkuVO::getStoreId)); - for (Map.Entry> storeCart : storeCollect.entrySet()) { - if (!storeCart.getValue().isEmpty()) { - CartVO cartVO = new CartVO(storeCart.getValue().get(0)); - if (CharSequenceUtil.isEmpty(cartVO.getDeliveryMethod())) { - cartVO.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.name()); - } - cartVO.setSkuList(storeCart.getValue()); - try { - //筛选属于当前店铺的优惠券 - storeCart.getValue().forEach(i -> i.getPromotionMap().forEach((key, value) -> { - if (key.contains(PromotionTypeEnum.COUPON.name())) { - JSONObject promotionsObj = JSONUtil.parseObj(value); - Coupon coupon = JSONUtil.toBean(promotionsObj, Coupon.class); - if (key.contains(PromotionTypeEnum.COUPON.name()) && coupon.getStoreId().equals(storeCart.getKey())) { - cartVO.getCanReceiveCoupon().add(new CouponVO(coupon)); + if(tradeDTO.getCartList() == null || tradeDTO.getCartList().size() == 0){ + //根据店铺分组 + Map> storeCollect = tradeDTO.getSkuList().stream().collect(Collectors.groupingBy(CartSkuVO::getStoreId)); + for (Map.Entry> storeCart : storeCollect.entrySet()) { + if (!storeCart.getValue().isEmpty()) { + CartVO cartVO = new CartVO(storeCart.getValue().get(0)); + if (CharSequenceUtil.isEmpty(cartVO.getDeliveryMethod())) { + cartVO.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.name()); + } + cartVO.setSkuList(storeCart.getValue()); + try { + //筛选属于当前店铺的优惠券 + storeCart.getValue().forEach(i -> i.getPromotionMap().forEach((key, value) -> { + if (key.contains(PromotionTypeEnum.COUPON.name())) { + JSONObject promotionsObj = JSONUtil.parseObj(value); + Coupon coupon = JSONUtil.toBean(promotionsObj, Coupon.class); + if (key.contains(PromotionTypeEnum.COUPON.name()) && coupon.getStoreId().equals(storeCart.getKey())) { + cartVO.getCanReceiveCoupon().add(new CouponVO(coupon)); + } } - } - })); - } catch (Exception e) { - log.error("筛选属于当前店铺的优惠券发生异常!", e); + })); + } catch (Exception e) { + log.error("筛选属于当前店铺的优惠券发生异常!", e); + } + storeCart.getValue().stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).findFirst().ifPresent(cartSkuVO -> cartVO.setChecked(true)); + cartList.add(cartVO); } - storeCart.getValue().stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).findFirst().ifPresent(cartSkuVO -> cartVO.setChecked(true)); - cartList.add(cartVO); } + tradeDTO.setCartList(cartList); } - tradeDTO.setCartList(cartList); + } /** diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java index 549dbd04..36d0423a 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java @@ -31,8 +31,6 @@ import java.util.stream.Collectors; @Service public class CouponRender implements CartRenderStep { - @Autowired - private PromotionPriceUtil promotionPriceUtil; @Autowired private MemberCouponService memberCouponService; @@ -267,9 +265,9 @@ public class CouponRender implements CartRenderStep { */ private void renderCouponPrice(Map couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) { //分发优惠券 - promotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), + PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), Boolean.TRUE.equals(coupon.getPlatformFlag()) ? - PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON); + PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON, memberCouponDTO.getMemberCoupon().getCouponId()); //如果是平台券 则需要计算商家承担比例 if (Boolean.TRUE.equals(coupon.getPlatformFlag()) && coupon.getStoreCommission() > 0) { diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java index dc473902..24618c4b 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java @@ -13,6 +13,7 @@ import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.cart.entity.vo.FullDiscountVO; import cn.lili.modules.order.cart.render.CartRenderStep; import cn.lili.modules.order.cart.render.util.PromotionPriceUtil; +import cn.lili.modules.order.order.entity.dto.DiscountPriceItem; import cn.lili.modules.order.order.entity.dto.PriceDetailDTO; import cn.lili.modules.promotion.entity.dos.FullDiscount; import org.springframework.beans.factory.annotation.Autowired; @@ -30,9 +31,6 @@ import java.util.stream.Collectors; @Service public class FullDiscountRender implements CartRenderStep { - @Autowired - private PromotionPriceUtil promotionPriceUtil; - @Autowired private GoodsSkuService goodsSkuService; @@ -84,11 +82,11 @@ public class FullDiscountRender implements CartRenderStep { if (isFull(countPrice, cart)) { //如果减现金 if (Boolean.TRUE.equals(fullDiscount.getFullMinusFlag())) { - promotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT); + PromotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT, fullDiscountVO.getId()); } //打折 else if (Boolean.TRUE.equals(fullDiscount.getFullRateFlag())) { - this.renderFullRate(cart, skuPriceDetail, CurrencyUtil.div(fullDiscount.getFullRate(), 10)); + this.renderFullRate(cart, skuPriceDetail, CurrencyUtil.div(fullDiscount.getFullRate(), 10), fullDiscountVO.getId()); } //渲染满优惠 renderFullMinus(cart); @@ -107,7 +105,7 @@ public class FullDiscountRender implements CartRenderStep { * @param cart * @param skuPriceDetail */ - private void renderFullRate(CartVO cart, Map skuPriceDetail, Double rate) { + private void renderFullRate(CartVO cart, Map skuPriceDetail, Double rate, String activityId) { List cartSkuVOS = cart.getCheckedSkuList().stream().filter(cartSkuVO -> skuPriceDetail.containsKey(cartSkuVO.getGoodsSku().getId())).collect(Collectors.toList()); @@ -115,14 +113,25 @@ public class FullDiscountRender implements CartRenderStep { cartSkuVOS.forEach(cartSkuVO -> { PriceDetailDTO priceDetailDTO = cartSkuVO.getPriceDetailDTO(); + + Double discountPrice = CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), + CurrencyUtil.sub(1, rate) + ); //优惠金额=旧的优惠金额+商品金额*商品折扣比例 priceDetailDTO.setDiscountPrice( - CurrencyUtil.add(priceDetailDTO.getDiscountPrice(), - CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), - CurrencyUtil.sub(1, rate) - ) + CurrencyUtil.add(priceDetailDTO.getDiscountPrice(), discountPrice ) ); + //优惠金额=旧的优惠金额+商品金额*商品折扣比例 + priceDetailDTO.addDiscountPriceItem(DiscountPriceItem + .builder() + .discountPrice(discountPrice) + .promotionTypeEnum(PromotionTypeEnum.FULL_DISCOUNT) + .promotionId(activityId) + .skuId(cartSkuVO.getGoodsSku().getId()) + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + + .build()); }); diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java index 799c62b8..795a0360 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java @@ -3,10 +3,12 @@ package cn.lili.modules.order.cart.render.impl; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.order.cart.entity.dto.TradeDTO; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.cart.entity.enums.RenderStepEnums; import cn.lili.modules.order.cart.entity.vo.CartSkuVO; import cn.lili.modules.order.cart.render.CartRenderStep; import cn.lili.modules.store.entity.dos.FreightTemplateChild; +import cn.lili.modules.store.entity.dos.StoreAddress; import cn.lili.modules.store.entity.dto.FreightTemplateChildDTO; import cn.lili.modules.store.entity.enums.FreightTemplateEnum; import cn.lili.modules.store.entity.vos.FreightTemplateVO; @@ -42,72 +44,81 @@ public class SkuFreightRender implements CartRenderStep { List cartSkuVOS = tradeDTO.getCheckedSkuList(); //会员收货地址问题处理 MemberAddress memberAddress = tradeDTO.getMemberAddress(); + StoreAddress storeAddress = tradeDTO.getStoreAddress(); //如果收货地址为空,则抛出异常 - if (memberAddress == null) { + if (memberAddress == null && storeAddress == null) { return; } - //运费分组信息 - Map> freightGroups = freightTemplateGrouping(cartSkuVOS); + //选择物流的时候计算价格 + if(DeliveryMethodEnum.LOGISTICS.name().equals(tradeDTO.getCartList().get(0).getDeliveryMethod())){ + if (memberAddress != null) { + //运费分组信息 + Map> freightGroups = freightTemplateGrouping(cartSkuVOS); - //循环运费模版 - for (Map.Entry> freightTemplateGroup : freightGroups.entrySet()) { + //循环运费模版 + for (Map.Entry> freightTemplateGroup : freightGroups.entrySet()) { - //商品id列表 - List skuIds = freightTemplateGroup.getValue(); + //商品id列表 + List skuIds = freightTemplateGroup.getValue(); - //当前购物车商品列表 - List currentCartSkus = cartSkuVOS.stream().filter(item -> skuIds.contains(item.getGoodsSku().getId())).collect(Collectors.toList()); + //当前购物车商品列表 + List currentCartSkus = cartSkuVOS.stream().filter(item -> skuIds.contains(item.getGoodsSku().getId())).collect(Collectors.toList()); - //寻找对应对商品运费计算模版 - FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateGroup.getKey()); - if (freightTemplate != null - && freightTemplate.getFreightTemplateChildList() != null - && !freightTemplate.getFreightTemplateChildList().isEmpty()) { - //店铺模版免运费则跳过 - if (freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())) { - break; - } + //寻找对应对商品运费计算模版 + FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateGroup.getKey()); + if (freightTemplate != null + && freightTemplate.getFreightTemplateChildList() != null + && !freightTemplate.getFreightTemplateChildList().isEmpty()) { + //店铺模版免运费则跳过 + if (freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())) { + break; + } - //运费模版 - FreightTemplateChild freightTemplateChild = null; + //运费模版 + FreightTemplateChild freightTemplateChild = null; - //获取市级别id匹配运费模版 - String addressId = memberAddress.getConsigneeAddressIdPath().split(",")[1]; - for (FreightTemplateChild templateChild : freightTemplate.getFreightTemplateChildList()) { - //模版匹配判定 - if (templateChild.getAreaId().contains(addressId)) { - freightTemplateChild = templateChild; - break; + //获取市级别id匹配运费模版 + String addressId = memberAddress.getConsigneeAddressIdPath().split(",")[1]; + for (FreightTemplateChild templateChild : freightTemplate.getFreightTemplateChildList()) { + //模版匹配判定 + if (templateChild.getAreaId().contains(addressId)) { + freightTemplateChild = templateChild; + break; + } + } + //如果没有匹配到物流规则,则说明不支持配送 + if (freightTemplateChild == null) { + if (tradeDTO.getNotSupportFreight() == null) { + tradeDTO.setNotSupportFreight(new ArrayList<>()); + } + tradeDTO.getNotSupportFreight().addAll(currentCartSkus); + continue; + } + + //物流规则模型创立 + FreightTemplateChildDTO freightTemplateChildDTO = new FreightTemplateChildDTO(freightTemplateChild); + //模型写入运费模版设置的计费方式 + freightTemplateChildDTO.setPricingMethod(freightTemplate.getPricingMethod()); + + //计算运费总数 + Double count = currentCartSkus.stream().mapToDouble(item -> + // 根据计费规则 累加计费基数 + freightTemplateChildDTO.getPricingMethod().equals(FreightTemplateEnum.NUM.name()) ? + item.getNum().doubleValue() : + CurrencyUtil.mul(item.getNum(), item.getGoodsSku().getWeight()) + ).sum(); + + //计算运费 + Double countFreight = countFreight(count, freightTemplateChildDTO); + + //写入SKU运费 + resetFreightPrice(FreightTemplateEnum.valueOf(freightTemplateChildDTO.getPricingMethod()), count, countFreight, currentCartSkus); } } - //如果没有匹配到物流规则,则说明不支持配送 - if (freightTemplateChild == null) { - if (tradeDTO.getNotSupportFreight() == null) { - tradeDTO.setNotSupportFreight(new ArrayList<>()); - } - tradeDTO.getNotSupportFreight().addAll(currentCartSkus); - continue; - } - - //物流规则模型创立 - FreightTemplateChildDTO freightTemplateChildDTO = new FreightTemplateChildDTO(freightTemplateChild); - //模型写入运费模版设置的计费方式 - freightTemplateChildDTO.setPricingMethod(freightTemplate.getPricingMethod()); - - //计算运费总数 - Double count = currentCartSkus.stream().mapToDouble(item -> - // 根据计费规则 累加计费基数 - freightTemplateChildDTO.getPricingMethod().equals(FreightTemplateEnum.NUM.name()) ? - item.getNum().doubleValue() : - CurrencyUtil.mul(item.getNum(), item.getGoodsSku().getWeight()) - ).sum(); - - //计算运费 - Double countFreight = countFreight(count, freightTemplateChildDTO); - - //写入SKU运费 - resetFreightPrice(FreightTemplateEnum.valueOf(freightTemplateChildDTO.getPricingMethod()), count, countFreight, currentCartSkus); } + }else{ + //自提清空不配送商品 + tradeDTO.setNotSupportFreight(null); } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java index 280082ed..b3cb010f 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java @@ -15,6 +15,7 @@ import cn.lili.modules.order.cart.entity.enums.RenderStepEnums; import cn.lili.modules.order.cart.entity.vo.CartSkuVO; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.cart.render.CartRenderStep; +import cn.lili.modules.order.order.entity.dto.DiscountPriceItem; import cn.lili.modules.order.order.entity.dto.PriceDetailDTO; import cn.lili.modules.promotion.entity.dto.search.KanjiaActivitySearchParams; import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum; @@ -117,6 +118,17 @@ public class SkuPromotionRender implements CartRenderStep { PromotionSkuVO promotionSkuVO = new PromotionSkuVO(PromotionTypeEnum.POINTS_GOODS.name(), cartSkuVO.getPointsId()); cartSkuVO.getPriceDetailDTO().getJoinPromotion().add(promotionSkuVO); totalPayPoints += cartSkuVO.getPoint(); + + //记录优惠由来 + cartSkuVO.getPriceDetailDTO().setDiscountPriceItem( + DiscountPriceItem.builder() + .discountPrice(CurrencyUtil.sub(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getPurchasePrice())) + .promotionId(promotionSkuVO.getActivityId()) + .promotionTypeEnum(PromotionTypeEnum.POINTS_GOODS) + .skuId(cartSkuVO.getGoodsSku().getId()) + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .build() + ); } } if (userInfo.getPoint() < totalPayPoints) { @@ -138,9 +150,19 @@ public class SkuPromotionRender implements CartRenderStep { cartSkuVO.setSubTotal(kanjiaActivityVO.getPurchasePrice()); cartSkuVO.getPriceDetailDTO().setGoodsPrice(kanjiaActivityVO.getPurchasePrice()); } - PromotionSkuVO promotionSkuVO = new PromotionSkuVO(PromotionTypeEnum.KANJIA.name(), cartSkuVO.getKanjiaId()); cartSkuVO.getPriceDetailDTO().getJoinPromotion().add(promotionSkuVO); + + //记录优惠由来 + cartSkuVO.getPriceDetailDTO().setDiscountPriceItem( + DiscountPriceItem.builder() + .discountPrice(CurrencyUtil.sub(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getPurchasePrice())) + .promotionId(promotionSkuVO.getActivityId()) + .promotionTypeEnum(PromotionTypeEnum.KANJIA) + .skuId(cartSkuVO.getGoodsSku().getId()) + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .build() + ); } } return; @@ -149,6 +171,17 @@ public class SkuPromotionRender implements CartRenderStep { for (CartSkuVO cartSkuVO : cartVO.getCheckedSkuList()) { PromotionSkuVO promotionSkuVO = new PromotionSkuVO(PromotionTypeEnum.PINTUAN.name(), cartSkuVO.getPintuanId()); cartSkuVO.getPriceDetailDTO().getJoinPromotion().add(promotionSkuVO); + + //记录优惠由来 + cartSkuVO.getPriceDetailDTO().setDiscountPriceItem( + DiscountPriceItem.builder() + .discountPrice(CurrencyUtil.sub(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getPurchasePrice())) + .promotionId(promotionSkuVO.getActivityId()) + .promotionTypeEnum(PromotionTypeEnum.PINTUAN) + .skuId(cartSkuVO.getGoodsSku().getId()) + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .build() + ); } } return; @@ -171,6 +204,21 @@ public class SkuPromotionRender implements CartRenderStep { cartSkuVO.getPriceDetailDTO().setGoodsPrice(cartSkuVO.getSubTotal()); cartSkuVO.getPriceDetailDTO().getJoinPromotion().add(promotionSkuVO); + + //如果是秒杀活动 + if (promotionSkuVO.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())) { + //需记录秒杀活动详情 + cartSkuVO.getPriceDetailDTO().setDiscountPriceItem( + DiscountPriceItem.builder() + .discountPrice(CurrencyUtil.sub(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getPurchasePrice())) + .promotionId(promotionSkuVO.getActivityId()) + .promotionTypeEnum(PromotionTypeEnum.SECKILL) + .skuId(cartSkuVO.getGoodsSku().getId()) + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .build()); + } + + } } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java index b6f1a731..dc1c2348 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java @@ -4,8 +4,8 @@ import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.vo.CartSkuVO; +import cn.lili.modules.order.order.entity.dto.DiscountPriceItem; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; import java.util.Date; import java.util.List; @@ -17,7 +17,6 @@ import java.util.Map; * @author paulG * @since 2020/8/21 **/ -@Service @Slf4j public class PromotionPriceUtil { @@ -29,7 +28,7 @@ public class PromotionPriceUtil { * @param discountPrice 需要分发的优惠金额 * @param promotionTypeEnum 促销类型 */ - public void recountPrice(TradeDTO tradeDTO, Map skuPromotionDetail, Double discountPrice, PromotionTypeEnum promotionTypeEnum) { + public static void recountPrice(TradeDTO tradeDTO, Map skuPromotionDetail, Double discountPrice, PromotionTypeEnum promotionTypeEnum, String activityId) { // sku 促销信息非空判定 if (skuPromotionDetail == null || skuPromotionDetail.size() == 0) { @@ -102,6 +101,17 @@ public class PromotionPriceUtil { cartSkuVO.getPriceDetailDTO().setCouponPrice( CurrencyUtil.add(cartSkuVO.getPriceDetailDTO().getCouponPrice(), skuDiscountPrice)); + + cartSkuVO.getPriceDetailDTO().addDiscountPriceItem( + DiscountPriceItem.builder() + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .skuId(cartSkuVO.getGoodsSku().getId()) + .discountPrice(skuDiscountPrice) + .promotionTypeEnum(PromotionTypeEnum.COUPON) + .promotionId(activityId) + .build() + ); + } else if (promotionTypeEnum == PromotionTypeEnum.PLATFORM_COUPON) { cartSkuVO.getPriceDetailDTO().setSiteCouponPrice( @@ -109,9 +119,32 @@ public class PromotionPriceUtil { cartSkuVO.getPriceDetailDTO().setCouponPrice( CurrencyUtil.add(cartSkuVO.getPriceDetailDTO().getCouponPrice(), cartSkuVO.getPriceDetailDTO().getSiteCouponPrice())); + + + cartSkuVO.getPriceDetailDTO().addDiscountPriceItem( + DiscountPriceItem.builder() + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .skuId(cartSkuVO.getGoodsSku().getId()) + .discountPrice(skuDiscountPrice) + .promotionTypeEnum(PromotionTypeEnum.PLATFORM_COUPON) + .promotionId(activityId) + .build() + ); + } else { cartSkuVO.getPriceDetailDTO().setDiscountPrice( CurrencyUtil.add(cartSkuVO.getPriceDetailDTO().getDiscountPrice(), skuDiscountPrice)); + + //目前剩余的只有满减金额活动。后续如果需要调整,这里建议传递活动类型进来 + cartSkuVO.getPriceDetailDTO().addDiscountPriceItem( + DiscountPriceItem.builder() + .goodsId(cartSkuVO.getGoodsSku().getGoodsId()) + .skuId(cartSkuVO.getGoodsSku().getId()) + .discountPrice(skuDiscountPrice) + .promotionTypeEnum(PromotionTypeEnum.FULL_DISCOUNT) + .promotionId(activityId) + .build() + ); } } } @@ -130,7 +163,7 @@ public class PromotionPriceUtil { * @param promotionId 活动ID * @return 是否有效 */ - private boolean checkPromotionValidTime(Date startTime, Date endTime, String promotionType, String promotionId) { + private static boolean checkPromotionValidTime(Date startTime, Date endTime, String promotionType, String promotionId) { long now = System.currentTimeMillis(); if (startTime.getTime() > now) { log.error("商品ID为{}的{}活动开始时间小于当时时间,活动未开始!", promotionId, promotionType); diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java index d11d8aa8..2d525af4 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java @@ -7,6 +7,8 @@ import cn.lili.modules.order.cart.entity.vo.TradeParams; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.vo.ReceiptVO; +import java.util.List; + /** * 购物车业务层 * @@ -111,6 +113,14 @@ public interface CartService { */ void shippingAddress(String shippingAddressId, String way); + /** + * 选择自提地址 + * + * @param shopAddressId 收货地址id + * @param way 购物车类型 + */ + void shippingSelfAddress(String shopAddressId, String way); + /** * 选择发票 * @@ -123,11 +133,10 @@ public interface CartService { /** * 选择配送方式 * - * @param storeId 店铺id * @param deliveryMethod 配送方式 * @param way 购物车类型 */ - void shippingMethod(String storeId, String deliveryMethod, String way); + void shippingMethod(String deliveryMethod, String way); /** * 获取购物车商品数量 @@ -160,4 +169,11 @@ public interface CartService { * @return 交易信息 */ Trade createTrade(TradeParams tradeParams); + + /*** + * 获取可使用的配送方式 + * @param way + * @return + */ + List shippingMethodList(String way); } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java index 485bb249..82c1805c 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java @@ -46,6 +46,10 @@ import cn.lili.modules.promotion.service.PointsGoodsService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import cn.lili.modules.search.service.EsGoodsSearchService; +import cn.lili.modules.store.entity.dos.Store; +import cn.lili.modules.store.entity.dos.StoreAddress; +import cn.lili.modules.store.service.StoreAddressService; +import cn.lili.modules.store.service.StoreService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -116,6 +120,12 @@ public class CartServiceImpl implements CartService { @Autowired private WholesaleService wholesaleService; + @Autowired + private StoreService storeService; + + @Autowired + private StoreAddressService storeAddressService; + @Override public void add(String skuId, Integer num, String cartType, Boolean cover) { AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); @@ -438,6 +448,20 @@ public class CartServiceImpl implements CartService { this.resetTradeDTO(tradeDTO); } + @Override + public void shippingSelfAddress(String shopAddressId, String way) { + //默认购物车 + CartTypeEnum cartTypeEnum = CartTypeEnum.CART; + if (CharSequenceUtil.isNotEmpty(way)) { + cartTypeEnum = CartTypeEnum.valueOf(way); + } + + TradeDTO tradeDTO = this.readDTO(cartTypeEnum); + StoreAddress storeAddress = storeAddressService.getById(shopAddressId); + tradeDTO.setStoreAddress(storeAddress); + this.resetTradeDTO(tradeDTO); + } + /** * 选择发票 * @@ -459,21 +483,18 @@ public class CartServiceImpl implements CartService { /** * 选择配送方式 * - * @param storeId 店铺id * @param deliveryMethod 配送方式 * @param way 购物车类型 */ @Override - public void shippingMethod(String storeId, String deliveryMethod, String way) { + public void shippingMethod(String deliveryMethod, String way) { CartTypeEnum cartTypeEnum = CartTypeEnum.CART; if (CharSequenceUtil.isNotEmpty(way)) { cartTypeEnum = CartTypeEnum.valueOf(way); } TradeDTO tradeDTO = this.readDTO(cartTypeEnum); - for (CartVO cartVO : tradeDTO.getCartList()) { - if (cartVO.getStoreId().equals(storeId)) { - cartVO.setDeliveryMethod(DeliveryMethodEnum.valueOf(deliveryMethod).name()); - } + for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { + cartSkuVO.setDeliveryMethod(DeliveryMethodEnum.valueOf(deliveryMethod).name()); } this.resetTradeDTO(tradeDTO); } @@ -547,8 +568,10 @@ public class CartServiceImpl implements CartService { tradeDTO.setStoreRemark(tradeParams.getRemark()); tradeDTO.setParentOrderSn(tradeParams.getParentOrderSn()); //订单无收货地址校验 - if (tradeDTO.getMemberAddress() == null) { - throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); + if(tradeDTO.getStoreAddress() == null){ + if (tradeDTO.getMemberAddress() == null) { + throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); + } } //构建交易 Trade trade = tradeBuilder.createTrade(tradeDTO); @@ -556,6 +579,22 @@ public class CartServiceImpl implements CartService { return trade; } + @Override + public List shippingMethodList(String way) { + List list = new ArrayList(); + list.add(DeliveryMethodEnum.LOGISTICS.name()); + TradeDTO tradeDTO = this.getCheckedTradeDTO(CartTypeEnum.valueOf(way)); + if(tradeDTO.getCartList().size()==1){ + for (CartVO cartVO : tradeDTO.getCartList()) { + Store store = storeService.getById(cartVO.getStoreId()); + if(store.getSelfPickFlag() != null && store.getSelfPickFlag()){ + list.add(DeliveryMethodEnum.SELF_PICK_UP.name()); + } + } + } + return list; + } + /** * 获取购物车类型 diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java index f185d17d..a937e125 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java @@ -210,6 +210,15 @@ public class Order extends BaseEntity { @ApiModelProperty(value = "qrCode 实物为提货码 虚拟货物为账号") private String qrCode; + @ApiModelProperty(value = "自提点地址") + private String storeAddressPath; + + @ApiModelProperty(value = "自提点电话") + private String storeAddressMobile; + + @ApiModelProperty(value = "自提点地址经纬度") + private String storeAddressCenter; + /** * 构建订单 * @@ -233,11 +242,19 @@ public class Order extends BaseEntity { this.setRemark(cartVO.getRemark()); this.setFreightPrice(tradeDTO.getPriceDetailDTO().getFreightPrice()); //会员收件信息 - this.setConsigneeAddressIdPath(tradeDTO.getMemberAddress().getConsigneeAddressIdPath()); - this.setConsigneeAddressPath(tradeDTO.getMemberAddress().getConsigneeAddressPath()); - this.setConsigneeDetail(tradeDTO.getMemberAddress().getDetail()); - this.setConsigneeMobile(tradeDTO.getMemberAddress().getMobile()); - this.setConsigneeName(tradeDTO.getMemberAddress().getName()); + if(DeliveryMethodEnum.LOGISTICS.name().equals(cartVO.getDeliveryMethod())){ + this.setConsigneeAddressIdPath(tradeDTO.getMemberAddress().getConsigneeAddressIdPath()); + this.setConsigneeAddressPath(tradeDTO.getMemberAddress().getConsigneeAddressPath()); + this.setConsigneeDetail(tradeDTO.getMemberAddress().getDetail()); + this.setConsigneeMobile(tradeDTO.getMemberAddress().getMobile()); + this.setConsigneeName(tradeDTO.getMemberAddress().getName()); + } + //自提点信息 + if(DeliveryMethodEnum.SELF_PICK_UP.name().equals(cartVO.getDeliveryMethod())){ + this.setStoreAddressPath(tradeDTO.getStoreAddress().getAddress()); + this.setStoreAddressMobile(tradeDTO.getStoreAddress().getMobile()); + this.setStoreAddressCenter(tradeDTO.getStoreAddress().getCenter()); + } //平台优惠券判定 if (tradeDTO.getPlatformCoupon() != null) { this.setUsePlatformMemberCouponId(tradeDTO.getPlatformCoupon().getMemberCoupon().getId()); diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/DiscountPriceItem.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/DiscountPriceItem.java new file mode 100644 index 00000000..5391e00f --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/DiscountPriceItem.java @@ -0,0 +1,44 @@ +package cn.lili.modules.order.order.entity.dto; + +import cn.lili.common.enums.PromotionTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 优惠信息详情 + * + * @author liushuai(liushuai711 @ gmail.com) + * @version v4.0 + * @Description: + * @since 2022/12/23 14:52 + */ +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DiscountPriceItem { + + + @ApiModelProperty(value = "促销类型") + private PromotionTypeEnum promotionTypeEnum; + + @ApiModelProperty(value = "促销id") + private String promotionId; + + @ApiModelProperty(value = "减免金额") + private Double discountPrice; + + @ApiModelProperty(value = "涉及 商品ID") + private String goodsId; + + @ApiModelProperty(value = "涉及 SKU ID") + private String skuId; + + + public String getPromotionName() { + return promotionTypeEnum.description(); + } +} diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java index edf3cfc9..76f6dad6 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/PriceDetailDTO.java @@ -42,6 +42,9 @@ public class PriceDetailDTO implements Serializable { @ApiModelProperty(value = "优惠金额") private Double discountPrice; + @ApiModelProperty(value = "优惠详情") + private List discountPriceDetail; + @ApiModelProperty(value = "优惠券金额") private Double couponPrice; @@ -101,6 +104,27 @@ public class PriceDetailDTO implements Serializable { private List joinPromotion; + /** + * 设置促销详情 + * + * @param discountPriceItem 促销信息 + */ + public void setDiscountPriceItem(DiscountPriceItem discountPriceItem) { + List discountPriceItems = new ArrayList<>(); + discountPriceItems.add(discountPriceItem); + this.discountPriceDetail = discountPriceItems; + } + + /** + * 设置促销详情 + * + * @param discountPriceItem 促销信息 + */ + public void addDiscountPriceItem(DiscountPriceItem discountPriceItem) { + discountPriceDetail.add(discountPriceItem); + } + + public Double getOriginalPrice() { if (originalPrice == 0D) { return flowPrice; @@ -134,6 +158,7 @@ public class PriceDetailDTO implements Serializable { billPrice = 0d; settlementPrice = 0d; + discountPriceDetail = new ArrayList<>(); joinPromotion = new ArrayList<>(); } @@ -204,6 +229,8 @@ public class PriceDetailDTO implements Serializable { billPrice = CurrencyUtil.add(billPrice, priceDetailDTO.getBillPrice()); settlementPrice = CurrencyUtil.add(settlementPrice, priceDetailDTO.getSettlementPrice()); + discountPriceDetail.addAll(priceDetailDTO.getDiscountPriceDetail()); + } /** diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/OrderStatusEnum.java b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/OrderStatusEnum.java index 6d9f4906..8edcaccf 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/OrderStatusEnum.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/OrderStatusEnum.java @@ -16,6 +16,7 @@ public enum OrderStatusEnum { UNDELIVERED("待发货"), DELIVERED("已发货"), COMPLETED("已完成"), + STAY_PICKED_UP("待自提"), /** * 虚拟订单需要核验商品 */ diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/AllowOperation.java b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/AllowOperation.java index 6ef7ca59..0db1700c 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/AllowOperation.java +++ b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/AllowOperation.java @@ -1,6 +1,7 @@ package cn.lili.modules.order.order.entity.vo; import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.enums.DeliverStatusEnum; import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; @@ -63,16 +64,17 @@ public class AllowOperation implements Serializable { } //新订单 - if (CharSequenceUtil.equalsAny(status, OrderStatusEnum.UNPAID.name(), OrderStatusEnum.PAID.name(), OrderStatusEnum.UNDELIVERED.name())) { + if (CharSequenceUtil.equalsAny(status, OrderStatusEnum.UNPAID.name(), OrderStatusEnum.PAID.name(), OrderStatusEnum.UNDELIVERED.name(), OrderStatusEnum.STAY_PICKED_UP.name())) { this.cancel = true; } //新订单,允许支付 this.pay = status.equals(OrderStatusEnum.UNPAID.name()) && payStatus.equals(PayStatusEnum.UNPAID.name()); - //可编辑订单收件人信息=实物订单 && 订单未发货 && 订单未取消 + //可编辑订单收件人信息=实物订单 && 订单未发货 && 订单未取消 && 订单不是自提 this.editConsignee = order.getOrderType().equals(OrderTypeEnum.NORMAL.name()) && order.getDeliverStatus().equals(DeliverStatusEnum.UNDELIVERED.name()) - && !status.equals(OrderStatusEnum.CANCELLED.name()); + && !status.equals(OrderStatusEnum.CANCELLED.name()) + && !order.getDeliveryMethod().equals(DeliveryMethodEnum.SELF_PICK_UP.name()); //是否允许被发货 this.ship = editConsignee && status.equals(OrderStatusEnum.UNDELIVERED.name()); @@ -83,7 +85,8 @@ public class AllowOperation implements Serializable { //是否允许查看物流信息 this.showLogistics = order.getDeliverStatus().equals(DeliverStatusEnum.DELIVERED.name()) && status.equals(OrderStatusEnum.DELIVERED.name()); - this.take = order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name()) && order.getOrderStatus().equals(OrderStatusEnum.TAKE.name()); + //虚拟订单 或 自提订单可以核销 + this.take = (order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name()) && order.getOrderStatus().equals(OrderStatusEnum.TAKE.name())) || (order.getDeliveryMethod().equals(DeliveryMethodEnum.SELF_PICK_UP.name()) && order.getOrderStatus().equals(OrderStatusEnum.STAY_PICKED_UP.name())); } /** diff --git a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java index 3740bb08..507d797f 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java +++ b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java @@ -183,6 +183,15 @@ public interface OrderService extends IService { */ Order take(String orderSn, String verificationCode); + + /** + * 订单核验 + * + * @param verificationCode 验证码 + * @return 订单 + */ + Order take(String verificationCode); + /** * 根据核验码获取订单信息 * diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java index 0601148a..783efbc9 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java @@ -16,10 +16,12 @@ import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.OperationalJudgment; import cn.lili.common.security.context.UserContext; import cn.lili.common.security.enums.UserEnums; +import cn.lili.common.utils.ObjectUtil; import cn.lili.common.utils.SnowFlake; import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage; import cn.lili.modules.member.entity.dto.MemberAddressDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.order.aop.OrderLogPoint; import cn.lili.modules.order.order.entity.dos.*; import cn.lili.modules.order.order.entity.dto.OrderBatchDeliverDTO; @@ -295,12 +297,13 @@ public class OrderServiceImpl extends ServiceImpl implements Order order = OperationalJudgment.judgment(this.getBySn(orderSn)); //如果订单促销类型不为空&&订单是拼团订单,并且订单未成团,则抛出异常 if (OrderPromotionTypeEnum.PINTUAN.name().equals(order.getOrderPromotionType()) - && !order.getOrderStatus().equals(OrderStatusEnum.UNDELIVERED.name())) { + && !CharSequenceUtil.equalsAny(order.getOrderStatus(),OrderStatusEnum.UNDELIVERED.name(),OrderStatusEnum.STAY_PICKED_UP.name())) { throw new ServiceException(ResultCode.ORDER_CAN_NOT_CANCEL); } if (CharSequenceUtil.equalsAny(order.getOrderStatus(), OrderStatusEnum.UNDELIVERED.name(), OrderStatusEnum.UNPAID.name(), + OrderStatusEnum.STAY_PICKED_UP.name(), OrderStatusEnum.PAID.name())) { order.setOrderStatus(OrderStatusEnum.CANCELLED.name()); @@ -477,11 +480,24 @@ public class OrderServiceImpl extends ServiceImpl implements return order; } + @Override + public Order take(String verificationCode) { + String storeId = OperationalJudgment.judgment(UserContext.getCurrentUser()).getStoreId(); + Order order = this.getOne(new LambdaQueryWrapper().eq(Order::getVerificationCode, verificationCode).eq(Order::getStoreId, storeId)); + if(order == null){ + throw new ServiceException(ResultCode.ORDER_NOT_EXIST); + } + order.setOrderStatus(OrderStatusEnum.COMPLETED.name()); + //订单完成 + this.complete(order.getSn()); + return order; + } + @Override public Order getOrderByVerificationCode(String verificationCode) { String storeId = Objects.requireNonNull(UserContext.getCurrentUser()).getStoreId(); return this.getOne(new LambdaQueryWrapper() - .eq(Order::getOrderStatus, OrderStatusEnum.TAKE.name()) + .in(Order::getOrderStatus, OrderStatusEnum.TAKE.name(),OrderStatusEnum.STAY_PICKED_UP.name()) .eq(Order::getStoreId, storeId) .eq(Order::getVerificationCode, verificationCode)); } @@ -943,13 +959,20 @@ public class OrderServiceImpl extends ServiceImpl implements */ @Transactional(rollbackFor = Exception.class) public void normalOrderConfirm(String orderSn) { + OrderStatusEnum orderStatusEnum = null; + Order order = this.getBySn(orderSn); + if(DeliveryMethodEnum.SELF_PICK_UP.name().equals(order.getDeliveryMethod())){ + orderStatusEnum = OrderStatusEnum.STAY_PICKED_UP; + }else if (DeliveryMethodEnum.LOGISTICS.name().equals(order.getDeliveryMethod())){ + orderStatusEnum = OrderStatusEnum.UNDELIVERED; + } //修改订单 this.update(new LambdaUpdateWrapper() .eq(Order::getSn, orderSn) - .set(Order::getOrderStatus, OrderStatusEnum.UNDELIVERED.name())); + .set(Order::getOrderStatus, orderStatusEnum.name())); //修改订单 OrderMessage orderMessage = new OrderMessage(); - orderMessage.setNewStatus(OrderStatusEnum.UNDELIVERED); + orderMessage.setNewStatus(orderStatusEnum); orderMessage.setOrderSn(orderSn); this.sendUpdateStatusMessage(orderMessage); } @@ -984,12 +1007,12 @@ public class OrderServiceImpl extends ServiceImpl implements if (order == null) { throw new ServiceException(ResultCode.ORDER_NOT_EXIST); } - //判断是否为虚拟订单 - if (!order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name())) { + //判断是否为虚拟订单 或 自提订单 + if (!order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name()) && !order.getDeliveryMethod().equals(DeliveryMethodEnum.SELF_PICK_UP.name())) { throw new ServiceException(ResultCode.ORDER_TAKE_ERROR); } - //判断虚拟订单状态 - if (!order.getOrderStatus().equals(OrderStatusEnum.TAKE.name())) { + //判断虚拟订单状态 或 待自提 + if (!order.getOrderStatus().equals(OrderStatusEnum.TAKE.name()) && !order.getOrderStatus().equals(OrderStatusEnum.STAY_PICKED_UP.name())) { throw new ServiceException(ResultCode.ORDER_TAKE_ERROR); } //判断验证码是否正确 diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java index 6094598d..954ddb3f 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java @@ -1 +1 @@ -package cn.lili.modules.order.order.serviceimpl; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @since 2020/11/17 7:39 下午 */ @Service public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, JSONUtil.toJsonStr(tradeDTO)); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO 购物车视图 */ private void createTradeCheck(TradeDTO tradeDTO) { //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } //订单配送区域校验 if (tradeDTO.getNotSupportFreight() != null && !tradeDTO.getNotSupportFreight().isEmpty()) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> stringBuilder.append(sku.getGoodsSku().getGoodsName())); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } if (tradeDTO.getCartList().stream().noneMatch(CartVO::getChecked)) { throw new ServiceException(ResultCode.ORDER_NOT_EXIST_VALID); } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO 购物车视图 */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(tradeDTO.getMemberId(), ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO 购物车视图 */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO 购物车视图 */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.endKanjiaActivity(kanjiaId); } } } \ No newline at end of file +package cn.lili.modules.order.order.serviceimpl; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @since 2020/11/17 7:39 下午 */ @Service public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, JSONUtil.toJsonStr(tradeDTO)); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO 购物车视图 */ private void createTradeCheck(TradeDTO tradeDTO) { if(tradeDTO.getStoreAddress() == null){ //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } //订单配送区域校验 if (tradeDTO.getNotSupportFreight() != null && !tradeDTO.getNotSupportFreight().isEmpty()) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> stringBuilder.append(sku.getGoodsSku().getGoodsName())); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } if (tradeDTO.getCartList().stream().noneMatch(CartVO::getChecked)) { throw new ServiceException(ResultCode.ORDER_NOT_EXIST_VALID); } if(tradeDTO.getCartList().stream().allMatch(item -> item.getDeliveryMethod().equals(DeliveryMethodEnum.SELF_PICK_UP.name()))){ throw new ServiceException(ResultCode.STORE_ADDRESS_NOT_EXIST); } } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO 购物车视图 */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(tradeDTO.getMemberId(), ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO 购物车视图 */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO 购物车视图 */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.endKanjiaActivity(kanjiaId); } } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java b/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java index 3e3d059e..5f8d9dd7 100644 --- a/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java +++ b/framework/src/main/java/cn/lili/modules/payment/kit/RefundSupport.java @@ -4,8 +4,6 @@ import cn.lili.common.utils.SnowFlake; import cn.lili.common.utils.SpringContextUtil; import cn.lili.modules.order.aftersale.entity.dos.AfterSale; import cn.lili.modules.order.order.entity.dos.Order; -import cn.lili.modules.order.order.entity.dos.OrderItem; -import cn.lili.modules.order.order.service.OrderItemService; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.StoreFlowService; import cn.lili.modules.payment.entity.RefundLog; @@ -35,11 +33,6 @@ public class RefundSupport { */ @Autowired private OrderService orderService; - /** - * 子订单 - */ - @Autowired - private OrderItemService orderItemService; /** * 售后退款 @@ -64,31 +57,10 @@ public class RefundSupport { Payment payment = (Payment) SpringContextUtil.getBean(paymentMethodEnum.getPlugin()); payment.refund(refundLog); - this.updateReturnGoodsNumber(afterSale); - //记录退款流水 storeFlowService.refundOrder(afterSale); } - /** - * 功能描述: 修改子订单中已售后退款商品数量 - * - * @return void - * @Author ftyy - * @Date 17:33 2021/11/18 - * @Param [afterSale] - **/ - private void updateReturnGoodsNumber(AfterSale afterSale) { - //根据商品id及订单sn获取子订单 - OrderItem orderItem = orderItemService.getByOrderSnAndSkuId(afterSale.getOrderSn(), afterSale.getSkuId()); - - orderItem.setReturnGoodsNumber(afterSale.getNum() + orderItem.getReturnGoodsNumber()); - - //修改子订单订单中的退货数量 - orderItemService.updateById(orderItem); - } - - /** * 退款通知 * diff --git a/framework/src/main/java/cn/lili/modules/permission/service/AdminUserService.java b/framework/src/main/java/cn/lili/modules/permission/service/AdminUserService.java index 7257ca22..edc55c6e 100644 --- a/framework/src/main/java/cn/lili/modules/permission/service/AdminUserService.java +++ b/framework/src/main/java/cn/lili/modules/permission/service/AdminUserService.java @@ -1,6 +1,7 @@ package cn.lili.modules.permission.service; +import cn.lili.common.security.enums.UserEnums; import cn.lili.common.security.token.Token; import cn.lili.modules.permission.entity.dos.AdminUser; import cn.lili.modules.permission.entity.dto.AdminUserDTO; @@ -99,4 +100,11 @@ public interface AdminUserService extends IService { */ Token refreshToken(String refreshToken); + /** + * 登出 + * + * @param userEnums token角色类型 + */ + void logout(UserEnums userEnums); + } diff --git a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java index 53ec3049..bc4f55d4 100644 --- a/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/permission/serviceimpl/AdminUserServiceImpl.java @@ -1,10 +1,13 @@ package cn.lili.modules.permission.serviceimpl; import cn.hutool.core.text.CharSequenceUtil; +import cn.lili.cache.Cache; +import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; +import cn.lili.common.security.enums.UserEnums; import cn.lili.common.security.token.Token; import cn.lili.common.utils.BeanUtil; import cn.lili.common.utils.StringUtils; @@ -53,6 +56,10 @@ public class AdminUserServiceImpl extends ServiceImpl