Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop into feature/pg
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -185,7 +185,7 @@ public class RedisCache implements Cache {
|
||||
public Long counter(Object key) {
|
||||
HyperLogLogOperations<Object, Object> operations = redisTemplate.opsForHyperLogLog();
|
||||
|
||||
//add 方法对应 PFADD 命令
|
||||
//add 方法对应 PFCOUNT 命令
|
||||
return operations.size(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ public enum ResultCode {
|
||||
PROMOTION_ACTIVITY_GOODS_ERROR(40009, "当前活动已经开始无法添加商品"),
|
||||
PROMOTION_ACTIVITY_ERROR(400010, "当前促销活动不存在"),
|
||||
PROMOTION_LOG_EXIST(40011, "活动已参加,已发重复参加"),
|
||||
APPLY_END_TIME_ERROR(40012, "参与截至时间不能小于当前时间,不能大于活动开始时间"),
|
||||
|
||||
/**
|
||||
* 优惠券
|
||||
@@ -301,6 +302,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 +310,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 +375,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"),
|
||||
|
||||
/**
|
||||
* 其他促销
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ public enum UserEnums {
|
||||
MEMBER("会员"),
|
||||
STORE("商家"),
|
||||
MANAGER("管理员"),
|
||||
SYSTEM("系统");
|
||||
SYSTEM("系统"),
|
||||
SEAT("坐席");
|
||||
private final String role;
|
||||
|
||||
UserEnums(String role) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取延时时间(秒)
|
||||
*
|
||||
|
||||
@@ -246,7 +246,17 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> 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);
|
||||
|
||||
@@ -241,12 +241,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
|
||||
}
|
||||
}
|
||||
UpdateWrapper<Category> 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();
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> 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());
|
||||
}
|
||||
|
||||
@@ -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> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
|
||||
return context.getBean(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
CustomSpringConfigurator.context = applicationContext;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
@@ -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 <T> QueryWrapper<T> queryWrapper() {
|
||||
QueryWrapper<T> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<ImMessage> initQueryWrapper() {
|
||||
if (StringUtils.isEmpty(talkId)) {
|
||||
throw new ServiceException(ResultCode.ERROR);
|
||||
}
|
||||
if (num == null || num > 50) {
|
||||
num = 50;
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<ImMessage> 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.lili.modules.im.entity.enums;
|
||||
|
||||
/**
|
||||
* 返回消息类型枚举
|
||||
*
|
||||
* @author liushuai
|
||||
*/
|
||||
public enum MessageResultType {
|
||||
/**
|
||||
* 返回消息类型枚举
|
||||
* <p>
|
||||
* 好友列表
|
||||
* 增加好友
|
||||
* 消息
|
||||
* 阅读消息
|
||||
* 未读消息
|
||||
* 历史消息
|
||||
* 系统提示
|
||||
*/
|
||||
FRIENDS,
|
||||
ADD_FRIENDS,
|
||||
MESSAGE,
|
||||
READ_MESSAGE,
|
||||
UN_READ,
|
||||
HISTORY,
|
||||
SYSTEM_TIPS
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.lili.modules.im.entity.enums;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
* @author liushuai
|
||||
*/
|
||||
public enum MessageTypeEnum {
|
||||
/**
|
||||
* 消息类型枚举
|
||||
* <p>
|
||||
* 普通消息
|
||||
* 图片
|
||||
* 语音
|
||||
* 视频
|
||||
*/
|
||||
MESSAGE,
|
||||
PICTURE,
|
||||
VOICE,
|
||||
GOODS,
|
||||
ORDER,
|
||||
VIDEO
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.lili.modules.im.entity.enums;
|
||||
|
||||
/**
|
||||
* 操作类型枚举
|
||||
*
|
||||
* @author liushuai
|
||||
*/
|
||||
public enum OperationType {
|
||||
/**
|
||||
* 消息类型枚举
|
||||
* <p>
|
||||
* 心跳检测
|
||||
* 发起聊天
|
||||
* 发起消息
|
||||
* 查询历史消息
|
||||
* 阅读消息
|
||||
* 查询未读消息
|
||||
*/
|
||||
PING,
|
||||
CREATE,
|
||||
MESSAGE,
|
||||
HISTORY,
|
||||
READ,
|
||||
UNREAD,
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.lili.modules.im.entity.vo;
|
||||
|
||||
import cn.lili.modules.im.entity.enums.MessageResultType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* MessageVO
|
||||
*
|
||||
* @author Chopper
|
||||
* @version v1.0
|
||||
* 2021-12-30 15:51
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class MessageVO {
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private MessageResultType messageResultType;
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private Object result;
|
||||
}
|
||||
@@ -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<String> readMessageList;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
@@ -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<ImMessage> {
|
||||
|
||||
}
|
||||
@@ -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<ImTalk> {
|
||||
|
||||
}
|
||||
@@ -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<QA> {
|
||||
|
||||
|
||||
}
|
||||
@@ -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<Seat> {
|
||||
|
||||
|
||||
}
|
||||
@@ -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<SeatSetting> {
|
||||
|
||||
|
||||
}
|
||||
@@ -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<ImMessage> {
|
||||
|
||||
/**
|
||||
* 阅读消息
|
||||
*
|
||||
* @param talkId
|
||||
* @param accessToken
|
||||
*/
|
||||
void read(String talkId, String accessToken);
|
||||
|
||||
/**
|
||||
* 未读消息列表
|
||||
*
|
||||
* @param accessToken
|
||||
*/
|
||||
List<ImMessage> unReadMessages(String accessToken);
|
||||
|
||||
/**
|
||||
* 历史消息
|
||||
*
|
||||
* @param accessToken
|
||||
* @param to
|
||||
*/
|
||||
List<ImMessage> historyMessage(String accessToken, String to);
|
||||
|
||||
/**
|
||||
* 是否有新消息
|
||||
* @param accessToken
|
||||
* @return
|
||||
*/
|
||||
Boolean hasNewMessage(String accessToken);
|
||||
|
||||
/**
|
||||
* 分页获取消息列表
|
||||
* @param messageQueryParams 查询条件
|
||||
* @return 消息列表
|
||||
*/
|
||||
List<ImMessage> getList(MessageQueryParams messageQueryParams);
|
||||
|
||||
/**
|
||||
* 获取所有未读消息
|
||||
* @return
|
||||
*/
|
||||
Long unreadMessageCount();
|
||||
|
||||
/**
|
||||
* 清空所有未读消息
|
||||
*/
|
||||
void cleanUnreadMessage();
|
||||
}
|
||||
@@ -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<ImTalk> {
|
||||
|
||||
/**
|
||||
* 获取与某人的聊天框
|
||||
*
|
||||
* @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<ImTalkVO> getUserTalkList(String userName);
|
||||
|
||||
/**
|
||||
* 获取商家聊天列表
|
||||
* @return
|
||||
*/
|
||||
List<ImTalkVO> getStoreTalkList();
|
||||
}
|
||||
@@ -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<QA> {
|
||||
|
||||
/**
|
||||
* 查询店铺问题
|
||||
* @param word
|
||||
* @param pageVO
|
||||
* @return
|
||||
*/
|
||||
IPage<QA> getStoreQA(String word, PageVO pageVO);
|
||||
|
||||
}
|
||||
@@ -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<Seat> {
|
||||
|
||||
|
||||
/**
|
||||
* 获取坐席列表
|
||||
*
|
||||
* @param storeId 店铺id
|
||||
* @return
|
||||
*/
|
||||
List<SeatVO> 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);
|
||||
}
|
||||
@@ -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<SeatSetting> {
|
||||
|
||||
|
||||
/**
|
||||
* 根据店铺id获取坐席配置
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
SeatSetting getSetting(String storeId);
|
||||
|
||||
/**
|
||||
* 根据店铺修改坐席设置
|
||||
*
|
||||
* @param seatSetting 坐席设置
|
||||
* @return
|
||||
*/
|
||||
SeatSetting updateByStore(SeatSetting seatSetting);
|
||||
}
|
||||
@@ -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<ImMessageMapper, ImMessage> implements ImMessageService {
|
||||
|
||||
@Autowired
|
||||
private ImTalkService imTalkService;
|
||||
|
||||
@Override
|
||||
public void read(String talkId, String accessToken) {
|
||||
LambdaUpdateWrapper<ImMessage> 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<ImMessage> unReadMessages(String accessToken) {
|
||||
String userId = UserContext.getAuthUser(accessToken).getId();
|
||||
LambdaQueryWrapper<ImMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ImMessage::getToUser, userId);
|
||||
queryWrapper.eq(ImMessage::getIsRead, false);
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImMessage> historyMessage(String accessToken, String to) {
|
||||
String userId = UserContext.getAuthUser(accessToken).getId();
|
||||
LambdaQueryWrapper<ImMessage> 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<ImMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ImMessage::getIsRead, false);
|
||||
queryWrapper.eq(ImMessage::getToUser, userId);
|
||||
return this.list(queryWrapper).size() > 0;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImMessage> getList(MessageQueryParams messageQueryParams) {
|
||||
List<ImMessage> 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<ImMessage>().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<ImMessage>().eq(ImMessage::getToUser,currentUser.getId()).set(ImMessage::getIsRead,true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据时间倒叙
|
||||
*
|
||||
* @param list
|
||||
*/
|
||||
private static void ListSort(List<ImMessage> list) {
|
||||
list.sort(new Comparator<ImMessage>() {
|
||||
@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<ImMessage> messageList) {
|
||||
if (messageList.size() > 0) {
|
||||
for (ImMessage imMessage : messageList) {
|
||||
if(Boolean.FALSE.equals(imMessage.getIsRead())){
|
||||
imMessage.setIsRead(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.updateBatchById(messageList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<ImTalkMapper, ImTalk> implements ImTalkService {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private StoreService storeService;
|
||||
|
||||
@Autowired
|
||||
private ImMessageService imMessageService;
|
||||
|
||||
@Override
|
||||
public ImTalk getTalkByUser(String userId1, String userId2) {
|
||||
LambdaQueryWrapper<ImTalk> 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<ImTalkVO> getUserTalkList(String userName) {
|
||||
AuthUser authUser = UserContext.getCurrentUser();
|
||||
if(authUser == null){
|
||||
throw new ServiceException(ResultCode.USER_NOT_LOGIN);
|
||||
}
|
||||
LambdaQueryWrapper<ImTalk> 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<ImTalk> imTalks = this.list(queryWrapper);
|
||||
List<ImTalkVO> imTalkVOList = imTalks.stream().map(imTalk -> {
|
||||
return new ImTalkVO(imTalk, authUser.getId());
|
||||
}).collect(Collectors.toList());
|
||||
getUnread(imTalkVOList);
|
||||
return imTalkVOList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImTalkVO> getStoreTalkList() {
|
||||
AuthUser authUser = UserContext.getCurrentUser();
|
||||
if(authUser == null){
|
||||
throw new ServiceException(ResultCode.STORE_NOT_LOGIN_ERROR);
|
||||
}
|
||||
LambdaQueryWrapper<ImTalk> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.and(wq->{
|
||||
wq.like(ImTalk::getUserId1, authUser.getStoreId()).or().like(ImTalk::getUserId2,authUser.getStoreId());
|
||||
});
|
||||
queryWrapper.orderByDesc(ImTalk::getLastTalkTime);
|
||||
List<ImTalk> imTalks = this.list(queryWrapper);
|
||||
|
||||
List<ImTalkVO> imTalkVOList = imTalks.stream().map(imTalk -> {
|
||||
return new ImTalkVO(imTalk, authUser.getStoreId());
|
||||
}).collect(Collectors.toList());
|
||||
getUnread(imTalkVOList);
|
||||
return imTalkVOList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未读消息数量
|
||||
* @param imTalkVOList
|
||||
*/
|
||||
private void getUnread(List<ImTalkVO> imTalkVOList){
|
||||
if(imTalkVOList.size() > 0){
|
||||
for (ImTalkVO imTalkVO : imTalkVOList) {
|
||||
long count = imMessageService.count(new LambdaQueryWrapper<ImMessage>().eq(ImMessage::getFromUser, imTalkVO.getUserId()).eq(ImMessage::getIsRead, false));
|
||||
imTalkVO.setUnread(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<QAMapper, QA> implements QAService {
|
||||
|
||||
@Override
|
||||
public IPage<QA> getStoreQA(String word, PageVO pageVo) {
|
||||
LambdaQueryWrapper<QA> qaLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
qaLambdaQueryWrapper.eq(QA::getTenantId, UserContext.getCurrentUser().getTenantId());
|
||||
qaLambdaQueryWrapper.like(QA::getQuestion, word);
|
||||
return this.page(PageUtil.initPage(pageVo), qaLambdaQueryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -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<SeatMapper, Seat> implements SeatService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SeatTokenGenerate seatTokenGenerate;
|
||||
|
||||
@Autowired
|
||||
private Cache<String> cache;
|
||||
|
||||
/**
|
||||
* 快捷登录缓存前缀
|
||||
*/
|
||||
private static String prefix = "{quick_login}_";
|
||||
|
||||
|
||||
@Override
|
||||
public List<SeatVO> seatVoList(String storeId) {
|
||||
|
||||
LambdaQueryWrapper<Seat> seatLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
seatLambdaQueryWrapper.eq(Seat::getTenantId, storeId);
|
||||
List<Seat> list = this.list(seatLambdaQueryWrapper);
|
||||
|
||||
//转换模型为VO
|
||||
List<SeatVO> 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<Seat> seatLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
seatLambdaQueryWrapper.eq(Seat::getUsername, username);
|
||||
return this.getOne(seatLambdaQueryWrapper);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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<SeatSettingMapper, SeatSetting> implements SeatSettingService {
|
||||
@Override
|
||||
public SeatSetting getSetting(String storeId) {
|
||||
LambdaQueryWrapper<SeatSetting> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<Seat> {
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
//电子面单模板
|
||||
@@ -198,6 +198,7 @@ public class KdNiaoServiceImpl implements KdNiaoService {
|
||||
//根据公司业务处理返回的信息......
|
||||
JSONObject obj = JSONObject.parseObject(result);
|
||||
|
||||
log.info("电子面单响应:{}",result);
|
||||
if(!"100".equals(obj.getString("ResultCode"))){
|
||||
return obj.getString("Reason");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ public class FootPrint extends BaseEntity {
|
||||
@ApiModelProperty(value = "会员ID")
|
||||
private String memberId;
|
||||
|
||||
@ApiModelProperty(value = "店铺Id")
|
||||
private String storeId;
|
||||
|
||||
@ApiModelProperty(value = "商品ID")
|
||||
private String goodsId;
|
||||
|
||||
|
||||
@@ -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 <T> QueryWrapper<T> queryWrapper() {
|
||||
QueryWrapper<T> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<FootPrint> {
|
||||
/**
|
||||
* 获取会员浏览历史分页
|
||||
*
|
||||
* @param pageVO 分页
|
||||
* @param params 分页
|
||||
* @return 会员浏览历史列表
|
||||
*/
|
||||
IPage<EsGoodsIndex> footPrintPage(PageVO pageVO);
|
||||
IPage<EsGoodsIndex> footPrintPage(FootPrintQueryParams params);
|
||||
|
||||
/**
|
||||
* 获取当前会员的浏览记录数量
|
||||
@@ -53,4 +54,5 @@ public interface FootprintService extends IService<FootPrint> {
|
||||
* @return 当前会员的浏览记录数量
|
||||
*/
|
||||
long getFootprintNum();
|
||||
|
||||
}
|
||||
@@ -252,7 +252,6 @@ public interface MemberService extends IService<Member> {
|
||||
void logout(UserEnums userEnums);
|
||||
|
||||
/**
|
||||
* <<<<<<< HEAD
|
||||
* 修改会员是否拥有店铺
|
||||
*
|
||||
* @param haveStore 是否拥有店铺
|
||||
|
||||
@@ -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<FootprintMapper, FootPrint
|
||||
queryWrapper.eq(FootPrint::getGoodsId, footPrint.getGoodsId());
|
||||
//如果已存在某商品记录,则更新其修改时间
|
||||
//如果不存在则添加记录
|
||||
//为了保证足迹的排序,将原本足迹删除后重新添加
|
||||
List<FootPrint> 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<FootprintMapper, FootPrint
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<EsGoodsIndex> footPrintPage(PageVO pageVO) {
|
||||
|
||||
LambdaQueryWrapper<FootPrint> lambdaQueryWrapper = Wrappers.lambdaQuery();
|
||||
lambdaQueryWrapper.eq(FootPrint::getMemberId, UserContext.getCurrentUser().getId());
|
||||
lambdaQueryWrapper.eq(FootPrint::getDeleteFlag, false);
|
||||
lambdaQueryWrapper.orderByDesc(FootPrint::getCreateTime);
|
||||
IPage<FootPrint> footPrintPages = this.page(PageUtil.initPage(pageVO), lambdaQueryWrapper);
|
||||
|
||||
|
||||
public IPage<EsGoodsIndex> footPrintPage(FootPrintQueryParams params) {
|
||||
IPage<FootPrint> footPrintPages = this.page(PageUtil.initPage(params), params.queryWrapper());
|
||||
//定义结果
|
||||
IPage<EsGoodsIndex> esGoodsIndexIPage = new Page<>();
|
||||
|
||||
@@ -90,7 +82,7 @@ public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, FootPrint
|
||||
return esGoodsIndexIPage;
|
||||
} else {
|
||||
List<EsGoodsIndex> 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);
|
||||
|
||||
@@ -40,13 +40,16 @@ 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.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.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 +97,9 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
|
||||
@Autowired
|
||||
private RocketmqCustomProperties rocketmqCustomProperties;
|
||||
|
||||
@Autowired
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
/**
|
||||
@@ -183,7 +189,8 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
|
||||
@Override
|
||||
public Token usernameStoreLogin(String username, String password) {
|
||||
|
||||
Member member = this.findMember(username);
|
||||
// Member member = this.findMember(username);
|
||||
Member member = this.getOne(new LambdaQueryWrapper<Member>().eq(Member::getMobile,username));
|
||||
//判断用户是否存在
|
||||
if (member == null || !member.getDisabled()) {
|
||||
throw new ServiceException(ResultCode.USER_NOT_EXIST);
|
||||
@@ -287,6 +294,8 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
|
||||
member.setId(SnowFlake.getIdStr());
|
||||
//保存会员
|
||||
this.save(member);
|
||||
|
||||
|
||||
// 发送会员注册信息
|
||||
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), member));
|
||||
}
|
||||
@@ -299,6 +308,9 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import cn.lili.modules.order.order.entity.vo.OrderVO;
|
||||
import cn.lili.modules.order.order.entity.vo.ReceiptVO;
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
|
||||
import cn.lili.modules.promotion.entity.vos.MemberCouponVO;
|
||||
import cn.lili.modules.store.entity.dos.StoreAddress;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -106,6 +107,10 @@ public class TradeDTO implements Serializable {
|
||||
*/
|
||||
private MemberAddress memberAddress;
|
||||
|
||||
/**
|
||||
* 自提地址
|
||||
*/
|
||||
private StoreAddress storeAddress;
|
||||
|
||||
/**
|
||||
* 客户端类型
|
||||
|
||||
@@ -160,35 +160,37 @@ public class CheckDataRender implements CartRenderStep {
|
||||
private void groupStore(TradeDTO tradeDTO) {
|
||||
//渲染的购物车
|
||||
List<CartVO> cartList = new ArrayList<>();
|
||||
|
||||
//根据店铺分组
|
||||
Map<String, List<CartSkuVO>> storeCollect = tradeDTO.getSkuList().stream().collect(Collectors.groupingBy(CartSkuVO::getStoreId));
|
||||
for (Map.Entry<String, List<CartSkuVO>> 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<String, List<CartSkuVO>> storeCollect = tradeDTO.getSkuList().stream().collect(Collectors.groupingBy(CartSkuVO::getStoreId));
|
||||
for (Map.Entry<String, List<CartSkuVO>> 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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<String, Double> 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) {
|
||||
|
||||
|
||||
@@ -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<String, Double> skuPriceDetail, Double rate) {
|
||||
private void renderFullRate(CartVO cart, Map<String, Double> skuPriceDetail, Double rate, String activityId) {
|
||||
|
||||
List<CartSkuVO> 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());
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -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,71 +44,77 @@ public class SkuFreightRender implements CartRenderStep {
|
||||
List<CartSkuVO> cartSkuVOS = tradeDTO.getCheckedSkuList();
|
||||
//会员收货地址问题处理
|
||||
MemberAddress memberAddress = tradeDTO.getMemberAddress();
|
||||
StoreAddress storeAddress = tradeDTO.getStoreAddress();
|
||||
//如果收货地址为空,则抛出异常
|
||||
if (memberAddress == null) {
|
||||
if (memberAddress == null && storeAddress == null) {
|
||||
return;
|
||||
}
|
||||
//运费分组信息
|
||||
Map<String, List<String>> freightGroups = freightTemplateGrouping(cartSkuVOS);
|
||||
//选择物流的时候计算价格
|
||||
if(DeliveryMethodEnum.LOGISTICS.name().equals(tradeDTO.getCartList().get(0).getDeliveryMethod())){
|
||||
if (memberAddress != null) {
|
||||
//运费分组信息
|
||||
Map<String, List<String>> freightGroups = freightTemplateGrouping(cartSkuVOS);
|
||||
|
||||
//循环运费模版
|
||||
for (Map.Entry<String, List<String>> freightTemplateGroup : freightGroups.entrySet()) {
|
||||
//循环运费模版
|
||||
for (Map.Entry<String, List<String>> freightTemplateGroup : freightGroups.entrySet()) {
|
||||
|
||||
//商品id列表
|
||||
List<String> skuIds = freightTemplateGroup.getValue();
|
||||
//商品id列表
|
||||
List<String> skuIds = freightTemplateGroup.getValue();
|
||||
|
||||
//当前购物车商品列表
|
||||
List<CartSkuVO> currentCartSkus = cartSkuVOS.stream().filter(item -> skuIds.contains(item.getGoodsSku().getId())).collect(Collectors.toList());
|
||||
//当前购物车商品列表
|
||||
List<CartSkuVO> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, Double> skuPromotionDetail, Double discountPrice, PromotionTypeEnum promotionTypeEnum) {
|
||||
public static void recountPrice(TradeDTO tradeDTO, Map<String, Double> 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);
|
||||
|
||||
@@ -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<String> shippingMethodList(String way);
|
||||
}
|
||||
|
||||
@@ -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,23 +483,21 @@ 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);
|
||||
TradeDTO tradeDTO = this.getCheckedTradeDTO(cartTypeEnum);
|
||||
for (CartVO cartVO : tradeDTO.getCartList()) {
|
||||
if (cartVO.getStoreId().equals(storeId)) {
|
||||
cartVO.setDeliveryMethod(DeliveryMethodEnum.valueOf(deliveryMethod).name());
|
||||
}
|
||||
cartVO.setDeliveryMethod(DeliveryMethodEnum.valueOf(deliveryMethod).name());
|
||||
}
|
||||
this.resetTradeDTO(tradeDTO);
|
||||
TradeDTO neTradeDTO = (TradeDTO) cache.get(this.getOriginKey(cartTypeEnum));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -547,8 +569,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 +580,22 @@ public class CartServiceImpl implements CartService {
|
||||
return trade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> shippingMethodList(String way) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取购物车类型
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,9 @@ public class PriceDetailDTO implements Serializable {
|
||||
@ApiModelProperty(value = "优惠金额")
|
||||
private Double discountPrice;
|
||||
|
||||
@ApiModelProperty(value = "优惠详情")
|
||||
private List<DiscountPriceItem> discountPriceDetail;
|
||||
|
||||
@ApiModelProperty(value = "优惠券金额")
|
||||
private Double couponPrice;
|
||||
|
||||
@@ -101,6 +104,27 @@ public class PriceDetailDTO implements Serializable {
|
||||
private List<PromotionSkuVO> joinPromotion;
|
||||
|
||||
|
||||
/**
|
||||
* 设置促销详情
|
||||
*
|
||||
* @param discountPriceItem 促销信息
|
||||
*/
|
||||
public void setDiscountPriceItem(DiscountPriceItem discountPriceItem) {
|
||||
List<DiscountPriceItem> 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());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ public enum OrderStatusEnum {
|
||||
UNDELIVERED("待发货"),
|
||||
DELIVERED("已发货"),
|
||||
COMPLETED("已完成"),
|
||||
STAY_PICKED_UP("待自提"),
|
||||
/**
|
||||
* 虚拟订单需要核验商品
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,7 @@ 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;
|
||||
}
|
||||
//新订单,允许支付
|
||||
|
||||
@@ -183,6 +183,15 @@ public interface OrderService extends IService<Order> {
|
||||
*/
|
||||
Order take(String orderSn, String verificationCode);
|
||||
|
||||
|
||||
/**
|
||||
* 订单核验
|
||||
*
|
||||
* @param verificationCode 验证码
|
||||
* @return 订单
|
||||
*/
|
||||
Order take(String verificationCode);
|
||||
|
||||
/**
|
||||
* 根据核验码获取订单信息
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
@@ -290,12 +292,13 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> 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());
|
||||
@@ -472,11 +475,24 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Order take(String verificationCode) {
|
||||
String storeId = OperationalJudgment.judgment(UserContext.getCurrentUser()).getStoreId();
|
||||
Order order = this.getOne(new LambdaQueryWrapper<Order>().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<Order>()
|
||||
.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));
|
||||
}
|
||||
@@ -938,13 +954,20 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> 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<Order>()
|
||||
.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);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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<AdminUser> {
|
||||
*/
|
||||
Token refreshToken(String refreshToken);
|
||||
|
||||
/**
|
||||
* 登出
|
||||
*
|
||||
* @param userEnums token角色类型
|
||||
*/
|
||||
void logout(UserEnums userEnums);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<AdminUserMapper, AdminUser
|
||||
private MenuService menuService;
|
||||
@Autowired
|
||||
private ManagerTokenGenerate managerTokenGenerate;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
/**
|
||||
* 角色长度
|
||||
*/
|
||||
@@ -132,6 +139,14 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
|
||||
return managerTokenGenerate.refreshToken(refreshToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(UserEnums userEnums) {
|
||||
String currentUserToken = UserContext.getCurrentUserToken();
|
||||
if (CharSequenceUtil.isNotEmpty(currentUserToken)) {
|
||||
cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix(userEnums) + currentUserToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AdminUser findByUsername(String username) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.lili.modules.promotion.entity.dos;
|
||||
|
||||
import cn.lili.modules.promotion.entity.enums.CouponActivitySendTypeEnum;
|
||||
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
|
||||
import cn.lili.modules.promotion.entity.enums.CouponFrequencyEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
@@ -26,15 +27,22 @@ public class CouponActivity extends BasePromotions {
|
||||
* @see CouponActivityTypeEnum
|
||||
*/
|
||||
@NotNull(message = "优惠券活动类型不能为空")
|
||||
@ApiModelProperty(value = "优惠券活动类型", allowableValues = "REGISTERED:新人赠券,SPECIFY:精确发券")
|
||||
@ApiModelProperty(value = "优惠券活动类型", allowableValues = "REGISTERED:新人赠券,INVITE_NEW:邀新赠券,AUTO_COUPON:自动赠券,SPECIFY:精确发券")
|
||||
private String couponActivityType;
|
||||
|
||||
/**
|
||||
* @see CouponActivitySendTypeEnum
|
||||
*/
|
||||
//目前仅在自动赠券模式下该参数会生效,日后如果完善发送测略则调整这里即可
|
||||
@NotNull(message = "请选择活动范围")
|
||||
@ApiModelProperty(value = "活动范围", allowableValues = "ALL:全部会员,DESIGNATED:指定会员")
|
||||
private String activityScope;
|
||||
/**
|
||||
* @see CouponFrequencyEnum
|
||||
*/
|
||||
@NotNull(message = "领取周期")
|
||||
@ApiModelProperty(value = "活动范围", allowableValues = " DAY:每天, WEEK:每周, MONTH:每月")
|
||||
private String couponFrequencyEnum;
|
||||
|
||||
@ApiModelProperty(value = "活动范围详情,只有精准发券使用")
|
||||
private String activityScopeInfo;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.lili.modules.promotion.entity.dos;
|
||||
|
||||
import cn.lili.mybatis.BaseIdEntity;
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 会员优惠券实体类
|
||||
*
|
||||
* @author Chopper
|
||||
* @since 2020-03-19 10:44 上午
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("li_member_coupon_sign")
|
||||
@ApiModel(value = "会员优惠券领取标记")
|
||||
public class MemberCouponSign extends BaseIdEntity {
|
||||
|
||||
@ApiModelProperty(value = "优惠券活动ID")
|
||||
private String couponActivityId;
|
||||
|
||||
@ApiModelProperty(value = "会员ID")
|
||||
private String memberId;
|
||||
|
||||
@ApiModelProperty(value = "失效时间,到达失效时间后自动删除,用户可以再次领取")
|
||||
private Date invalidTime;
|
||||
|
||||
|
||||
@CreatedDate
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建时间", hidden = true)
|
||||
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.lili.modules.promotion.entity.dto;
|
||||
|
||||
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 优惠券活动触发
|
||||
*
|
||||
* @author paulG
|
||||
* @since 2020/10/9
|
||||
**/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class CouponActivityTrigger {
|
||||
|
||||
|
||||
@ApiModelProperty(value = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@ApiModelProperty(value = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
@ApiModelProperty(value = "优惠券活动类型")
|
||||
private CouponActivityTypeEnum couponActivityTypeEnum;
|
||||
}
|
||||
@@ -13,7 +13,15 @@ public enum CouponActivityTypeEnum {
|
||||
*/
|
||||
REGISTERED("新人赠券"),
|
||||
/**
|
||||
* "精确发券"
|
||||
* "邀新赠券"
|
||||
*/
|
||||
INVITE_NEW("邀新赠券"),
|
||||
/**
|
||||
* "自动赠券"
|
||||
*/
|
||||
AUTO_COUPON("自动赠券"),
|
||||
/**
|
||||
* "定向发券"
|
||||
*/
|
||||
SPECIFY("精确发券");
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.lili.modules.promotion.entity.enums;
|
||||
|
||||
/**
|
||||
* 优惠券活动发送类型枚举
|
||||
*
|
||||
* @author Bulbasaur
|
||||
* @since 2021/5/20 5:47 下午
|
||||
*/
|
||||
public enum CouponFrequencyEnum {
|
||||
|
||||
/**
|
||||
* 领取周期
|
||||
*/
|
||||
DAY("每天"), WEEK("每周"), MONTH("每月");
|
||||
|
||||
private final String description;
|
||||
|
||||
CouponFrequencyEnum(String str) {
|
||||
this.description = str;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static boolean exist(String name) {
|
||||
try {
|
||||
CouponFrequencyEnum.valueOf(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,5 +23,14 @@ public enum CouponRangeDayEnum {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static boolean exist(String name) {
|
||||
try {
|
||||
CouponRangeDayEnum.valueOf(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.lili.modules.promotion.mapper;
|
||||
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* 会员优惠券领取标记
|
||||
*
|
||||
* @author liushuai(liushuai711 @ gmail.com)
|
||||
* @version v4.0
|
||||
* @Description:
|
||||
* @since 2023/1/3 18:11
|
||||
*/
|
||||
public interface MemberCouponSignMapper extends BaseMapper<MemberCouponSign> {
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package cn.lili.modules.promotion.service;
|
||||
|
||||
import cn.lili.modules.member.entity.dos.Member;
|
||||
import cn.lili.modules.promotion.entity.dos.CouponActivity;
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
|
||||
import cn.lili.modules.promotion.entity.dto.CouponActivityTrigger;
|
||||
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
|
||||
|
||||
import java.util.List;
|
||||
@@ -27,16 +28,15 @@ public interface CouponActivityService extends AbstractPromotionsService<CouponA
|
||||
/**
|
||||
* 精准发券
|
||||
*
|
||||
* @param couponActivityId 优惠券活动ID
|
||||
* @param couponActivity 精准发券
|
||||
*/
|
||||
void specify(String couponActivityId);
|
||||
void specify(CouponActivity couponActivity);
|
||||
|
||||
/**
|
||||
* 注册赠券
|
||||
* 用户优惠券活动触发
|
||||
*
|
||||
* @param couponActivityList 优惠券活动
|
||||
* @param member 会员
|
||||
* @return 优惠券列表
|
||||
*/
|
||||
void registered(List<CouponActivity> couponActivityList, Member member);
|
||||
List<MemberCoupon> trigger(CouponActivityTrigger couponActivityTrigger);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.lili.modules.promotion.service;
|
||||
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
|
||||
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠券领取标记业务层
|
||||
*
|
||||
* @author liushuai(liushuai711 @ gmail.com)
|
||||
* @version v4.0
|
||||
* @Description:
|
||||
* @since 2023/1/3 18:12
|
||||
*/
|
||||
|
||||
public interface MemberCouponSignService extends IService<MemberCouponSign> {
|
||||
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* 清除失效标记
|
||||
*/
|
||||
void clean();
|
||||
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* 清除失效标记
|
||||
*/
|
||||
List<CouponActivityVO> receiveCoupon(List<CouponActivityVO> couponActivity);
|
||||
}
|
||||
@@ -2,30 +2,35 @@ package cn.lili.modules.promotion.serviceimpl;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.common.enums.PromotionTypeEnum;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.member.entity.dos.Member;
|
||||
import cn.lili.common.security.AuthUser;
|
||||
import cn.lili.modules.member.service.MemberService;
|
||||
import cn.lili.modules.promotion.entity.dos.Coupon;
|
||||
import cn.lili.modules.promotion.entity.dos.CouponActivity;
|
||||
import cn.lili.modules.promotion.entity.dos.CouponActivityItem;
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
|
||||
import cn.lili.modules.promotion.entity.dto.CouponActivityDTO;
|
||||
import cn.lili.modules.promotion.entity.dto.CouponActivityTrigger;
|
||||
import cn.lili.modules.promotion.entity.enums.*;
|
||||
import cn.lili.modules.promotion.entity.vos.CouponActivityItemVO;
|
||||
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
|
||||
import cn.lili.modules.promotion.mapper.CouponActivityMapper;
|
||||
import cn.lili.modules.promotion.service.CouponActivityItemService;
|
||||
import cn.lili.modules.promotion.service.CouponActivityService;
|
||||
import cn.lili.modules.promotion.service.CouponService;
|
||||
import cn.lili.modules.promotion.service.MemberCouponService;
|
||||
import cn.lili.modules.promotion.service.*;
|
||||
import cn.lili.modules.promotion.tools.PromotionTools;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import groovy.util.logging.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -44,9 +49,18 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
private MemberCouponService memberCouponService;
|
||||
@Autowired
|
||||
private CouponActivityItemService couponActivityItemService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private MemberCouponSignService memberCouponSignService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private Cache<List<CouponActivityVO>> cache;
|
||||
|
||||
@Override
|
||||
public CouponActivityVO getCouponActivityVO(String couponActivityId) {
|
||||
CouponActivity couponActivity = this.getById(couponActivityId);
|
||||
@@ -55,47 +69,30 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void specify(String couponActivityId) {
|
||||
//获取优惠券
|
||||
CouponActivity couponActivity = this.getById(couponActivityId);
|
||||
public void specify(CouponActivity couponActivity) {
|
||||
//获取活动优惠券发送范围
|
||||
List<Map<String, Object>> member = this.getMemberList(couponActivity);
|
||||
|
||||
//会员拆成多个小组进行发送
|
||||
List<List<Map<String, Object>>> memberGroup = new ArrayList<>();
|
||||
//如果指定会员发券,则当下直接进行发送,如果是全体会员发券,则变更为用户登录首页进行请求发券
|
||||
//PS:即不主动发券,需要用户在活动时间内登录自动领取优惠券,类似美团、饿了么 的发放方式
|
||||
if (couponActivity.getActivityScope().equals(CouponActivitySendTypeEnum.DESIGNATED.name())) {
|
||||
//会员拆成多个小组进行发送
|
||||
List<List<Map<String, Object>>> memberGroup = new ArrayList<>();
|
||||
|
||||
//循环分组
|
||||
for (int i = 0; i < (member.size() / 100 + (member.size() % 100 == 0 ? 0 : 1)); i++) {
|
||||
int endPoint = Math.min((100 + (i * 100)), member.size());
|
||||
memberGroup.add(member.subList((i * 100), endPoint));
|
||||
}
|
||||
|
||||
//优惠优惠券活动的优惠券列表
|
||||
List<CouponActivityItem> couponActivityItems = couponActivityItemService.getCouponActivityList(couponActivity.getId());
|
||||
//发送优惠券
|
||||
for (List<Map<String, Object>> memberList : memberGroup) {
|
||||
sendCoupon(memberList, couponActivityItems);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void registered(List<CouponActivity> couponActivityList, Member member) {
|
||||
for (CouponActivity couponActivity : couponActivityList) {
|
||||
//获取会员信息
|
||||
List<Map<String, Object>> memberList = new ArrayList<>();
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("id", member.getId());
|
||||
map.put("nick_name", member.getNickName());
|
||||
memberList.add(map);
|
||||
//循环分组
|
||||
for (int i = 0; i < (member.size() / 100 + (member.size() % 100 == 0 ? 0 : 1)); i++) {
|
||||
int endPoint = Math.min((100 + (i * 100)), member.size());
|
||||
memberGroup.add(member.subList((i * 100), endPoint));
|
||||
}
|
||||
|
||||
//优惠优惠券活动的优惠券列表
|
||||
List<CouponActivityItem> couponActivityItems = couponActivityItemService.getCouponActivityList(couponActivity.getId());
|
||||
|
||||
//发送优惠券
|
||||
sendCoupon(memberList, couponActivityItems);
|
||||
for (List<Map<String, Object>> memberList : memberGroup) {
|
||||
sendCoupon(memberList, couponActivityItems);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,9 +143,7 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
@Transactional(rollbackFor = {Exception.class})
|
||||
public boolean updatePromotionsGoods(CouponActivity couponActivity) {
|
||||
boolean result = super.updatePromotionsGoods(couponActivity);
|
||||
if (couponActivity instanceof CouponActivityDTO
|
||||
&& !PromotionsStatusEnum.CLOSE.name().equals(couponActivity.getPromotionStatus())
|
||||
&& PromotionsScopeTypeEnum.PORTION_GOODS.name().equals(couponActivity.getScopeType())) {
|
||||
if (couponActivity instanceof CouponActivityDTO && !PromotionsStatusEnum.CLOSE.name().equals(couponActivity.getPromotionStatus()) && PromotionsScopeTypeEnum.PORTION_GOODS.name().equals(couponActivity.getScopeType())) {
|
||||
CouponActivityDTO couponActivityDTO = (CouponActivityDTO) couponActivity;
|
||||
//创建优惠券活动子列表
|
||||
for (CouponActivityItem couponActivityItem : couponActivityDTO.getCouponActivityItems()) {
|
||||
@@ -168,12 +163,52 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateEsGoodsIndex(CouponActivity couponActivity) {
|
||||
//如果是精准发券,进行发送优惠券
|
||||
if (!PromotionsStatusEnum.CLOSE.name().equals(couponActivity.getPromotionStatus()) && couponActivity.getCouponActivityType().equals(CouponActivityTypeEnum.SPECIFY.name())) {
|
||||
this.specify(couponActivity.getId());
|
||||
|
||||
|
||||
switch (CouponActivityTypeEnum.valueOf(couponActivity.getCouponActivityType())) {
|
||||
|
||||
// 精准发券 则立即发放
|
||||
case SPECIFY:
|
||||
this.specify(couponActivity);
|
||||
break;
|
||||
//其他活动则是缓存模块,根据缓存中的优惠券活动信息来确认发放优惠券测略
|
||||
case INVITE_NEW:
|
||||
case AUTO_COUPON:
|
||||
case REGISTERED:
|
||||
this.resetCache(couponActivity.getCouponActivityType());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberCoupon> trigger(CouponActivityTrigger couponActivityTrigger) {
|
||||
//获取当前正在进行的优惠券活动
|
||||
List<CouponActivityVO> couponActivities = currentCouponActivity(couponActivityTrigger.getCouponActivityTypeEnum().name());
|
||||
|
||||
|
||||
/**
|
||||
* 自动发送优惠券则需要补足日志
|
||||
*/
|
||||
if (couponActivityTrigger.getCouponActivityTypeEnum().equals(CouponActivityTypeEnum.AUTO_COUPON)) {
|
||||
couponActivities = memberCouponSignService.receiveCoupon(couponActivities);
|
||||
}
|
||||
|
||||
//优惠券发放列表
|
||||
List<CouponActivityItemVO> couponActivityItemVOS = new ArrayList<>();
|
||||
|
||||
//准备发放优惠券活动的列表
|
||||
couponActivities.stream().forEach(item -> couponActivityItemVOS.addAll(item.getCouponActivityItems()));
|
||||
|
||||
AuthUser authUser = new AuthUser();
|
||||
authUser.setId(couponActivityTrigger.getUserId());
|
||||
authUser.setNickName(couponActivityTrigger.getNickName());
|
||||
|
||||
|
||||
return this.sendCoupon(authUser, couponActivityItemVOS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当前促销类型
|
||||
*
|
||||
@@ -185,36 +220,131 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送优惠券
|
||||
* 1.循环优惠券列表
|
||||
* 2.判断优惠券每个会员发送数量
|
||||
* 3.循环会员列表,发送优惠券
|
||||
* 4.记录优惠券发送数量
|
||||
* 缓存key生成策略
|
||||
*
|
||||
* @param couponActivityType 优惠券活动类型
|
||||
* @return 缓存key
|
||||
*/
|
||||
private String cacheKey(String couponActivityType) {
|
||||
return CachePrefix.CURRENT_COUPON_ACTIVITY.getPrefix() + couponActivityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前进行的活动
|
||||
*
|
||||
* @return 当前进行的活动列表
|
||||
*/
|
||||
private List<CouponActivityVO> currentCouponActivity() {
|
||||
return currentCouponActivity(CouponActivityTypeEnum.AUTO_COUPON.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前进行的活动
|
||||
*
|
||||
* @return 当前进行的活动列表
|
||||
*/
|
||||
private List<CouponActivityVO> currentCouponActivity(String couponActivityTypeEnum) {
|
||||
//获取缓存中的活动
|
||||
List<CouponActivityVO> couponActivityList = cache.get(cacheKey(couponActivityTypeEnum));
|
||||
if (couponActivityList == null) {
|
||||
return ongoingActivities(resetCache(couponActivityTypeEnum));
|
||||
}
|
||||
return ongoingActivities(couponActivityList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从生效的活动优惠券中,过滤出正在进行的活动列表
|
||||
*
|
||||
* @param activityVOS
|
||||
* @return
|
||||
*/
|
||||
private List<CouponActivityVO> ongoingActivities(List<CouponActivityVO> activityVOS) {
|
||||
if (activityVOS == null || activityVOS.size() == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return activityVOS.stream().filter(item -> {
|
||||
return item.getPromotionStatus().equals(PromotionsStatusEnum.START.name());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写缓存中的活动优惠券信息
|
||||
*/
|
||||
private List<CouponActivityVO> resetCache(String couponActivityType) {
|
||||
|
||||
LambdaQueryWrapper<CouponActivity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
//如果结束时间大于当前时间,则表示有效
|
||||
lambdaQueryWrapper.gt(CouponActivity::getEndTime, new Date());
|
||||
//发送策略
|
||||
lambdaQueryWrapper.eq(CouponActivity::getActivityScope, CouponActivitySendTypeEnum.ALL);
|
||||
//活动类型
|
||||
lambdaQueryWrapper.eq(CouponActivity::getCouponActivityType, couponActivityType);
|
||||
|
||||
//查询出结果,缓存后返回
|
||||
List<CouponActivity> couponActivities = list(lambdaQueryWrapper);
|
||||
|
||||
List<CouponActivityVO> couponActivityVOS = new ArrayList<>();
|
||||
for (CouponActivity couponActivity : couponActivities) {
|
||||
couponActivityVOS.add(new CouponActivityVO(couponActivity, couponActivityItemService.getCouponActivityItemListVO(couponActivity.getId())));
|
||||
}
|
||||
|
||||
cache.put(cacheKey(couponActivityType), couponActivityVOS);
|
||||
return couponActivityVOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定向发送优惠券
|
||||
*
|
||||
* @param memberList 用户列表
|
||||
* @param couponActivityItems 优惠券列表
|
||||
*/
|
||||
void sendCoupon(List<Map<String, Object>> memberList, List<CouponActivityItem> couponActivityItems) {
|
||||
private void sendCoupon(List<Map<String, Object>> memberList, List<CouponActivityItem> couponActivityItems) {
|
||||
|
||||
for (Map<String, Object> map : memberList) {
|
||||
AuthUser authUser = new AuthUser();
|
||||
authUser.setId(map.get("id").toString());
|
||||
authUser.setNickName(map.get("nick_name").toString());
|
||||
|
||||
sendCoupon(authUser, couponActivityItems);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 给当前用户发送优惠券
|
||||
* 1.循环优惠券列表
|
||||
* 2.判断优惠券每个会员发送数量
|
||||
* 3.记录优惠券发送数量
|
||||
*
|
||||
* @param authUser 发送目标用户
|
||||
* @param couponActivityItems 优惠券列表
|
||||
*/
|
||||
private List<MemberCoupon> sendCoupon(AuthUser authUser, List<? extends CouponActivityItem> couponActivityItems) {
|
||||
|
||||
//最终优惠券列表
|
||||
List<MemberCoupon> finalCoupons = new ArrayList<>();
|
||||
|
||||
//循环优惠券赠送列表
|
||||
for (CouponActivityItem couponActivityItem : couponActivityItems) {
|
||||
//获取优惠券
|
||||
Coupon coupon = couponService.getById(couponActivityItem.getCouponId());
|
||||
//判断优惠券是否存在
|
||||
if (coupon != null) {
|
||||
List<MemberCoupon> memberCouponList = new LinkedList<>();
|
||||
//循环优惠券的领取数量
|
||||
int j = couponActivityItem.getNum();
|
||||
for (int i = 1; i <= j; i++) {
|
||||
//循环会员列表,添加优惠券
|
||||
for (Map<String, Object> map : memberList) {
|
||||
MemberCoupon memberCoupon = new MemberCoupon(coupon);
|
||||
memberCoupon.setMemberId(map.get("id").toString());
|
||||
memberCoupon.setMemberName(map.get("nick_name").toString());
|
||||
memberCoupon.setMemberCouponStatus(MemberCouponStatusEnum.NEW.name());
|
||||
memberCoupon.setPlatformFlag(PromotionTools.PLATFORM_ID.equals(coupon.getStoreId()));
|
||||
memberCouponList.add(memberCoupon);
|
||||
}
|
||||
int activitySendNum = couponActivityItem.getNum();
|
||||
|
||||
List<MemberCoupon> memberCouponList = new ArrayList<>();
|
||||
for (int i = 1; i <= activitySendNum; i++) {
|
||||
MemberCoupon memberCoupon = new MemberCoupon(coupon);
|
||||
memberCoupon.setMemberId(authUser.getId());
|
||||
memberCoupon.setMemberName(authUser.getNickName());
|
||||
memberCoupon.setMemberCouponStatus(MemberCouponStatusEnum.NEW.name());
|
||||
memberCoupon.setPlatformFlag(PromotionTools.PLATFORM_ID.equals(coupon.getStoreId()));
|
||||
memberCouponList.add(memberCoupon);
|
||||
}
|
||||
|
||||
finalCoupons.addAll(memberCouponList);
|
||||
//批量添加优惠券
|
||||
memberCouponService.saveBatch(memberCouponList);
|
||||
//添加优惠券已领取数量
|
||||
@@ -223,6 +353,10 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
log.error("赠送优惠券失败,当前优惠券不存在:" + couponActivityItem.getCouponId());
|
||||
}
|
||||
}
|
||||
if (finalCoupons.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return finalCoupons;
|
||||
|
||||
}
|
||||
|
||||
@@ -235,16 +369,13 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
*/
|
||||
private List<Map<String, Object>> getMemberList(CouponActivity couponActivity) {
|
||||
//判断优惠券的发送范围,获取会员列表
|
||||
if ("ALL".equals(couponActivity.getActivityScope())) {
|
||||
return this.memberService.listFieldsByMemberIds("id,nick_name", null);
|
||||
} else {
|
||||
List<String> ids = new ArrayList<>();
|
||||
if (JSONUtil.isJsonArray(couponActivity.getActivityScopeInfo())) {
|
||||
JSONArray array = JSONUtil.parseArray(couponActivity.getActivityScopeInfo());
|
||||
ids = array.toList(Map.class).stream().map(i -> i.get("id").toString()).collect(Collectors.toList());
|
||||
}
|
||||
return memberService.listFieldsByMemberIds("id,nick_name", ids);
|
||||
|
||||
List<String> ids = new ArrayList<>();
|
||||
if (JSONUtil.isJsonArray(couponActivity.getActivityScopeInfo())) {
|
||||
JSONArray array = JSONUtil.parseArray(couponActivity.getActivityScopeInfo());
|
||||
ids = array.toList(Map.class).stream().map(i -> i.get("id").toString()).collect(Collectors.toList());
|
||||
}
|
||||
return memberService.listFieldsByMemberIds("id,nick_name", ids);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +394,9 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
|
||||
if (item.getNum() == null || item.getNum() <= 0) {
|
||||
throw new ServiceException(ResultCode.COUPON_ACTIVITY_ITEM_NUM_ERROR);
|
||||
}
|
||||
if (item.getNum() > 2) {
|
||||
throw new ServiceException(ResultCode.COUPON_ACTIVITY_ITEM_NUM_MAX_VALUE_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,36 +183,52 @@ public class CouponServiceImpl extends AbstractPromotionsServiceImpl<CouponMappe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPromotions(Coupon promotions) {
|
||||
if (promotions.getRangeDayType() == null) {
|
||||
super.checkPromotions(promotions);
|
||||
public void checkPromotions(Coupon coupon) {
|
||||
if (coupon.getRangeDayType() == null) {
|
||||
super.checkPromotions(coupon);
|
||||
}
|
||||
//优惠券限制领取数量
|
||||
if (promotions.getCouponLimitNum() < 0) {
|
||||
if (coupon.getCouponLimitNum() < 0) {
|
||||
throw new ServiceException(ResultCode.COUPON_LIMIT_NUM_LESS_THAN_0);
|
||||
}
|
||||
//如果发行数量是0则判断领取限制数量
|
||||
if (promotions.getPublishNum() != 0 && promotions.getCouponLimitNum() > promotions.getPublishNum()) {
|
||||
if (coupon.getPublishNum() != 0 && coupon.getCouponLimitNum() > coupon.getPublishNum()) {
|
||||
throw new ServiceException(ResultCode.COUPON_LIMIT_GREATER_THAN_PUBLISH);
|
||||
}
|
||||
//打折优惠券大于10折
|
||||
boolean discountCoupon = (promotions.getCouponType().equals(CouponTypeEnum.DISCOUNT.name())
|
||||
&& (promotions.getCouponDiscount() < 0 || promotions.getCouponDiscount() > 10));
|
||||
boolean discountCoupon = (coupon.getCouponType().equals(CouponTypeEnum.DISCOUNT.name())
|
||||
&& (coupon.getCouponDiscount() < 0 || coupon.getCouponDiscount() > 10));
|
||||
if (discountCoupon) {
|
||||
throw new ServiceException(ResultCode.COUPON_DISCOUNT_ERROR);
|
||||
}
|
||||
|
||||
//优惠券为固定时间类型
|
||||
if (promotions.getRangeDayType() != null && promotions.getRangeDayType().equals(CouponRangeDayEnum.FIXEDTIME.name())) {
|
||||
long nowTime = DateUtil.getDateline() * 1000;
|
||||
//固定时间的优惠券不能小于当前时间
|
||||
if (promotions.getEndTime().getTime() < nowTime) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_END_TIME_ERROR);
|
||||
}
|
||||
//如果优惠券使用时间类型不合法,抛出异常,抛出异常
|
||||
if (!CouponRangeDayEnum.exist(coupon.getRangeDayType())) {
|
||||
throw new ServiceException(ResultCode.COUPON_RANGE_ERROR);
|
||||
}
|
||||
|
||||
switch (CouponRangeDayEnum.valueOf(coupon.getRangeDayType())) {
|
||||
case FIXEDTIME:
|
||||
//如果优惠券为固定时间,则开始结束时间不能为空
|
||||
if (coupon.getEndTime() == null || coupon.getStartTime() == null) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_TIME_ERROR);
|
||||
}
|
||||
long nowTime = DateUtil.getDateline() * 1000;
|
||||
//固定时间的优惠券不能小于当前时间
|
||||
if (coupon.getEndTime().getTime() < nowTime) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_END_TIME_ERROR);
|
||||
}
|
||||
break;
|
||||
case DYNAMICTIME:
|
||||
//固定时间的优惠券不能小于当前时间
|
||||
if (coupon.getEffectiveDays() == null || coupon.getEffectiveDays() < 0) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_END_TIME_ERROR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
this.checkCouponScope((CouponVO) promotions);
|
||||
this.checkCouponScope((CouponVO) coupon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -112,9 +112,11 @@ public class MemberCouponServiceImpl extends ServiceImpl<MemberCouponMapper, Mem
|
||||
public IPage<MemberCoupon> getMemberCoupons(MemberCouponSearchParams param, PageVO pageVo) {
|
||||
QueryWrapper<MemberCoupon> queryWrapper = param.queryWrapper();
|
||||
Page<MemberCoupon> page = this.page(PageUtil.initPage(pageVo), queryWrapper);
|
||||
if (page.getRecords().stream().anyMatch(i -> i.getEndTime().before(new Date()))) {
|
||||
this.expireInvalidMemberCoupon(param.getMemberId());
|
||||
return this.page(PageUtil.initPage(pageVo), queryWrapper);
|
||||
if (page.getRecords() != null && page.getRecords().size() > 0) {
|
||||
if (page.getRecords().stream().anyMatch(i -> i.getEndTime().before(new Date()))) {
|
||||
this.expireInvalidMemberCoupon(param.getMemberId());
|
||||
return this.page(PageUtil.initPage(pageVo), queryWrapper);
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package cn.lili.modules.promotion.serviceimpl;
|
||||
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.cache.CachePrefix;
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.common.security.context.UserContext;
|
||||
import cn.lili.common.utils.DateUtil;
|
||||
import cn.lili.modules.promotion.entity.dos.CouponActivity;
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
|
||||
import cn.lili.modules.promotion.entity.enums.CouponFrequencyEnum;
|
||||
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
|
||||
import cn.lili.modules.promotion.mapper.MemberCouponSignMapper;
|
||||
import cn.lili.modules.promotion.service.MemberCouponSignService;
|
||||
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.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员优惠券领取标记
|
||||
*
|
||||
* @author liushuai(liushuai711 @ gmail.com)
|
||||
* @version v4.0
|
||||
* @Description:
|
||||
* @since 2023/1/3 18:13
|
||||
*/
|
||||
@Service
|
||||
public class MemberCouponSignServiceImpl extends ServiceImpl<MemberCouponSignMapper, MemberCouponSign> implements MemberCouponSignService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Override
|
||||
public void clean() {
|
||||
LambdaQueryWrapper<MemberCouponSign> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.lt(MemberCouponSign::getInvalidTime, DateUtil.getCurrentDayStartTime());
|
||||
this.baseMapper.delete(queryWrapper);
|
||||
cache.remove(CachePrefix.MEMBER_COUPON_SIGN.getPrefix());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CouponActivityVO> receiveCoupon(List<CouponActivityVO> couponActivity) {
|
||||
List<MemberCouponSign> memberCouponSigns = new ArrayList<>();
|
||||
|
||||
|
||||
//查询当前用户领取标记
|
||||
LambdaQueryWrapper<MemberCouponSign> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(MemberCouponSign::getMemberId, UserContext.getCurrentUser().getId());
|
||||
List<MemberCouponSign> oldMemberCouponSigns = this.list(queryWrapper);
|
||||
|
||||
//定义生效的活动
|
||||
List<CouponActivityVO> assertCouponActivity = new ArrayList<>();
|
||||
|
||||
//生成标记对象
|
||||
couponActivityFor:
|
||||
for (CouponActivityVO activity : couponActivity) {
|
||||
//如果旧的标记中包含记号,则略过
|
||||
for (MemberCouponSign oldMemberCouponSign : oldMemberCouponSigns) {
|
||||
if (oldMemberCouponSign.getCouponActivityId().equals(activity.getId())) {
|
||||
continue couponActivityFor;
|
||||
}
|
||||
}
|
||||
assertCouponActivity.add(activity);
|
||||
|
||||
MemberCouponSign memberCouponSign = new MemberCouponSign();
|
||||
memberCouponSign.setMemberId(UserContext.getCurrentUser().getId());
|
||||
memberCouponSign.setCouponActivityId(activity.getId());
|
||||
memberCouponSign.setInvalidTime(getInvalidTime(activity));
|
||||
memberCouponSigns.add(memberCouponSign);
|
||||
}
|
||||
|
||||
this.saveBatch(memberCouponSigns);
|
||||
return assertCouponActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据活动优惠券获取标记失效时间
|
||||
*
|
||||
* @param activity
|
||||
* @return
|
||||
*/
|
||||
private Date getInvalidTime(CouponActivity activity) {
|
||||
|
||||
//领取周期符合预设
|
||||
if (CouponFrequencyEnum.exist(activity.getCouponFrequencyEnum())) {
|
||||
|
||||
Calendar cal = DateUtil.getCleanCalendar();
|
||||
switch (CouponFrequencyEnum.valueOf(activity.getCouponFrequencyEnum())) {
|
||||
case DAY:
|
||||
return DateUtil.getCurrentDayEndTime();
|
||||
case WEEK:
|
||||
//周一
|
||||
cal.set(Calendar.DAY_OF_WEEK, 2);
|
||||
//去往下周
|
||||
cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) + 1);
|
||||
//减1毫秒上个星期最后一刻
|
||||
cal.set(Calendar.MILLISECOND, -1);
|
||||
return cal.getTime();
|
||||
case MONTH:
|
||||
//日期 1日
|
||||
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||
//下个月
|
||||
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
|
||||
//减少一毫秒去上个月最后一刻
|
||||
cal.set(Calendar.MILLISECOND, -1);
|
||||
|
||||
return cal.getTime();
|
||||
default:
|
||||
|
||||
throw new ServiceException();
|
||||
}
|
||||
} else {
|
||||
throw new ServiceException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.lili.cache.Cache;
|
||||
import cn.lili.common.enums.PromotionTypeEnum;
|
||||
import cn.lili.common.utils.StringUtils;
|
||||
import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
|
||||
@@ -98,7 +99,12 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
|
||||
List<String> categories = skus.stream().map(GoodsSku::getCategoryPath).collect(Collectors.toList());
|
||||
List<String> skuIds = skus.stream().map(GoodsSku::getId).collect(Collectors.toList());
|
||||
List<String> categoriesPath = new ArrayList<>();
|
||||
categories.forEach(i -> categoriesPath.addAll(Arrays.asList(i.split(","))));
|
||||
categories.forEach(i -> {
|
||||
if (StringUtils.isNotEmpty(i)) {
|
||||
categoriesPath.addAll(Arrays.asList(i.split(",")));
|
||||
}
|
||||
}
|
||||
);
|
||||
QueryWrapper<PromotionGoods> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
queryWrapper.and(i -> i.or(j -> j.in(SKU_ID_COLUMN, skuIds))
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -134,10 +135,10 @@ public class SeckillServiceImpl extends AbstractPromotionsServiceImpl<SeckillMap
|
||||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
>>>>>>> origin/master
|
||||
* <<<<<<< HEAD
|
||||
* =======
|
||||
* <<<<<<< HEAD
|
||||
* >>>>>>> origin/master
|
||||
* 通用促销更新
|
||||
* 调用顺序:
|
||||
* 1. checkStatus 检查促销状态
|
||||
@@ -154,11 +155,16 @@ public class SeckillServiceImpl extends AbstractPromotionsServiceImpl<SeckillMap
|
||||
public boolean updatePromotions(Seckill promotions) {
|
||||
this.checkStatus(promotions);
|
||||
this.checkPromotions(promotions);
|
||||
//如果申请结束时间在当前时间之前
|
||||
if (promotions.getApplyEndTime().before(new Date()) || promotions.getApplyEndTime().after(promotions.getStartTime())) {
|
||||
throw new ServiceException(ResultCode.STORE_NAME_EXIST_ERROR);
|
||||
}
|
||||
boolean result = this.updateById(promotions);
|
||||
seckillApplyService.updateSeckillApplyTime(promotions);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新商品索引限时抢购信息
|
||||
*
|
||||
|
||||
@@ -47,5 +47,8 @@ public class StoreIndexStatisticsVO {
|
||||
@ApiModelProperty(value = "未对账结算单数量")
|
||||
private Long waitPayBill;
|
||||
|
||||
@ApiModelProperty(value = "待自提数量")
|
||||
private Long selfPickNum;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -200,7 +200,8 @@ public class IndexStatisticsServiceImpl implements IndexStatisticsService {
|
||||
storeIndexStatisticsVO.setUnDeliveredOrder(orderStatisticsService.orderNum(OrderStatusEnum.UNDELIVERED.name()));
|
||||
//待收货订单数量
|
||||
storeIndexStatisticsVO.setDeliveredOrder(orderStatisticsService.orderNum(OrderStatusEnum.DELIVERED.name()));
|
||||
|
||||
//待自提数量
|
||||
storeIndexStatisticsVO.setSelfPickNum(orderStatisticsService.orderNum(OrderStatusEnum.STAY_PICKED_UP.name()));
|
||||
//待处理退货数量
|
||||
storeIndexStatisticsVO.setReturnGoods(afterSaleStatisticsService.applyNum(AfterSaleTypeEnum.RETURN_GOODS.name()));
|
||||
//待处理退款数量
|
||||
|
||||
@@ -103,6 +103,9 @@ public class Store extends BaseEntity {
|
||||
@ApiModelProperty(value = "默认页面是否开启")
|
||||
private Boolean pageShow;
|
||||
|
||||
@ApiModelProperty(value = "是否开启自提")
|
||||
private Boolean selfPickFlag;
|
||||
|
||||
public Store(Member member) {
|
||||
this.memberId = member.getId();
|
||||
this.memberName = member.getUsername();
|
||||
|
||||
@@ -36,4 +36,7 @@ public class StoreSettingDTO {
|
||||
@ApiModelProperty(value = "默认页面是否开启")
|
||||
private Boolean pageShow;
|
||||
|
||||
@ApiModelProperty(value = "是否开启自提")
|
||||
private Boolean selfPickFlag;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.lili.modules.store.service;
|
||||
|
||||
import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.member.entity.dto.CollectionDTO;
|
||||
import cn.lili.modules.store.entity.dos.Store;
|
||||
import cn.lili.modules.store.entity.dto.*;
|
||||
@@ -9,6 +10,8 @@ import cn.lili.modules.store.entity.vos.StoreVO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 店铺业务层
|
||||
*
|
||||
@@ -117,5 +120,15 @@ public interface StoreService extends IService<Store> {
|
||||
*/
|
||||
void updateStoreCollectionNum(CollectionDTO collectionDTO);
|
||||
|
||||
/**
|
||||
* 重新生成所有店铺
|
||||
*/
|
||||
void storeToClerk();
|
||||
|
||||
/**
|
||||
* 店铺获取该会员的访问记录
|
||||
* @param memberId 会员Id
|
||||
* @return
|
||||
*/
|
||||
List<GoodsSku> getToMemberHistory(String memberId);
|
||||
}
|
||||
@@ -25,6 +25,8 @@ import cn.lili.modules.store.service.StoreDetailService;
|
||||
import cn.lili.modules.store.service.StoreService;
|
||||
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
|
||||
import cn.lili.rocketmq.tags.GoodsTagsEnum;
|
||||
import cn.lili.rocketmq.tags.MemberTagsEnum;
|
||||
import cn.lili.rocketmq.tags.StoreTagsEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
@@ -99,6 +101,9 @@ public class StoreDetailServiceImpl extends ServiceImpl<StoreDetailMapper, Store
|
||||
if (result) {
|
||||
this.updateStoreGoodsInfo(store);
|
||||
}
|
||||
String destination = rocketmqCustomProperties.getStoreTopic() + ":" + StoreTagsEnum.EDIT_STORE_SETTING.name();
|
||||
//发送订单变更mq消息
|
||||
rocketMQTemplate.asyncSend(destination, store, RocketmqSendCallbackBuilder.commonCallback());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,21 @@ 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.common.security.AuthUser;
|
||||
import cn.lili.common.security.context.UserContext;
|
||||
import cn.lili.common.utils.BeanUtil;
|
||||
import cn.lili.common.vo.PageVO;
|
||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||
import cn.lili.modules.goods.service.GoodsService;
|
||||
import cn.lili.modules.goods.service.GoodsSkuService;
|
||||
import cn.lili.modules.member.entity.dos.Clerk;
|
||||
import cn.lili.modules.member.entity.dos.FootPrint;
|
||||
import cn.lili.modules.member.entity.dos.Member;
|
||||
import cn.lili.modules.member.entity.dto.ClerkAddDTO;
|
||||
import cn.lili.modules.member.entity.dto.CollectionDTO;
|
||||
import cn.lili.modules.member.service.ClerkService;
|
||||
import cn.lili.modules.member.service.FootprintService;
|
||||
import cn.lili.modules.member.service.MemberService;
|
||||
import cn.lili.modules.store.entity.dos.Store;
|
||||
import cn.lili.modules.store.entity.dos.StoreDetail;
|
||||
@@ -27,12 +32,15 @@ import cn.lili.modules.store.mapper.StoreMapper;
|
||||
import cn.lili.modules.store.service.StoreDetailService;
|
||||
import cn.lili.modules.store.service.StoreService;
|
||||
import cn.lili.mybatis.util.PageUtil;
|
||||
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
|
||||
import cn.lili.rocketmq.tags.StoreTagsEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.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.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -66,12 +74,24 @@ public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements
|
||||
*/
|
||||
@Autowired
|
||||
private GoodsService goodsService;
|
||||
|
||||
@Autowired
|
||||
private GoodsSkuService goodsSkuService;
|
||||
/**
|
||||
* 店铺详情
|
||||
*/
|
||||
@Autowired
|
||||
private StoreDetailService storeDetailService;
|
||||
|
||||
@Autowired
|
||||
private RocketmqCustomProperties rocketmqCustomProperties;
|
||||
|
||||
@Autowired
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Autowired
|
||||
private FootprintService footprintService;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@@ -159,7 +179,11 @@ public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements
|
||||
if (result) {
|
||||
storeDetailService.updateStoreGoodsInfo(store);
|
||||
}
|
||||
String destination = rocketmqCustomProperties.getStoreTopic() + ":" + StoreTagsEnum.EDIT_STORE_SETTING.name();
|
||||
//发送订单变更mq消息
|
||||
rocketMQTemplate.asyncSend(destination, store, RocketmqSendCallbackBuilder.commonCallback());
|
||||
}
|
||||
|
||||
cache.remove(CachePrefix.STORE.getPrefix() + storeEditDTO.getStoreId());
|
||||
return store;
|
||||
}
|
||||
@@ -352,6 +376,18 @@ public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements
|
||||
clerkService.saveBatch(clerkList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GoodsSku> getToMemberHistory(String memberId) {
|
||||
AuthUser currentUser = UserContext.getCurrentUser();
|
||||
List<String> skuIdList = new ArrayList<>();
|
||||
for (FootPrint footPrint : footprintService.list(new LambdaUpdateWrapper<FootPrint>().eq(FootPrint::getStoreId, currentUser.getStoreId()).eq(FootPrint::getMemberId, memberId))) {
|
||||
if(footPrint.getSkuId() != null){
|
||||
skuIdList.add(footPrint.getSkuId());
|
||||
}
|
||||
}
|
||||
return goodsSkuService.getGoodsSkuByIdFromCache(skuIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录操作的店铺
|
||||
*
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.lili.mybatis;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 租户超级类
|
||||
*
|
||||
* @author Chopper
|
||||
* @version v1.0
|
||||
* @since 2020/8/20 14:34
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public abstract class BaseTenantEntity extends BaseEntity {
|
||||
|
||||
@ApiModelProperty(value = "租户id", hidden = true)
|
||||
private String tenantId;
|
||||
|
||||
}
|
||||
@@ -23,6 +23,10 @@ public enum MemberTagsEnum {
|
||||
* 会员提现
|
||||
*/
|
||||
MEMBER_WITHDRAWAL("会员提现"),
|
||||
/**
|
||||
* 会员信息更改
|
||||
*/
|
||||
MEMBER_INFO_EDIT("会员信息更改"),
|
||||
/**
|
||||
* 会员积分变动
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.lili.rocketmq.tags;
|
||||
|
||||
/**
|
||||
* @author chc
|
||||
* @since 2022/6/2114:46
|
||||
*/
|
||||
public enum StoreTagsEnum {
|
||||
|
||||
EDIT_STORE_SETTING("修改商家设置");
|
||||
|
||||
private final String description;
|
||||
|
||||
StoreTagsEnum(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user