This commit is contained in:
pikachu1995@126.com
2023-01-05 15:31:22 +08:00
268 changed files with 8555 additions and 1935 deletions

View File

@@ -153,7 +153,15 @@ public interface Cache<T> {
* @param pattern 模糊key
* @return 缓存中的数据
*/
List<String> keys(String pattern);
List<Object> keys(String pattern);
/**
* 原生阻塞keys 不推荐使用
*
* @param pattern 模糊key
* @return 缓存中的数据
*/
List<Object> keysBlock(String pattern);
//-----------------------------------------------用于特殊场景redis去重计数---------------------------------------------
@@ -211,11 +219,12 @@ public interface Cache<T> {
* @return 计数器结果
*/
Long incr(String key, long liveTime);
/**
* redis 计数器 累加
* 注到达liveTime之后该次增加取消即自动-1而不是redis值为空
*
* @param key 为累计的key同一key每次调用则值 +1
* @param key 为累计的key同一key每次调用则值 +1
* @return 计数器结果
*/
Long incr(String key);

View File

@@ -473,13 +473,25 @@ public enum CachePrefix {
* 店铺分类
*/
STORE_CATEGORY,
/**
* 用户菜单
*/
MENU_USER_ID,
/**
* 用户菜单
* <p>
* 这个缓存并非永久缓存而是300秒缓存也就是说修改用户关联的部门关联的角色
* 部门关联的角色角色关联的菜单等等最多需要5分钟才能生效
*/
STORE_MENU_USER_ID,
/**
* 用户菜单
*/
USER_MENU,
/**
* 用户菜单
*/
STORE_USER_MENU,
/**
* 订单暂时缓存
*/
@@ -487,7 +499,16 @@ public enum CachePrefix {
/**
* 敏感词
*/
SENSITIVE;
SENSITIVE,
/**
* 扫码登录
* @param str
* @return
*/
QR_CODE_LOGIN_SESSION
;
public static String removePrefix(String str) {

View File

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

View File

@@ -90,14 +90,13 @@ public class RedisCache implements Cache {
*/
@Override
public void vagueDel(Object key) {
Set<Object> keys = redisTemplate.keys(key + "*");
List keys = this.keys(key + "*");
redisTemplate.delete(keys);
}
@Override
public void clear() {
Set keys = redisTemplate.keys("*");
List keys = this.keys("*");
redisTemplate.delete(keys);
}
@@ -133,8 +132,8 @@ public class RedisCache implements Cache {
* @return 模糊匹配key
*/
@Override
public List<String> keys(String pattern) {
List<String> keys = new ArrayList<>();
public List<Object> keys(String pattern) {
List<Object> keys = new ArrayList<>();
this.scan(pattern, item -> {
//符合条件的key
String key = new String(item, StandardCharsets.UTF_8);
@@ -143,6 +142,13 @@ public class RedisCache implements Cache {
return keys;
}
@Override
public List<Object> keysBlock(String pattern) {
Set<Object> set = redisTemplate.keys(pattern);
List<Object> list = new ArrayList<>();
list.addAll(set);
return list;
}
/**
* scan 实现

View File

@@ -45,24 +45,23 @@ public class LimitInterceptor {
@Before("@annotation(limitPointAnnotation)")
public void interceptor(LimitPoint limitPointAnnotation) {
LimitTypeEnums limitTypeEnums = limitPointAnnotation.limitType();
String name = limitPointAnnotation.name();
String key;
int limitPeriod = limitPointAnnotation.period();
int limitCount = limitPointAnnotation.limit();
switch (limitTypeEnums) {
case CUSTOMER:
key = limitPointAnnotation.key();
break;
default:
key = limitPointAnnotation.key() + IpUtils
.getIpAddress(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
if (limitTypeEnums == LimitTypeEnums.CUSTOMER) {
key = limitPointAnnotation.key();
} else {
key = limitPointAnnotation.key() + IpUtils
.getIpAddress(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
}
ImmutableList<String> keys = ImmutableList.of(StringUtils.join(limitPointAnnotation.prefix(), key));
try {
Number count = redisTemplate.execute(limitScript, keys, limitCount, limitPeriod);
assert count != null;
log.info("限制请求{}, 当前请求{},缓存key{}", limitCount, count.intValue(), key);
//如果缓存里没有值,或者他的值小于限制频率
if (count.intValue() >= limitCount) {
if (count.intValue() > limitCount) {
throw new ServiceException(ResultCode.LIMIT_ERROR);
}
}
@@ -72,6 +71,7 @@ public class LimitInterceptor {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("限流异常", e);
throw new ServiceException(ResultCode.ERROR);
}
}

View File

@@ -18,7 +18,12 @@ public @interface PreventDuplicateSubmissions {
/**
* 过期时间
* 过期时间 默认3秒即3秒内无法重复点击。
*/
long expire() default 3;
/**
* 用户间隔离默认false。
* 如果为true则全局限制为true需要用户登录状态否则则是全局隔离
*/
boolean userIsolation() default false;
}

View File

@@ -1,9 +1,19 @@
package cn.lili.common.aop.interceptor;
/**
* 防重复提交业务
*
* @author Chopper
* @version v1.0
* 2022-01-25 09:20
*/
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
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 lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
@@ -15,13 +25,6 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 防重复提交业务
*
* @author Chopper
* @version v1.0
* 2022-01-25 09:20
*/
@Aspect
@Component
@Slf4j
@@ -35,9 +38,11 @@ public class PreventDuplicateSubmissionsInterceptor {
public void interceptor(PreventDuplicateSubmissions preventDuplicateSubmissions) {
try {
Long count = cache.incr(getParams(), preventDuplicateSubmissions.expire());
//如果超过2或者设置的参数则表示重复提交了
if (count.intValue() >= 2) {
String redisKey = getParams(preventDuplicateSubmissions.userIsolation());
Long count = cache.incr(redisKey, preventDuplicateSubmissions.expire());
log.debug("防重复提交params-{},value-{}", redisKey, count);
//如果超过0或者设置的参数则表示重复提交了
if (count.intValue() > 0) {
throw new ServiceException(ResultCode.LIMIT_ERROR);
}
}
@@ -47,6 +52,7 @@ public class PreventDuplicateSubmissionsInterceptor {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("防重复提交拦截器异常", e);
throw new ServiceException(ResultCode.ERROR);
}
}
@@ -54,12 +60,33 @@ public class PreventDuplicateSubmissionsInterceptor {
/**
* 获取表单参数
*
* @return
* @param userIsolation 用户是否隔离
* @return 计数器key
*/
private String getParams() {
private String getParams(Boolean userIsolation) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
StringBuilder stringBuilder = new StringBuilder();
//拼接请求地址
stringBuilder.append(request.getRequestURI());
//参数不为空则拼接参数
if (!request.getParameterMap().isEmpty()) {
stringBuilder.append(JSONUtil.toJsonStr(request.getParameterMap()));
}
//用户隔离设置为开启,则选择当前用回顾
if (userIsolation) {
AuthUser authUser = UserContext.getCurrentUser();
//用户为空则发出警告但不拼接否则拼接用户id
if (authUser == null) {
log.warn("user isolation settings are on,but current user is null");
}
// 不为空则拼接用户id
else {
stringBuilder.append(authUser.getId());
}
}
//请求地址
return request.getRequestURI() + UserContext.getCurrentUser().getId() + UserContext.getCurrentUser().getUsername();
return stringBuilder.toString();
}

View File

@@ -37,6 +37,7 @@ public enum ResultCode {
LIMIT_ERROR(1003, "访问过于频繁,请稍后再试"),
ILLEGAL_REQUEST_ERROR(1004, "非法请求,请重新刷新页面操作"),
IMAGE_FILE_EXT_ERROR(1005, "不支持图片格式"),
FILE_NOT_EXIST_ERROR(1011, "上传文件不能为空"),
FILE_TYPE_NOT_SUPPORT(1010, "不支持上传的文件类型!"),
PLATFORM_NOT_SUPPORTED_IM(1006, "平台未开启IM"),
STORE_NOT_SUPPORTED_IM(1007, "店铺未开启IM"),
@@ -79,6 +80,8 @@ public enum ResultCode {
MUST_HAVE_SALES_MODEL(11022, "销售模式为批发时必须要有批发规则!"),
HAVE_INVALID_SALES_MODEL(11023, "批发规则存在小于等于0的无效数据"),
MUST_HAVE_GOODS_SKU_VALUE(11024, "规格值不能为空!"),
DO_NOT_MATCH_WHOLESALE(11025, "批发商品购买数量不能低于起拍量!"),
GOODS_PARAMS_ERROR(11013, "商品参数错误,刷新后重试"),
PHYSICAL_GOODS_NEED_TEMP(11014, "实物商品需选择配送模板"),
@@ -137,7 +140,14 @@ public enum ResultCode {
USER_CONNECT_BANDING_ERROR(20023, "当前联合登陆方式,已绑定其他账号,需进行解绑操作"),
USER_CONNECT_NOT_EXIST_ERROR(20024, "暂无联合登陆信息,无法实现一键注册功能,请点击第三方登录进行授权"),
USER_POINTS_ERROR(20024, "用户积分不足"),
CLERK_SUPPER(20025, "店主无法操作"),
CLERK_SAVE_ERROR(20026, "店员保存失败"),
CLERK_NOT_FOUND_ERROR(20027, "店员不存在"),
USER_STATUS_ERROR(20028, "用户已禁用"),
CLERK_USER_ERROR(20029, "此账户已经绑定其他店铺"),
CLERK_ALREADY_EXIT_ERROR(20030, "店员已经存在"),
CLERK_DISABLED_ERROR(20031, "店员已禁用"),
CLERK_CURRENT_SUPPER(20032, "无法删除当前登录店员"),
/**
* 权限
*/
@@ -146,6 +156,10 @@ public enum ResultCode {
PERMISSION_MENU_ROLE_ERROR(21003, "菜单已绑定角色,请先删除或编辑角色"),
PERMISSION_DEPARTMENT_DELETE_ERROR(21004, "部门已经绑定管理员,请先删除或编辑管理员"),
PERMISSION_BEYOND_TEN(21005, "最多可以设置10个角色"),
PERMISSION_NOT_FOUND_ERROR(21006, "部门不存在"),
PERMISSION_ROLE_NOT_FOUND_ERROR(21007, "角色不存在"),
PERMISSION_CLERK_BAND_ERROR(21008, "此手机号码已绑定其他店铺 "),
/**
* 分销
@@ -278,11 +292,6 @@ public enum ResultCode {
COUPON_RECEIVE_ERROR(41005, "当前优惠券已经被领取完了,下次要早点来哦"),
COUPON_NUM_INSUFFICIENT_ERROR(41006, "优惠券剩余领取数量不足"),
COUPON_NOT_EXIST(41007, "当前优惠券不存在"),
COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"),
COUPON_ACTIVITY_NOT_EXIST(410022, "当前优惠券活动不存在"),
COUPON_SAVE_ERROR(41020, "保存优惠券失败"),
COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"),
COUPON_DELETE_ERROR(41021, "删除优惠券失败"),
COUPON_LIMIT_NUM_LESS_THAN_0(41008, "领取限制数量不能为负数"),
COUPON_LIMIT_GREATER_THAN_PUBLISH(41009, "领取限制数量超出发行数量"),
COUPON_DISCOUNT_ERROR(41010, "优惠券折扣必须小于10且大于0"),
@@ -293,6 +302,15 @@ public enum ResultCode {
COUPON_MEMBER_NOT_EXIST(41015, "没有当前会员优惠券"),
COUPON_MEMBER_STATUS_ERROR(41016, "当前会员优惠券已过期/作废无法变更状态!"),
SPECIAL_CANT_USE(41019, "特殊商品不能使用优惠券,不能使用"),
COUPON_SAVE_ERROR(41020, "保存优惠券失败"),
COUPON_DELETE_ERROR(41021, "删除优惠券失败"),
COUPON_ACTIVITY_NOT_EXIST(41022, "当前优惠券活动不存在"),
COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"),
COUPON_ACTIVITY_MAX_NUM(41024, "优惠券活动赠券数量最多为3"),
COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"),
/**
* 拼团
@@ -385,11 +403,12 @@ public enum ResultCode {
STORE_NOT_EXIST(50001, "此店铺不存在"),
STORE_NAME_EXIST_ERROR(50002, "店铺名称已存在!"),
STORE_APPLY_DOUBLE_ERROR(50003, "已有店铺,无需重复申请!"),
STORE_APPLY_DOUBLE_ERROR(50003, "经拥有店铺!"),
STORE_NOT_OPEN(50004, "该会员未开通店铺"),
STORE_NOT_LOGIN_ERROR(50005, "未登录店铺"),
STORE_CLOSE_ERROR(50006, "店铺关闭,请联系管理员"),
FREIGHT_TEMPLATE_NOT_EXIST(50010, "当前模版不存在"),
STORE_STATUS_ERROR(50011, "店铺状态异常,无法申请"),
/**
* 结算单

View File

@@ -21,9 +21,9 @@ public class TransactionCommitSendMQEvent extends ApplicationEvent {
private final String tag;
@Getter
private final String message;
private final Object message;
public TransactionCommitSendMQEvent(Object source, String topic, String tag, String message) {
public TransactionCommitSendMQEvent(Object source, String topic, String tag, Object message) {
super(source);
this.topic = topic;
this.tag = tag;

View File

@@ -18,7 +18,7 @@ import javax.validation.ConstraintViolationException;
import java.util.List;
/**
* 全局异常异常处理
* 异常处理
*
* @author Chopper
*/
@@ -74,6 +74,15 @@ public class GlobalControllerExceptionHandler {
}
return ResultUtil.error(ResultCode.ERROR.code(), errorMsg);
}
/*
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public ResultMessage<Object> constraintExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
log.error("全局异常[RuntimeException]:", e);
return ResultUtil.error(001, e.getMessage());
}*/
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)

View File

@@ -16,21 +16,21 @@ public class SmsTemplateProperties {
/**
* 登录
*/
private String lOGIN = "SMS_205755300";
private String lOGIN = "SMS_185821482";
/**
* 注册
*/
private String REGISTER = "SMS_205755298";
private String REGISTER = "SMS_185821482";
/**
* 找回密码
*/
private String FIND_USER = "SMS_205755301";
private String FIND_USER = "SMS_185821482";
/**
* 设置密码
*/
private String UPDATE_PASSWORD = "SMS_205755297";
private String UPDATE_PASSWORD = "SMS_185821482";
/**
* 设置支付密码
*/
private String WALLET_PASSWORD = "SMS_205755297";
private String WALLET_PASSWORD = "SMS_185821482";
}

View File

@@ -24,8 +24,7 @@ public class VerificationCodeProperties {
/**
* 水印
*/
private String watermark = "LILI-SHOP";
private String watermark = "";
/**
* 干扰数量 最大数量
*/

View File

@@ -51,6 +51,11 @@ public class AuthUser implements Serializable {
* storeId
*/
private String storeId;
/**
* 如果角色是商家则存在此店铺id字段
* clerkId
*/
private String clerkId;
/**
* 如果角色是商家,则存在此店铺名称字段
@@ -79,4 +84,14 @@ public class AuthUser implements Serializable {
this.isSuper = isSuper;
this.nickName = nickName;
}
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;
this.isSuper = isSuper;
this.nickName = nickName;
this.clerkId = clerkId;
this.face = face;
}
}

View File

@@ -1,6 +1,7 @@
package cn.lili.common.security.context;
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;
@@ -60,10 +61,13 @@ public class UserContext {
*/
public static AuthUser getAuthUser(Cache cache, String accessToken) {
try {
if (cache.keys("*" + accessToken).isEmpty()) {
AuthUser authUser = getAuthUser(accessToken);
assert authUser != null;
if (!cache.hasKey(CachePrefix.ACCESS_TOKEN.getPrefix(authUser.getRole()) + accessToken)) {
throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
}
return getAuthUser(accessToken);
return authUser;
} catch (Exception e) {
return null;
}

View File

@@ -181,7 +181,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
//将resultMap转换为json字符串
String resultStr = JSONUtil.toJsonStr(resultMap);
//将json字符串转换为字节
final ByteArrayInputStream resultBIS = new ByteArrayInputStream(resultStr.getBytes());
final ByteArrayInputStream resultBIS = new ByteArrayInputStream(resultStr.getBytes(StandardCharsets.UTF_8));
//实现接口
return new ServletInputStream() {

View File

@@ -17,7 +17,7 @@ public class SecretKeyUtil {
public static SecretKey generalKey() {
//自定义
byte[] encodedKey = Base64.decodeBase64("cuAihCz53DZRjZwbsGcZJ2Ai6At+T142uphtJMsk7iQ=");
javax.crypto.SecretKey key = Keys.hmacShaKeyFor(encodedKey);
SecretKey key = Keys.hmacShaKeyFor(encodedKey);
return key;
}

View File

@@ -34,9 +34,9 @@ public class TokenUtil {
/**
* 构建token
*
* @param username 主体
* @param claim 私有声明
* @param longTerm 长时间特殊token 如:移动端,微信小程序等
* @param username 主体
* @param claim 私有声明
* @param longTerm 长时间特殊token 如:移动端,微信小程序等
* @param userEnums 用户枚举
* @return TOKEN
*/
@@ -62,7 +62,7 @@ public class TokenUtil {
* 刷新token
*
* @param oldRefreshToken 刷新token
* @param userEnums 用户枚举
* @param userEnums 用户枚举
* @return token
*/
public Token refreshToken(String oldRefreshToken, UserEnums userEnums) {

View File

@@ -55,7 +55,7 @@ public class IpUtils {
}
}
if ("0:0:0:0:0:0:0:1".equals(ip)) {
ip = "127.0.0.1";
ip = "106.124.130.167";
}
return ip;
}

View File

@@ -5,6 +5,7 @@ import java.util.regex.Pattern;
/**
* 用户名验证工具类
*
* @author Chopper
*/
public class RegularUtil {
@@ -20,21 +21,88 @@ public class RegularUtil {
*/
private static final Pattern EMAIL = Pattern.compile("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$");
public static boolean mobile(String v){
//sql正则
static Pattern sqlPattern = Pattern.compile("(select|update|and|delete|insert|trancate|char|substr|ascii|declare|exec|count|master|into|drop|execute" +
// 可能涉及英文查询参数问题
// "|in|not in exists|not exists" +
// "|between|not between" +
// "|like|not like" +
// "|is null|is not null" +
")", Pattern.CASE_INSENSITIVE);
//符号正则
static Pattern symbolPattern = Pattern.compile("[\\s~·`!@#¥$%^……&*()\\-——\\-_=+【\\[\\]】{{}\\|、\\\\;:'“”\",《<。.》>、/?]");
/**
* 校验手机号
*
* @param v
* @return
*/
public static boolean mobile(String v) {
Matcher m = MOBILE.matcher(v);
if(m.matches()){
if (m.matches()) {
return true;
}
return false;
}
public static boolean email(String v){
//校验邮箱
public static boolean email(String v) {
Matcher m = EMAIL.matcher(v);
if(m.matches()){
if (m.matches()) {
return true;
}
return false;
}
/**
* 搜索参数过滤
*
* @param str 字符串
* @return 过滤后的字符串
*/
public static String replace(String str) {
return symbolReplace(sqlReplace(str));
}
/**
* 过滤sql关键字
*
* @param str 字符串
* @return 过滤后的字符串
*/
public static String sqlReplace(String str) {
if (StringUtils.isEmpty(str)) {
return "";
}
Matcher sqlMatcher = sqlPattern.matcher(str);
return sqlMatcher.replaceAll("");
}
/**
* 符号过滤
*
* @param str 字符串
* @return 过滤后的字符串
*/
public static String symbolReplace(String str) {
if (StringUtils.isEmpty(str)) {
return "";
}
Matcher symbolMatcher = symbolPattern.matcher(str);
return symbolMatcher.replaceAll("");
}
public static void main(String[] args) {
System.out.println(replace("selectSELECTINORNOTIN123阿松大asdfa!@#$%^&&*()_+{}[]>?").trim());
}
}

View File

@@ -98,7 +98,7 @@ public abstract class BaseElasticsearchService {
log.info(" whether all of the nodes have acknowledged the request : {}", createIndexResponse.isAcknowledged());
log.info(" Indicates whether the requisite number of shard copies were started for each shard in the index before timing out :{}", createIndexResponse.isShardsAcknowledged());
} catch (Exception e) {
log.error("创建索引错误",e);
log.error("创建索引错误", e);
throw new ElasticsearchException("创建索引 {" + index + "} 失败:" + e.getMessage());
}
}
@@ -339,8 +339,7 @@ public abstract class BaseElasticsearchService {
" }\n" +
" }\n";
PutMappingRequest request = new PutMappingRequest(index)
.source(source, XContentType.JSON);
PutMappingRequest request = new PutMappingRequest(index).source(source, XContentType.JSON);
CountDownLatch latch = new CountDownLatch(1);
client.indices().putMappingAsync(
request,
@@ -445,7 +444,7 @@ public abstract class BaseElasticsearchService {
try {
searchResponse = client.search(searchRequest, COMMON_OPTIONS);
} catch (IOException e) {
log.error("es 搜索错误",e);
log.error("es 搜索错误", e);
}
return searchResponse;
}

View File

@@ -77,7 +77,11 @@ public class AuthConfig {
/**
* 针对国外服务可以单独设置代理
* HttpConfig config = new HttpConfig();
<<<<<<< HEAD
* config.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("106.124.130.167", 10080)));
=======
* config.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080)));
>>>>>>> ae0c4aea12996d3d72eca7c6ccdc97922373e4d7
* config.setTimeout(15000);
*
* @since 1.15.5

View File

@@ -8,7 +8,9 @@ import cn.lili.cache.CachePrefix;
import cn.lili.common.context.ThreadContextHolder;
import cn.lili.common.enums.ClientTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.token.Token;
@@ -29,11 +31,13 @@ import cn.lili.modules.system.entity.dto.connect.WechatConnectSetting;
import cn.lili.modules.system.entity.dto.connect.dto.WechatConnectSettingItem;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.rocketmq.tags.MemberTagsEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -66,6 +70,14 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
private MemberTokenGenerate memberTokenGenerate;
@Autowired
private Cache cache;
/**
* RocketMQ 配置
*/
@Autowired
private RocketmqCustomProperties rocketmqCustomProperties;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -235,6 +247,8 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
memberService.save(newMember);
newMember = memberService.findByUsername(newMember.getUsername());
bindMpMember(openId, unionId, newMember);
// 发送会员注册信息
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("new member register", rocketmqCustomProperties.getMemberTopic(), MemberTagsEnum.MEMBER_REGISTER.name(), newMember));
return memberTokenGenerate.createToken(newMember, true);
}
@@ -262,9 +276,9 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
* 这样微信小程序注册之后其他app 公众号页面,都可以实现绑定自动登录功能
* </p>
*
* @param openId 微信openid
* @param unionId 微信unionid
* @param member 会员
* @param openId 微信openid
* @param unionId 微信unionid
* @param member 会员
*/
private void bindMpMember(String openId, String unionId, Member member) {

View File

@@ -47,9 +47,9 @@ public class AuthChecker {
if (!GlobalAuthUtils.isHttpProtocol(redirectUri) && !GlobalAuthUtils.isHttpsProtocol(redirectUri)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, connectAuth);
}
//支付宝在创建回调地址时不允许使用localhost或者127.0.0.1
//支付宝在创建回调地址时不允许使用localhost或者106.124.130.167
if (ConnectAuthEnum.ALIPAY == connectAuth && GlobalAuthUtils.isLocalHost(redirectUri)) {
//The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
//The redirect uri of alipay is forbidden to use localhost or 106.124.130.167
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, connectAuth);
}
}

View File

@@ -171,7 +171,7 @@ public class GlobalAuthUtils {
* @return true: 本地主机(域名), false: 非本地主机(域名)
*/
public static boolean isLocalHost(String url) {
return StringUtils.isEmpty(url) || url.contains("127.0.0.1") || url.contains("localhost");
return StringUtils.isEmpty(url) || url.contains("106.124.130.167") || url.contains("localhost");
}

View File

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

View File

@@ -20,8 +20,8 @@ public interface DistributionOrderMapper extends BaseMapper<DistributionOrder> {
* @param settleCycle 时间
*/
@Update("UPDATE li_distribution AS d " +
"SET d.can_rebate =(d.can_rebate +(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_order_status = #{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} AND dorder.distribution_id = d.id ))" +
",d.commission_frozen =(d.commission_frozen -(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_order_status = #{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} AND dorder.distribution_id = d.id ) )")
"SET d.can_rebate =(ifnull(d.can_rebate,0) +(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_order_status = #{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} AND dorder.distribution_id = d.id ))" +
",d.commission_frozen =(ifnull(d.commission_frozen,0) -(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_order_status = #{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} AND dorder.distribution_id = d.id ) )")
void rebate(String distributionOrderStatus, DateTime settleCycle);
}
}

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
package cn.lili.modules.file.plugin.impl;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.file.entity.enums.OssEnum;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.system.entity.dto.OssSetting;
@@ -62,10 +64,9 @@ public class MinioFilePlugin implements FilePlugin {
public String pathUpload(String filePath, String key) {
try {
return this.inputStreamUpload(new FileInputStream(filePath), key);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
return null;
}
@Override
@@ -77,18 +78,15 @@ public class MinioFilePlugin implements FilePlugin {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucket).stream(inputStream, inputStream.available(), 5 * 1024 * 1024)
.object(key)
.contentType("image/png")
.contentType("image/png" )
.build();
client.putObject(putObjectArgs);
} catch (ErrorResponseException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
log.error("上传失败2", e);
return null;
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
//拼接出可访问的url地址
return ossSetting.getM_endpoint() + "/" + bucket + "/" + key;
return ossSetting.getM_frontUrl() + "/" + bucket + "/" + key;
}
@@ -125,12 +123,14 @@ public class MinioFilePlugin implements FilePlugin {
//创建bucket
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(ossSetting.getM_bucketName()).build();
this.minioClient.makeBucket(makeBucketArgs);
setBucketPolicy(this.minioClient, ossSetting.getM_bucketName(), "read-write");
setBucketPolicy(this.minioClient, ossSetting.getM_bucketName(), "read-write" );
log.info("创建minio桶成功{}", ossSetting.getM_bucketName());
}
} catch (Exception e) {
e.printStackTrace();
//晴空配置
minioClient = null;
log.error("创建[{}]bucket失败", ossSetting.getM_bucketName());
throw new ServiceException(ResultCode.OSS_DELETE_ERROR, e.getMessage());
}
}
}
@@ -153,7 +153,7 @@ public class MinioFilePlugin implements FilePlugin {
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
break;
case "read-write":
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).region("public").config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).region("public" ).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
break;
case "none":
default:

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.mybatis.util.PageUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.SearchVO;
import cn.lili.modules.file.entity.File;
@@ -12,7 +13,6 @@ import cn.lili.modules.file.mapper.FileMapper;
import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.file.plugin.FilePluginFactory;
import cn.lili.modules.file.service.FileService;
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;

View File

@@ -111,7 +111,7 @@ public class DraftGoods extends BaseEntity {
private String goodsVideo;
@ApiModelProperty(value = "是否为推荐商品")
private boolean recommend;
private Boolean recommend;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum

View File

@@ -6,6 +6,7 @@ import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dto.DraftGoodsDTO;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
@@ -13,7 +14,6 @@ import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.enums.GoodsTypeEnum;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.xkcoding.http.util.StringUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -148,7 +148,6 @@ public class Goods extends BaseEntity {
private String goodsType;
@ApiModelProperty(value = "商品参数json", hidden = true)
@JsonIgnore
private String params;
@@ -196,10 +195,40 @@ public class Goods extends BaseEntity {
if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) {
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR);
}
sku.values().forEach(i -> {
if (CharSequenceUtil.isBlank(i.toString())) {
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU_VALUE);
}
});
}
}
public Goods(DraftGoodsDTO goodsDTO) {
this.goodsName = goodsDTO.getGoodsName();
this.categoryPath = goodsDTO.getCategoryPath();
this.storeCategoryPath = goodsDTO.getStoreCategoryPath();
this.brandId = goodsDTO.getBrandId();
this.templateId = goodsDTO.getTemplateId();
this.recommend = goodsDTO.getRecommend();
this.sellingPoint = goodsDTO.getSellingPoint();
this.salesModel = goodsDTO.getSalesModel();
this.goodsUnit = goodsDTO.getGoodsUnit();
this.intro = goodsDTO.getIntro();
this.mobileIntro = goodsDTO.getMobileIntro();
this.goodsVideo = goodsDTO.getGoodsVideo();
this.price = goodsDTO.getPrice();
if (goodsDTO.getGoodsParamsDTOList() != null && goodsDTO.getGoodsParamsDTOList().isEmpty()) {
this.params = JSONUtil.toJsonStr(goodsDTO.getGoodsParamsDTOList());
}
//如果立即上架则
this.marketEnable = GoodsStatusEnum.DOWN.name();
this.goodsType = goodsDTO.getGoodsType();
this.grade = 100D;
}
public String getIntro() {
if (CharSequenceUtil.isNotEmpty(intro)) {
return HtmlUtil.unescape(intro);

View File

@@ -23,6 +23,8 @@ public class Wholesale extends BaseIdEntity {
private String goodsId;
@ApiModelProperty(value = "SkuID")
private String skuId;
@ApiModelProperty(value = "模版id")
private String templateId;
@ApiModelProperty(value = "数量")
private Integer num;
@ApiModelProperty(value = "金额")

View File

@@ -30,4 +30,10 @@ public class DraftGoodsDTO extends DraftGoods {
@Valid
private List<Map<String, Object>> skuList;
/**
* 批发商品规则
*/
@ApiModelProperty(value = "批发商品规则")
private List<WholesaleDTO> wholesaleList;
}

View File

@@ -1,6 +1,6 @@
package cn.lili.modules.goods.entity.dto;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.modules.goods.entity.enums.DraftGoodsSaveType;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiModelProperty;
@@ -26,7 +26,7 @@ public class DraftGoodsSearchParams extends GoodsSearchParams {
@Override
public <T> QueryWrapper<T> queryWrapper() {
QueryWrapper<T> queryWrapper = super.queryWrapper();
if (StrUtil.isNotEmpty(saveType)) {
if (CharSequenceUtil.isNotEmpty(saveType)) {
queryWrapper.eq("save_type", saveType);
}
return queryWrapper;

View File

@@ -0,0 +1,67 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.Category;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* 商品导入DTO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoodsImportDTO {
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ApiModelProperty(value = "商品卖点")
private String sellingPoint;
@ApiModelProperty(value = "商品分类")
private Category category;
@ApiModelProperty(value = "运费模板")
private String template;
@ApiModelProperty(value = "计量单位")
private String goodsUnit;
@ApiModelProperty(value = "发布状态")
private Boolean release;
@ApiModelProperty(value = "商品图片")
private List<Map<String, String>> images;
private List<String> goodsGalleryList;
@ApiModelProperty(value = "成本价")
private Double cost;
@ApiModelProperty(value = "销售价")
private Double price;
@ApiModelProperty(value = "库存")
private Integer quantity;
@ApiModelProperty(value = "重量")
private Double weight;
@ApiModelProperty(value = "货号")
private String sn;
@ApiModelProperty(value = "详情")
private String intro;
@ApiModelProperty(value = "规格项")
private String skuKey;
@ApiModelProperty(value = "规格值")
private String skuValue;
}

View File

@@ -1,14 +1,18 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.common.validation.EnumValue;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.enums.GoodsTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import lombok.*;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -20,6 +24,9 @@ import java.util.Map;
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GoodsOperationDTO implements Serializable {
private static final long serialVersionUID = -509667581371776913L;
@@ -116,15 +123,57 @@ public class GoodsOperationDTO implements Serializable {
@Valid
private List<Map<String, Object>> skuList;
@ApiModelProperty(value = "是否为商品模版")
private Boolean goodsTemplateFlag = false;
/**
* 批发商品规则
*/
@ApiModelProperty(value = "批发商品规则")
private List<WholesaleDTO> wholesaleList;
@ApiModelProperty(value = "注意事项")
private String needingAttention;
@ApiModelProperty(value = "是否为年度会员专属")
private Boolean annualFeeExclusive;
@ApiModelProperty(value = "浏览权限")
private String browsePermissions;
public String getGoodsName() {
//对商品对名称做一个极限处理。这里没有用xss过滤是因为xss过滤为全局过滤影响很大。
// 业务中,全局代码中只有商品名称不能拥有英文逗号,是由于商品名称存在一个数据库联合查询,结果要根据逗号分组
return goodsName.replace(",", "");
}
public GoodsOperationDTO(GoodsImportDTO goodsImportDTO) {
this.price = goodsImportDTO.getPrice();
this.goodsName = goodsImportDTO.getGoodsName();
this.intro = goodsImportDTO.getIntro();
this.mobileIntro = goodsImportDTO.getIntro();
this.quantity = goodsImportDTO.getQuantity();
this.goodsGalleryList = goodsImportDTO.getGoodsGalleryList();
this.templateId = goodsImportDTO.getTemplate();
this.sellingPoint = goodsImportDTO.getSellingPoint();
this.salesModel = GoodsSalesModeEnum.RETAIL.name();
this.goodsUnit = goodsImportDTO.getGoodsUnit();
this.goodsType = GoodsTypeEnum.PHYSICAL_GOODS.name();
this.release = goodsImportDTO.getRelease();
this.recommend=false;
Map<String, Object> map = new HashMap<>();
map.put("sn", goodsImportDTO.getSn());
map.put("price", goodsImportDTO.getPrice());
map.put("cost", goodsImportDTO.getCost());
map.put("weight", goodsImportDTO.getWeight());
map.put("quantity", goodsImportDTO.getQuantity());
map.put(goodsImportDTO.getSkuKey(), goodsImportDTO.getSkuValue());
map.put("images", goodsImportDTO.getImages());
List<Map<String, Object>> skuList = new ArrayList<>();
skuList.add(map);
this.skuList = skuList;
}
}

View File

@@ -6,8 +6,7 @@ import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import java.util.Arrays;
@@ -19,6 +18,9 @@ import java.util.Arrays;
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GoodsSearchParams extends PageVO {
private static final long serialVersionUID = 2544015852728566887L;

View File

@@ -3,6 +3,8 @@ package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.Wholesale;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;
/**
* @author paulG
@@ -10,7 +12,12 @@ import lombok.EqualsAndHashCode;
**/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class WholesaleDTO extends Wholesale {
private static final long serialVersionUID = 853297561151783335L;
public WholesaleDTO(Wholesale wholesale) {
BeanUtils.copyProperties(wholesale, this);
}
}

View File

@@ -1,6 +1,7 @@
package cn.lili.modules.goods.entity.vos;
import cn.lili.modules.goods.entity.dos.DraftGoods;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -29,4 +30,10 @@ public class DraftGoodsVO extends DraftGoods {
@ApiModelProperty(value = "sku列表")
private List<GoodsSkuVO> skuList;
/**
* 批发商品规则
*/
@ApiModelProperty(value = "批发商品规则")
private List<Wholesale> wholesaleList;
}

View File

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* 商品品牌业务层
@@ -40,6 +41,14 @@ public interface BrandService extends IService<Brand> {
*/
List<Brand> getBrandsByCategory(String categoryId);
/**
* 根据分类ID获取品牌列表
*
* @param categoryIds 分类ID
* @return 品牌列表
*/
List<Map<String, Object>> getBrandsMapsByCategory(List<String> categoryIds, String columns);
/**
* 添加品牌
*

View File

@@ -6,6 +6,7 @@ import cn.lili.modules.goods.entity.vos.CategoryVO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* 商品分类业务层
@@ -41,6 +42,14 @@ public interface CategoryService extends IService<Category> {
*/
List<Category> listByIdsOrderByLevel(List<String> ids);
/**
* 根据分类id集合获取所有分类根据层级排序
*
* @param ids 分类ID集合
* @return 商品分类列表
*/
List<Map<String, Object>> listMapsByIdsOrderByLevel(List<String> ids, String columns);
/**
* 获取分类树
*

View File

@@ -0,0 +1,20 @@
package cn.lili.modules.goods.service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
public interface GoodsImportService {
/**
* 下载导入列表
* @param response
*/
void download(HttpServletResponse response);
/**
* 导入商品
*/
void importExcel(MultipartFile files) throws Exception;
}

View File

@@ -184,4 +184,4 @@ public interface GoodsService extends IService<Goods> {
*/
long countStoreGoodsNum(String storeId);
}
}

View File

@@ -82,6 +82,14 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
GoodsSku getGoodsSkuByIdFromCache(String id);
/**
* 从缓存中获取可参与促销商品
*
* @param skuId skuid
* @return 商品详情
*/
GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId);
/**
* 获取商品sku详情
*
@@ -143,7 +151,7 @@ public interface GoodsSkuService extends IService<GoodsSku> {
/**
* 分页查询商品sku信息
*
* @param page 分页参数
* @param page 分页参数
* @param queryWrapper 查询参数
* @return 商品sku信息
*/
@@ -173,13 +181,6 @@ public interface GoodsSkuService extends IService<GoodsSku> {
*/
void updateGoodsSkuStatusByStoreId(String storeId, String marketEnable, String authFlag);
/**
* 发送生成ES商品索引
*
* @param goods 商品信息
*/
void generateEs(Goods goods);
/**
* 更新SKU库存
*
@@ -240,4 +241,12 @@ public interface GoodsSkuService extends IService<GoodsSku> {
* @return sku总数
*/
Long countSkuNum(String storeId);
/**
* 批量渲染商品sku
*
* @param goodsSkuList SKU基础数据列表
* @param goodsOperationDTO 商品操作信息
*/
void renderGoodsSkuList(List<GoodsSku> goodsSkuList, GoodsOperationDTO goodsOperationDTO);
}

View File

@@ -5,6 +5,7 @@ import cn.lili.modules.goods.entity.vos.StoreGoodsLabelVO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* 店铺商品分类业务层
@@ -30,6 +31,14 @@ public interface StoreGoodsLabelService extends IService<StoreGoodsLabel> {
*/
List<StoreGoodsLabel> listByStoreIds(List<String> ids);
/**
* 根据分类id集合获取所有店铺分类根据层级排序
*
* @param ids 商家ID
* @return 店铺分类列表
*/
List<Map<String, Object>> listMapsByStoreIds(List<String> ids, String columns);
/**
* 添加商品分类
*

View File

@@ -53,7 +53,7 @@ public interface StudioService extends IService<Studio> {
* @param storeId 店铺ID
* @return 操作结果
*/
Boolean push(Integer roomId,Integer goodsId, String storeId);
Boolean push(Integer roomId,Integer liveGoodsId, String storeId, String goodsId);
/**
* 删除商品

View File

@@ -14,8 +14,13 @@ public interface WholesaleService extends IService<Wholesale> {
List<Wholesale> findByGoodsId(String goodsId);
List<Wholesale> findByTemplateId(String templateId);
Boolean removeByGoodsId(String goodsId);
Boolean removeByTemplateId(String templateId);
/**
* 匹配批发规则
*

View File

@@ -23,6 +23,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -68,6 +69,14 @@ public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements
return new ArrayList<>();
}
@Override
public List<Map<String, Object>> getBrandsMapsByCategory(List<String> categoryIds, String columns) {
QueryWrapper<Brand> queryWrapper = new QueryWrapper<>();
queryWrapper.select(columns);
queryWrapper.in("id", categoryIds);
return this.listMaps(queryWrapper);
}
@Override
public boolean addBrand(BrandVO brandVO) {

View File

@@ -25,10 +25,7 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@@ -80,6 +77,14 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
return this.list(new LambdaQueryWrapper<Category>().in(Category::getId, ids).orderByAsc(Category::getLevel));
}
@Override
public List<Map<String, Object>> listMapsByIdsOrderByLevel(List<String> ids, String columns) {
QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
queryWrapper.select(columns);
queryWrapper.in("id", ids).orderByAsc("level");
return this.listMaps(queryWrapper);
}
@Override
public List<CategoryVO> categoryTree() {
List<CategoryVO> categoryVOList = (List<CategoryVO>) cache.get(CachePrefix.CATEGORY.getPrefix());

View File

@@ -1,29 +1,25 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.dos.DraftGoods;
import cn.lili.modules.goods.entity.dos.GoodsGallery;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.DraftGoodsDTO;
import cn.lili.modules.goods.entity.dto.DraftGoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import cn.lili.modules.goods.entity.dos.*;
import cn.lili.modules.goods.entity.dto.*;
import cn.lili.modules.goods.entity.vos.DraftGoodsVO;
import cn.lili.modules.goods.mapper.DraftGoodsMapper;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.DraftGoodsService;
import cn.lili.modules.goods.service.GoodsGalleryService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.goods.service.*;
import cn.lili.modules.goods.sku.GoodsSkuBuilder;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 草稿商品业务层实现
@@ -49,6 +45,9 @@ public class DraftGoodsServiceImpl extends ServiceImpl<DraftGoodsMapper, DraftGo
@Autowired
private GoodsSkuService goodsSkuService;
@Autowired
private WholesaleService wholesaleService;
@Override
public boolean addGoodsDraft(DraftGoodsDTO draftGoods) {
draftGoods.setGoodsGalleryListJson(JSONUtil.toJsonStr(draftGoods.getGoodsGalleryList()));
@@ -74,15 +73,33 @@ public class DraftGoodsServiceImpl extends ServiceImpl<DraftGoodsMapper, DraftGo
draftGoods.setSmall(goodsGallery.getSmall());
draftGoods.setThumbnail(goodsGallery.getThumbnail());
}
// 商品图片
draftGoods.setGoodsGalleryListJson(JSONUtil.toJsonStr(draftGoods.getGoodsGalleryList()));
draftGoods.setSkuListJson(JSONUtil.toJsonStr(this.getGoodsSkuList(draftGoods.getSkuList())));
// 商品参数
draftGoods.setGoodsParamsListJson(JSONUtil.toJsonStr(draftGoods.getGoodsParamsDTOList()));
this.saveOrUpdate(draftGoods);
boolean result = this.saveOrUpdate(draftGoods);
if (result && draftGoods.getSkuList() != null && !draftGoods.getSkuList().isEmpty()) {
List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(new Goods(draftGoods), draftGoods.getSkuList());
GoodsOperationDTO.GoodsOperationDTOBuilder goodsOperationDTOBuilder = GoodsOperationDTO.builder().goodsTemplateFlag(true).salesModel(draftGoods.getSalesModel());
if (draftGoods.getWholesaleList() != null && !draftGoods.getWholesaleList().isEmpty()) {
for (WholesaleDTO wholesaleDTO : draftGoods.getWholesaleList()) {
wholesaleDTO.setTemplateId(draftGoods.getId());
}
goodsOperationDTOBuilder.wholesaleList(draftGoods.getWholesaleList());
}
goodsSkuService.renderGoodsSkuList(goodsSkus, goodsOperationDTOBuilder.build());
LambdaUpdateWrapper<DraftGoods> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(DraftGoods::getId, draftGoods.getId());
updateWrapper.set(DraftGoods::getSkuListJson, JSONUtil.toJsonStr(goodsSkus));
this.update(updateWrapper);
}
}
@Override
public void deleteGoodsDraft(String id) {
this.removeById(id);
this.wholesaleService.removeByTemplateId(id);
}
@Override
@@ -104,6 +121,10 @@ public class DraftGoodsServiceImpl extends ServiceImpl<DraftGoodsMapper, DraftGo
JSONArray jsonArray = JSONUtil.parseArray(draftGoods.getSkuListJson());
List<GoodsSku> list = JSONUtil.toList(jsonArray, GoodsSku.class);
draftGoodsVO.setSkuList(goodsSkuService.getGoodsSkuVOList(list));
List<Wholesale> wholesaleList = wholesaleService.findByTemplateId(draftGoods.getId());
if (CollUtil.isNotEmpty(wholesaleList)) {
draftGoodsVO.setWholesaleList(wholesaleList);
}
return draftGoodsVO;
}
@@ -112,48 +133,4 @@ public class DraftGoodsServiceImpl extends ServiceImpl<DraftGoodsMapper, DraftGo
return this.page(PageUtil.initPage(searchParams), searchParams.queryWrapper());
}
/**
* 获取sku集合
*
* @param skuList sku列表
* @return sku集合
*/
private List<GoodsSku> getGoodsSkuList(List<Map<String, Object>> skuList) {
List<GoodsSku> skus = new ArrayList<>();
for (Map<String, Object> skuVO : skuList) {
GoodsSku add = this.add(skuVO);
skus.add(add);
}
return skus;
}
private GoodsSku add(Map<String, Object> map) {
Map<String, Object> specMap = new HashMap<>(2);
GoodsSku sku = new GoodsSku();
for (Map.Entry<String, Object> m : map.entrySet()) {
switch (m.getKey()) {
case "sn":
sku.setSn(m.getValue() != null ? m.getValue().toString() : "");
break;
case "cost":
sku.setCost(Convert.toDouble(m.getValue()));
break;
case "price":
sku.setPrice(Convert.toDouble(m.getValue()));
break;
case "quantity":
sku.setQuantity(Convert.toInt(m.getValue()));
break;
case "weight":
sku.setWeight(Convert.toDouble(m.getValue()));
break;
default:
specMap.put(m.getKey(), m.getValue());
break;
}
}
sku.setSpecs(JSONUtil.toJsonStr(specMap));
return sku;
}
}

View File

@@ -0,0 +1,281 @@
package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.convert.Convert;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dos.Category;
import cn.lili.modules.goods.entity.dos.GoodsUnit;
import cn.lili.modules.goods.entity.dto.GoodsImportDTO;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.vos.CategoryVO;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsImportService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsUnitService;
import cn.lili.modules.store.entity.vos.FreightTemplateVO;
import cn.lili.modules.store.service.FreightTemplateService;
import cn.lili.modules.store.service.StoreDetailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class GoodsImportServiceImpl implements GoodsImportService {
@Autowired
private FreightTemplateService freightTemplateService;
@Autowired
private StoreDetailService storeDetailService;
@Autowired
private CategoryService categoryService;
@Autowired
private GoodsUnitService goodsUnitService;
@Autowired
private GoodsService goodsService;
@Override
public void download(HttpServletResponse response) {
String storeId = "1376369067769724928";
// //Objects.requireNonNull(UserContext.getCurrentUser()).getStoreId();
//创建Excel工作薄对象
Workbook workbook = new HSSFWorkbook();
//生成一个表格 设置:页签
Sheet sheet = workbook.createSheet("导入模板");
//创建第1行
Row row0 = sheet.createRow(0);
row0.createCell(0).setCellValue("商品名称");
row0.createCell(1).setCellValue("商品卖点");
row0.createCell(2).setCellValue("商品分类");
row0.createCell(3).setCellValue("运费模板");
row0.createCell(4).setCellValue("计量单位");
row0.createCell(5).setCellValue("发布状态");
row0.createCell(6).setCellValue("商品图片");
row0.createCell(7).setCellValue("成本价");
row0.createCell(8).setCellValue("销售价");
row0.createCell(9).setCellValue("库存");
row0.createCell(10).setCellValue("重量");
row0.createCell(11).setCellValue("货号");
row0.createCell(12).setCellValue("详情");
row0.createCell(13).setCellValue("规格项");
row0.createCell(14).setCellValue("规格值");
sheet.setColumnWidth(0, 7000);
sheet.setColumnWidth(1, 7000);
sheet.setColumnWidth(2, 7000);
sheet.setColumnWidth(3, 7000);
sheet.setColumnWidth(4, 7000);
sheet.setColumnWidth(5, 3000);
sheet.setColumnWidth(6, 7000);
sheet.setColumnWidth(7, 3000);
sheet.setColumnWidth(8, 3000);
sheet.setColumnWidth(9, 3000);
sheet.setColumnWidth(10, 3000);
sheet.setColumnWidth(11, 7000);
sheet.setColumnWidth(12, 7000);
sheet.setColumnWidth(13, 3000);
sheet.setColumnWidth(14, 3000);
String goodsManagementCategory = storeDetailService.getStoreDetail(storeId).getGoodsManagementCategory();
List<CategoryVO> categoryVOList = this.categoryService.getStoreCategory(goodsManagementCategory.split(","));
List<String> categoryNameList = new ArrayList<>();
//先简单写,后期优化
//循环三次添加值
//循环列表存放ID-分类名称
for (CategoryVO categoryVO1 : categoryVOList) {
for (CategoryVO categoryVO2 : categoryVO1.getChildren()) {
for (CategoryVO categoryVO3 : categoryVO2.getChildren()) {
categoryNameList.add(categoryVO3.getId() + "-" + categoryVO3.getName());
}
}
}
List<String> freightTemplateNameList = new ArrayList<>();
//循环列表存放ID-运费模板名称
for (FreightTemplateVO freightTemplateVO : freightTemplateService.getFreightTemplateList(storeId)) {
freightTemplateNameList.add(freightTemplateVO.getId() + "-" + freightTemplateVO.getName());
}
//获取计量单位
List<String> goodsUnitList = new ArrayList<>();
List<GoodsUnit> goodsUnitListVO = goodsUnitService.list();
for (GoodsUnit goodsUnit : goodsUnitListVO) {
goodsUnitList.add(goodsUnit.getId() + "-" + goodsUnit.getName());
}
//添加分类
this.excelTo255(workbook, "hiddenCategoryVO", 1, categoryNameList.toArray(new String[]{}), 1, 5000, 2, 2);
//添加运费模板
this.excelTo255(workbook, "hiddenFreightTemplateVO", 2, freightTemplateNameList.toArray(new String[]{}), 1, 5000, 3, 3);
//添加计量单位
this.excelTo255(workbook, "hiddenGoodsUnit", 3, goodsUnitList.toArray(new String[]{}), 1, 5000, 4, 4);
//添加计量单位
this.excelTo255(workbook, "hiddenRelease", 4, new String[]{"上架", "仓库中"}, 1, 5000, 5, 5);
ServletOutputStream out = null;
try {
//设置公共属性,列表名称
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("下载商品导入模板", "UTF8") + ".xls");
out = response.getOutputStream();
workbook.write(out);
} catch (Exception e) {
log.error("下载商品导入模板错误", e);
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void importExcel(MultipartFile files) throws Exception {
InputStream inputStream;
List<GoodsImportDTO> goodsImportDTOList = new ArrayList<>();
inputStream = files.getInputStream();
ExcelReader excelReader = ExcelUtil.getReader(inputStream);
// 读取列表
// 检测数据-查看分类、模板、计量单位是否存在
List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
for (List<Object> objects : read) {
GoodsImportDTO goodsImportDTO = new GoodsImportDTO();
String categoryId = objects.get(2).toString().substring(0, objects.get(2).toString().indexOf("-"));
Category category = categoryService.getCategoryById(categoryId);
if (category == null) {
throw new ServiceException("商品分类不存在:" + objects.get(2).toString().substring(objects.get(2).toString().indexOf("-")));
}
String templateId = objects.get(3).toString().substring(0, objects.get(3).toString().indexOf("-"));
FreightTemplateVO freightTemplateVO = freightTemplateService.getFreightTemplate(templateId);
if (freightTemplateVO == null) {
throw new ServiceException("配送模板不存在:" + objects.get(3).toString().substring(objects.get(3).toString().indexOf("-")));
}
goodsImportDTO.setGoodsName(objects.get(0).toString());
goodsImportDTO.setSellingPoint(objects.get(1).toString());
goodsImportDTO.setCategory(category);
goodsImportDTO.setTemplate(templateId);
goodsImportDTO.setGoodsUnit(objects.get(4).toString().substring(objects.get(4).toString().indexOf("-") + 1));
goodsImportDTO.setRelease(objects.get(5).toString().equals("上架") ? true : false);
List<Map<String, String>> images = new ArrayList<>();
List<String> goodsGalleryList = new ArrayList<>();
Map<String, String> map = new HashMap<>();
map.put("url", objects.get(6).toString());
images.add(map);
goodsGalleryList.add(objects.get(6).toString());
goodsImportDTO.setImages(images);
goodsImportDTO.setGoodsGalleryList(goodsGalleryList);
goodsImportDTO.setCost(Convert.toDouble(objects.get(7)));
goodsImportDTO.setPrice(Convert.toDouble(objects.get(8)));
goodsImportDTO.setQuantity(Convert.toInt(objects.get(9)));
goodsImportDTO.setWeight(Convert.toDouble(objects.get(10)));
goodsImportDTO.setSn(objects.get(11).toString());
goodsImportDTO.setIntro("<p>" + objects.get(12).toString() + "</p>");
goodsImportDTO.setSkuKey(objects.get(13).toString());
goodsImportDTO.setSkuValue(objects.get(14).toString());
goodsImportDTOList.add(goodsImportDTO);
}
//添加商品
addGoodsList(goodsImportDTOList);
}
/**
* 添加商品
*
* @param goodsImportDTOList
*/
private void addGoodsList(List<GoodsImportDTO> goodsImportDTOList) {
for (GoodsImportDTO goodsImportDTO : goodsImportDTOList) {
GoodsOperationDTO goodsOperationDTO = new GoodsOperationDTO(goodsImportDTO);
//获取父
Category parentCategory = categoryService.getCategoryById(goodsImportDTO.getCategory().getParentId());
goodsOperationDTO.setCategoryPath(parentCategory.getParentId() + "," + parentCategory.getId() + "," + goodsImportDTO.getCategory().getParentId());
//添加商品
goodsService.addGoods(goodsOperationDTO);
}
}
/**
* 表格
*
* @param workbook 表格
* @param sheetName sheet名称
* @param sheetNameIndex 开始
* @param sheetData 数据
* @param firstRow 开始行
* @param lastRow 结束行
* @param firstCol 开始列
* @param lastCol 结束列
*/
private void excelTo255(Workbook workbook, String sheetName, int sheetNameIndex, String[] sheetData,
int firstRow, int lastRow, int firstCol, int lastCol) {
//将下拉框数据放到新的sheet里然后excle通过新的sheet数据加载下拉框数据
Sheet hidden = workbook.createSheet(sheetName);
//创建单元格对象
Cell cell = null;
//遍历我们上面的数组将数据取出来放到新sheet的单元格中
for (int i = 0, length = sheetData.length; i < length; i++) {
//取出数组中的每个元素
String name = sheetData[i];
//根据i创建相应的行对象说明我们将会把每个元素单独放一行
Row row = hidden.createRow(i);
//创建每一行中的第一个单元格
cell = row.createCell(0);
//然后将数组中的元素赋值给这个单元格
cell.setCellValue(name);
}
// 创建名称,可被其他单元格引用
Name namedCell = workbook.createName();
namedCell.setNameName(sheetName);
// 设置名称引用的公式
namedCell.setRefersToFormula(sheetName + "!$A$1:$A$" + (sheetData.length > 0 ? sheetData.length : 1));
//加载数据,将名称为hidden的sheet中的数据转换为List形式
DVConstraint constraint = DVConstraint.createFormulaListConstraint(sheetName);
// 设置第一列的3-65534行为下拉列表
// (3, 65534, 2, 2) ====> (起始行,结束行,起始列,结束列)
CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
// 将设置下拉选的位置和数据的对应关系 绑定到一起
DataValidation dataValidation = new HSSFDataValidation(regions, constraint);
//将第二个sheet设置为隐藏
workbook.setSheetHidden(sheetNameIndex, true);
//将数据赋给下拉列表
workbook.getSheetAt(0).addValidationData(dataValidation);
}
}

View File

@@ -7,6 +7,7 @@ import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.common.security.AuthUser;
@@ -50,6 +51,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -106,6 +108,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
@Autowired
private RocketmqCustomProperties rocketmqCustomProperties;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private FreightTemplateService freightTemplateService;
@@ -129,6 +134,10 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
List<String> list = this.baseMapper.getGoodsIdByStoreId(storeId);
//下架店铺下的商品
updateGoodsMarketAble(list, GoodsStatusEnum.DOWN, "店铺关闭");
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("下架商品",
rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.DOWN.name(), JSONUtil.toJsonStr(list)));
}
/**
@@ -161,7 +170,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
//检查商品
this.checkGoods(goods);
//向goods加入图片
this.setGoodsGalleryParam(goodsOperationDTO.getGoodsGalleryList().get(0), goods);
if (goodsOperationDTO.getGoodsGalleryList().size() > 0 ) {
this.setGoodsGalleryParam(goodsOperationDTO.getGoodsGalleryList().get(0), goods);
}
//添加商品参数
if (goodsOperationDTO.getGoodsParamsDTOList() != null && !goodsOperationDTO.getGoodsParamsDTOList().isEmpty()) {
//给商品参数填充值
@@ -175,9 +186,11 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
}
this.generateEs(goods);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void editGoods(GoodsOperationDTO goodsOperationDTO, String goodsId) {
@@ -203,8 +216,10 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
this.deleteEsGoods(Collections.singletonList(goodsId));
}
cache.remove(CachePrefix.GOODS.getPrefix() + goodsId);
this.generateEs(goods);
}
@Override
public GoodsVO getGoodsVO(String goodsId) {
//缓存获取,如果没有则读取缓存
@@ -330,13 +345,13 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
*/
@Override
public Boolean updateGoodsMarketAbleByStoreId(String storeId, GoodsStatusEnum goodsStatusEnum, String underReason) {
boolean result;
LambdaUpdateWrapper<Goods> updateWrapper = this.getUpdateWrapperByStoreAuthority();
updateWrapper.set(Goods::getMarketEnable, goodsStatusEnum.name());
updateWrapper.set(Goods::getUnderMessage, underReason);
updateWrapper.eq(Goods::getStoreId, storeId);
result = this.update(updateWrapper);
boolean result = this.update(updateWrapper);
//修改规格商品
this.goodsSkuService.updateGoodsSkuStatusByStoreId(storeId, goodsStatusEnum.name(), null);
@@ -420,6 +435,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
LambdaUpdateWrapper<Goods> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.set(Goods::getQuantity, quantity);
lambdaUpdateWrapper.eq(Goods::getId, goodsId);
cache.remove(CachePrefix.GOODS.getPrefix() + goodsId);
this.update(lambdaUpdateWrapper);
}
@@ -478,17 +494,6 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
}
/**
* 更新店铺商品数量
*
* @param storeId 信息体
*/
void updateGoodsNum(String storeId) {
Long num = goodsSkuService.countSkuNum(storeId);
storeService.updateStoreGoodsNum(storeId, num);
}
/**
* 更新商品状态
*
@@ -506,7 +511,40 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) {
this.deleteEsGoods(goodsIds);
} else {
this.updateEsGoods(goodsIds);
}
//下架商品发送消息
if (goodsStatusEnum.equals(GoodsStatusEnum.DOWN)) {
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("下架商品",
rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.DOWN.name(), JSONUtil.toJsonStr(goodsIds)));
}
}
/**
* 发送生成ES商品索引
*
* @param goods 商品信息
*/
@Transactional
public void generateEs(Goods goods) {
// 不生成没有审核通过且没有上架的商品
if (!GoodsStatusEnum.UPPER.name().equals(goods.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) {
return;
}
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_GOODS_INDEX.name(), goods.getId()));
}
/**
* 发送生成ES商品索引
*
* @param goodsIds 商品id
*/
@Transactional
public void updateEsGoods(List<String> goodsIds) {
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("更新商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.UPDATE_GOODS_INDEX.name(), goodsIds));
}
/**
@@ -514,11 +552,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
*
* @param goodsIds 商品id
*/
private void deleteEsGoods(List<String> goodsIds) {
//商品删除消息
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIds), RocketmqSendCallbackBuilder.commonCallback());
@Transactional
public void deleteEsGoods(List<String> goodsIds) {
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GOODS_DELETE.name(), JSONUtil.toJsonStr(goodsIds)));
}
/**
@@ -554,7 +590,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
break;
case "VIRTUAL_GOODS":
if (!"0".equals(goods.getTemplateId())) {
throw new ServiceException(ResultCode.VIRTUAL_GOODS_NOT_NEED_TEMP);
goods.setTemplateId("0");
}
break;
default:
@@ -667,4 +703,4 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
return queryWrapper;
}
}
}

View File

@@ -22,6 +22,7 @@ import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsSkuDTO;
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.vos.GoodsSkuSpecVO;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
@@ -42,6 +43,7 @@ import cn.lili.modules.promotion.service.PromotionGoodsService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.search.utils.EsIndexUtil;
import cn.lili.mybatis.BaseEntity;
import cn.lili.mybatis.util.PageUtil;
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
import cn.lili.rocketmq.tags.GoodsTagsEnum;
@@ -130,13 +132,12 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
}
// 检查是否需要生成索引
List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO.getSkuList());
renderGoodsSkuList(goodsSkus, goodsOperationDTO);
if (!goodsSkus.isEmpty()) {
this.saveOrUpdateBatch(goodsSkus);
this.updateStock(goodsSkus);
this.generateEs(goods);
}
}
@@ -150,7 +151,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
List<GoodsSku> skuList;
//删除旧的sku信息
if (Boolean.TRUE.equals(goodsOperationDTO.getRegeneratorSkuFlag())) {
skuList = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO);
skuList = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO.getSkuList());
renderGoodsSkuList(skuList, goodsOperationDTO);
List<GoodsSkuVO> goodsListByGoodsId = getGoodsListByGoodsId(goods.getId());
List<String> oldSkuIds = new ArrayList<>();
@@ -160,7 +161,6 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
cache.remove(GoodsSkuService.getCacheKeys(goodsSkuVO.getId()));
}
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
//删除sku相册
goodsGalleryService.removeByGoodsId(goods.getId());
@@ -170,7 +170,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
} else {
skuList = new ArrayList<>();
for (Map<String, Object> map : goodsOperationDTO.getSkuList()) {
GoodsSku sku = GoodsSkuBuilder.build(goods, map, goodsOperationDTO);
GoodsSku sku = GoodsSkuBuilder.build(goods, map);
renderGoodsSku(sku, goodsOperationDTO);
skuList.add(sku);
//如果商品状态值不对则es索引移除
@@ -181,10 +181,12 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
}
}
if (!skuList.isEmpty()) {
this.remove(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goods.getId()));
LambdaQueryWrapper<GoodsSku> unnecessarySkuIdsQuery = new LambdaQueryWrapper<>();
unnecessarySkuIdsQuery.eq(GoodsSku::getGoodsId, goods.getId());
unnecessarySkuIdsQuery.notIn(GoodsSku::getId, skuList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
this.remove(unnecessarySkuIdsQuery);
this.saveOrUpdateBatch(skuList);
this.updateStock(skuList);
this.generateEs(goods);
}
}
@@ -237,6 +239,15 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
return goodsSku;
}
@Override
public GoodsSku getCanPromotionGoodsSkuByIdFromCache(String skuId) {
GoodsSku goodsSku = this.getGoodsSkuByIdFromCache(skuId);
if (goodsSku != null && GoodsSalesModeEnum.WHOLESALE.name().equals(goodsSku.getSalesModel())) {
throw new ServiceException(ResultCode.PROMOTION_GOODS_DO_NOT_JOIN_WHOLESALE, goodsSku.getGoodsName());
}
return goodsSku;
}
@Override
public Map<String, Object> getGoodsSkuDetail(String goodsId, String skuId) {
Map<String, Object> map = new HashMap<>(16);
@@ -344,9 +355,6 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
cache.remove(GoodsSkuService.getCacheKeys(sku.getId()));
cache.put(GoodsSkuService.getCacheKeys(sku.getId()), sku);
}
if (!goodsSkus.isEmpty()) {
this.generateEs(goods);
}
}
}
@@ -395,7 +403,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
@Override
public List<GoodsSkuVO> getGoodsListByGoodsId(String goodsId) {
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId).orderByAsc(GoodsSku::getGoodsName));
List<GoodsSku> list = this.list(new LambdaQueryWrapper<GoodsSku>().eq(GoodsSku::getGoodsId, goodsId));
return this.getGoodsSkuVOList(list);
}
@@ -583,21 +591,6 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
return this.baseMapper.getGoodsSkuIdByGoodsId(goodsId);
}
/**
* 发送生成ES商品索引
*
* @param goods 商品信息
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void generateEs(Goods goods) {
// 不生成没有审核通过且没有上架的商品
if (!GoodsStatusEnum.UPPER.name().equals(goods.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) {
return;
}
applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_GOODS_INDEX.name(), goods.getId()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteAndInsertGoodsSkus(List<GoodsSku> goodsSkus) {
@@ -646,7 +639,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
* @param goodsSkuList sku集合
* @param goodsOperationDTO 商品操作DTO
*/
void renderGoodsSkuList(List<GoodsSku> goodsSkuList, GoodsOperationDTO goodsOperationDTO) {
@Override
public void renderGoodsSkuList(List<GoodsSku> goodsSkuList, GoodsOperationDTO goodsOperationDTO) {
// 商品销售模式渲染器
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderBatch(goodsSkuList, goodsOperationDTO));
for (GoodsSku goodsSku : goodsSkuList) {

View File

@@ -12,6 +12,7 @@ import cn.lili.modules.goods.entity.vos.StoreGoodsLabelVO;
import cn.lili.modules.goods.mapper.StoreGoodsLabelMapper;
import cn.lili.modules.goods.service.StoreGoodsLabelService;
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.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -22,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* 店铺商品分类业务层实现
@@ -58,6 +60,7 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
list.stream()
.filter(label -> label.getParentId() != null && label.getParentId().equals(storeGoodsLabel.getId()))
.forEach(storeGoodsLabelChild -> storeGoodsLabelVOChildList.add(new StoreGoodsLabelVO(storeGoodsLabelChild.getId(), storeGoodsLabelChild.getLabelName(), storeGoodsLabelChild.getLevel(), storeGoodsLabelChild.getSortOrder())));
storeGoodsLabelVOChildList.sort(Comparator.comparing(StoreGoodsLabelVO::getSortOrder));
storeGoodsLabelVO.setChildren(storeGoodsLabelVOChildList);
storeGoodsLabelVOList.add(storeGoodsLabelVO);
});
@@ -82,6 +85,13 @@ public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMappe
return this.list(new LambdaQueryWrapper<StoreGoodsLabel>().in(StoreGoodsLabel::getId, ids).orderByAsc(StoreGoodsLabel::getLevel));
}
@Override
public List<Map<String, Object>> listMapsByStoreIds(List<String> ids, String columns) {
QueryWrapper<StoreGoodsLabel> queryWrapper = new QueryWrapper<StoreGoodsLabel>().in("id", ids).orderByAsc("level");
queryWrapper.select(columns);
return this.listMaps(queryWrapper);
}
@Override
@Transactional(rollbackFor = Exception.class)
public StoreGoodsLabel addStoreGoodsLabel(StoreGoodsLabel storeGoodsLabel) {

View File

@@ -161,12 +161,12 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean push(Integer roomId, Integer goodsId, String storeId) {
public Boolean push(Integer roomId, Integer liveGoodsId, String storeId, String goodsId) {
//判断直播间是否已添加商品
if (studioCommodityService.getOne(
new LambdaQueryWrapper<StudioCommodity>().eq(StudioCommodity::getRoomId, roomId)
.eq(StudioCommodity::getGoodsId, goodsId)) != null) {
.eq(StudioCommodity::getGoodsId, liveGoodsId)) != null) {
throw new ServiceException(ResultCode.STODIO_GOODS_EXIST_ERROR);
}
@@ -176,8 +176,8 @@ public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> impleme
}
//调用微信接口添加直播间商品并进行记录
if (Boolean.TRUE.equals(wechatLivePlayerUtil.pushGoods(roomId, goodsId))) {
studioCommodityService.save(new StudioCommodity(roomId, goodsId));
if (Boolean.TRUE.equals(wechatLivePlayerUtil.pushGoods(roomId, liveGoodsId))) {
studioCommodityService.save(new StudioCommodity(roomId, liveGoodsId));
//添加直播间商品数量
Studio studio = this.getByRoomId(roomId);
studio.setRoomGoodsNum(studio.getRoomGoodsNum() != null ? studio.getRoomGoodsNum() + 1 : 1);

View File

@@ -2,6 +2,8 @@ package cn.lili.modules.goods.serviceimpl;
import cn.hutool.core.collection.CollUtil;
import cn.lili.cache.Cache;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dos.Wholesale;
import cn.lili.modules.goods.mapper.WholesaleMapper;
import cn.lili.modules.goods.service.WholesaleService;
@@ -36,6 +38,23 @@ public class WholesaleServiceImpl extends ServiceImpl<WholesaleMapper, Wholesale
return this.list(queryWrapper).stream().sorted(Comparator.comparing(Wholesale::getNum)).collect(Collectors.toList());
}
@Override
@Cacheable(key = "#templateId+'_template'")
public List<Wholesale> findByTemplateId(String templateId) {
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Wholesale::getTemplateId, templateId);
return this.list(queryWrapper).stream().sorted(Comparator.comparing(Wholesale::getNum)).collect(Collectors.toList());
}
@Override
@CacheEvict(key = "#templateId+'_template'")
public Boolean removeByTemplateId(String templateId) {
LambdaQueryWrapper<Wholesale> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Wholesale::getTemplateId, templateId);
cache.remove("{wholesale}_" + templateId + "_template");
return this.remove(queryWrapper);
}
@Override
@CacheEvict(key = "#goodsId")
public Boolean removeByGoodsId(String goodsId) {
@@ -58,7 +77,7 @@ public class WholesaleServiceImpl extends ServiceImpl<WholesaleMapper, Wholesale
if (CollUtil.isNotEmpty(matchList)) {
return matchList.get(matchList.size() - 1);
} else if (CollUtil.isNotEmpty(wholesaleList) && CollUtil.isEmpty(matchList)) {
return wholesaleList.get(0);
throw new ServiceException(ResultCode.DO_NOT_MATCH_WHOLESALE);
}
return null;
}

View File

@@ -6,7 +6,6 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import org.springframework.stereotype.Component;
import java.util.*;
@@ -25,50 +24,44 @@ public class GoodsSkuBuilder {
/**
* 构建商品sku
*
* @param goods 商品
* @param skuInfo sku信息列表
* @param goodsOperationDTO 商品操作信息(如需处理额外信息传递,不需可传空)
* @param goods 商品
* @param skuInfo sku信息列表
* @return 商品sku
*/
public static GoodsSku build(Goods goods, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
public static GoodsSku build(Goods goods, Map<String, Object> skuInfo) {
GoodsSku goodsSku = new GoodsSku(goods);
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
builderSingle(goodsSku, skuInfo);
return goodsSku;
}
/**
* 批量构建商品sku
*
* @param goods 商品
* @param goodsOperationDTO 商品操作信息
* @param goods 商品
* @return 商品sku
*/
public static List<GoodsSku> buildBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
return builderBatch(goods, goodsOperationDTO);
public static List<GoodsSku> buildBatch(Goods goods, List<Map<String, Object>> skuList) {
Assert.notEmpty(skuList, "skuList不能为空");
Assert.notNull(goods, "goods不能为空");
List<GoodsSku> goodsSkus = new ArrayList<>();
for (Map<String, Object> skuInfo : skuList) {
GoodsSku goodsSku = new GoodsSku(goods);
builderSingle(goodsSku, skuInfo);
goodsSkus.add(goodsSku);
}
return goodsSkus;
}
/**
* 从已有的商品sku中构建商品sku
*
* @param goodsSku 原商品sku
* @param skuInfo sku信息列表
* @param goodsOperationDTO 商品操作信息(如需处理额外信息传递,不需可传空)
* @return 商品sku
*/
public static GoodsSku build(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
return goodsSku;
}
private static void builderSingle(GoodsSku goodsSku, Map<String, Object> skuInfo, GoodsOperationDTO goodsOperationDTO) {
private static void builderSingle(GoodsSku goodsSku, Map<String, Object> skuInfo) {
Assert.notNull(goodsSku, "goodsSku不能为空");
Assert.notEmpty(skuInfo, "skuInfo不能为空");
//规格简短信息
StringBuilder simpleSpecs = new StringBuilder();
//商品名称
StringBuilder goodsName = new StringBuilder(goodsOperationDTO.getGoodsName());
StringBuilder goodsName = new StringBuilder(goodsSku.getGoodsName());
//规格值
Map<String, Object> specMap = new HashMap<>(16);
Map<String, Object> specMap = new LinkedHashMap<>();
// 原始规格项
String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight"};
@@ -100,17 +93,5 @@ public class GoodsSkuBuilder {
goodsSku.setSimpleSpecs(simpleSpecs.toString());
}
private static List<GoodsSku> builderBatch(Goods goods, GoodsOperationDTO goodsOperationDTO) {
Assert.notEmpty(goodsOperationDTO.getSkuList(), "goodsOperationDTO.getSkuList()不能为空");
Assert.notNull(goods, "goods不能为空");
List<GoodsSku> goodsSkus = new ArrayList<>();
for (Map<String, Object> skuInfo : goodsOperationDTO.getSkuList()) {
GoodsSku goodsSku = new GoodsSku(goods);
builderSingle(goodsSku, skuInfo, goodsOperationDTO);
goodsSkus.add(goodsSku);
}
return goodsSkus;
}
}

View File

@@ -55,7 +55,11 @@ public class WholesaleSaleModelRenderImpl implements SalesModelRender {
skus.setPrice(collect.get(0).getPrice());
skus.setCost(collect.get(0).getPrice());
}
wholesaleService.removeByGoodsId(goodsSkus.get(0).getGoodsId());
if (Boolean.TRUE.equals(goodsOperationDTO.getGoodsTemplateFlag())) {
wholesaleService.removeByTemplateId(goodsSkus.get(0).getGoodsId());
} else {
wholesaleService.removeByGoodsId(goodsSkus.get(0).getGoodsId());
}
wholesaleService.saveOrUpdateBatch(collect);
}

View File

@@ -0,0 +1,17 @@
package cn.lili.modules.kdBrid.service;
/**
* 快递鸟电子面单业务层实现
*
* @author chc
* @since 2022-4-12 10:12:43
*/
public interface KdNiaoService {
/**
* 生成电子面单
* @param orderSn 订单编号
* @param logisticsId 物流公司
* @return 电子面单模板
*/
String createElectronicsFaceSheet(String orderSn, String logisticsId) throws Exception;
}

View File

@@ -0,0 +1,383 @@
package cn.lili.modules.kdBrid.serviceImpl;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.OperationalJudgment;
import cn.lili.modules.kdBrid.service.KdNiaoService;
import cn.lili.modules.member.service.StoreLogisticsService;
import cn.lili.modules.order.order.aop.OrderLogPoint;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.enums.DeliverStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.store.entity.dos.StoreLogistics;
import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO;
import cn.lili.modules.store.service.StoreDetailService;
import cn.lili.modules.system.entity.dos.Logistics;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.KuaidiSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.LogisticsService;
import cn.lili.modules.system.service.SettingService;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 快递鸟电子面单业务层实现
*
* @author chc
* @since 2022-4-12 10:12:43
*/
@Service
@Slf4j
public class KdNiaoServiceImpl implements KdNiaoService {
/**
* 订单货物
*/
@Autowired
OrderItemService orderItemService;
/**
* 订单
*/
@Autowired
OrderService orderService;
/**
* 物流公司
*/
@Autowired
LogisticsService logisticsService;
/**
* 商家店铺
*/
@Autowired
StoreDetailService storeDetailService;
/**
* 配置
*/
@Autowired
SettingService settingService;
/**
* 店铺-物流
*/
@Autowired
StoreLogisticsService storeLogisticsService;
@Override
@OrderLogPoint(description = "'订单['+#orderSn+']发货,发货单号['+#logisticsNo+'],已打印电子面单'", orderSn = "#orderSn")
@Transactional(rollbackFor = Exception.class)
public String createElectronicsFaceSheet(String orderSn, String logisticsId) throws Exception {
//电子面单模板
String printTemplate = null;
//获取订单及子订单
Order order = OperationalJudgment.judgment(orderService.getBySn(orderSn));
List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn);
Setting setting = settingService.get(SettingEnum.KUAIDI_SETTING.name());
if (CharSequenceUtil.isBlank(setting.getSettingValue())) {
throw new ServiceException(ResultCode.LOGISTICS_NOT_SETTING);
}
KuaidiSetting kuaidiSetting = new Gson().fromJson(setting.getSettingValue(), KuaidiSetting.class);
//ID
String EBusinessID = kuaidiSetting.getEbusinessID();
//KEY
String AppKey = kuaidiSetting.getAppKey();
//请求url
String ReqURL = kuaidiSetting.getSheetReqURL();
//如果订单未发货,并且订单状态值等于待发货
if (order.getDeliverStatus().equals(DeliverStatusEnum.UNDELIVERED.name()) && order.getOrderStatus().equals(OrderStatusEnum.UNDELIVERED.name())) {
//获取对应物流
Logistics logistics = logisticsService.getById(logisticsId);
//物流为空,抛出异常
if (logistics == null) {
throw new ServiceException(ResultCode.ORDER_LOGISTICS_ERROR);
}
//获取店家的物流信息
LambdaQueryWrapper<StoreLogistics> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(StoreLogistics::getLogisticsId, logisticsId);
lambdaQueryWrapper.eq(StoreLogistics::getStoreId, order.getStoreId());
StoreLogistics storeLogistics = storeLogisticsService.getOne(lambdaQueryWrapper);
//获取店家信息
StoreDeliverGoodsAddressDTO storeDeliverGoodsAddressDTO = storeDetailService.getStoreDeliverGoodsAddressDto(order.getStoreId());
//收件人地址
String[] ConsigneeAddress = order.getConsigneeAddressPath().split(",");
//发件人地址
String[] consignorAddress = storeDeliverGoodsAddressDTO.getSalesConsignorAddressPath().split(",");
//组装快递鸟应用级参数
String resultDate = "{" +
"'OrderCode': '" + orderSn + "'," + //订单编码
"'ShipperCode': '" + logistics.getCode() + "'," + //快递公司编码
"'CustomerName': '"+storeLogistics.getCustomerName()+"'," +//客户编码
"'CustomerPwd': '"+storeLogistics.getCustomerPwd()+"'," + //客户密码
"'MonthCode': '"+storeLogistics.getMonthCode()+"'," + //密钥
"'SendSite': '"+storeLogistics.getSendSite()+"'," + //归属网点
"'SendStaff': '"+storeLogistics.getSendStaff()+"'," + //收件快递员
"'PayType': "+storeLogistics.getPayType()+"," +
"'ExpType': "+storeLogistics.getExpType()+"," +
//发件人信息
"'Sender': {" +
"'Name': '" + storeDeliverGoodsAddressDTO.getSalesConsignorName() + "'," +
"'Mobile': '" + storeDeliverGoodsAddressDTO.getSalesConsignorMobile() + "'," +
"'ProvinceName': '" + consignorAddress[0] + "'," + //省
"'CityName': '" + consignorAddress[1] + "'," + //市
"'ExpAreaName': '" + consignorAddress[2] + "'," + //区
"'Address': '" + storeDeliverGoodsAddressDTO.getSalesConsignorDetail() + "'" + //发件人详细地址
"}," +
//收件人信息
"'Receiver': {" +
"'Name': '" + order.getConsigneeName() + "'," +
"'Mobile': '" + order.getConsigneeMobile() + "'," +
"'ProvinceName': '" + ConsigneeAddress[0] + "'," + //省
"'CityName': '" + ConsigneeAddress[1] + "'," + //市
"'ExpAreaName': '" + ConsigneeAddress[2] + "'," + //区
"'Address': '" + order.getConsigneeDetail() + "'" + //收件人详细地址
"}," +
//商品信息
"'Commodity': [";
//子订单信息
for (OrderItem orderItem : orderItems) {
resultDate = resultDate + "{" +
"'GoodsName': '" + orderItem.getGoodsName() + "'," +
"'Goodsquantity': '" + orderItem.getNum() + "'" +
"},";
}
resultDate = resultDate + "]," +
"'Quantity': "+orderItems.size()+"," + //包裹数
"'IsReturnPrintTemplate':1,"+ //生成电子面单模板
"'Remark': '" + order.getRemark() + "'"+//商家备注
"}";
//组织系统级参数
Map<String, String> params = new HashMap<>();
//进行格式加密
params.put("RequestData", urlEncoder(resultDate, "UTF-8"));
params.put("EBusinessID", EBusinessID);
params.put("RequestType", "1007");
String dataSign = encrypt(resultDate, AppKey, "UTF-8");
params.put("DataSign", dataSign);
params.put("DataType", "2");
// 以form表单形式提交post请求post请求体中包含了应用级参数和系统级参数
String result = sendPost(ReqURL, params);
//根据公司业务处理返回的信息......
JSONObject obj = JSONObject.parseObject(result);
if(!"100".equals(obj.getString("ResultCode"))){
return obj.getString("Reason");
}
JSONObject orderJson = JSONObject.parseObject(obj.getString("Order"));
//电子面单模板
printTemplate = obj.getString("PrintTemplate");
//进行发货
orderService.delivery(orderSn, orderJson.getString("LogisticCode"), logisticsId);
}
return printTemplate;
}
/**
* MD5加密
*
* @param str 内容
* @param charset 编码方式
* @throws Exception
*/
@SuppressWarnings("unused")
private String MD5(String str, String charset) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(charset));
byte[] result = md.digest();
StringBuffer sb = new StringBuffer(32);
for (int i = 0; i < result.length; i++) {
int val = result[i] & 0xff;
if (val <= 0xf) {
sb.append("0");
}
sb.append(Integer.toHexString(val));
}
return sb.toString().toLowerCase();
}
/**
* base64编码
*
* @param str 内容
* @param charset 编码方式di
* @throws UnsupportedEncodingException
*/
private String base64(String str, String charset) throws UnsupportedEncodingException {
return base64Encode(str.getBytes(charset));
}
@SuppressWarnings("unused")
private String urlEncoder(String str, String charset) throws UnsupportedEncodingException {
return URLEncoder.encode(str, charset);
}
/**
* 电商Sign签名生成
*
* @param content 内容
* @param keyValue Appkey
* @param charset 编码方式
* @return DataSign签名
* @throws UnsupportedEncodingException ,Exception
*/
@SuppressWarnings("unused")
private String encrypt(String content, String keyValue, String charset) throws Exception {
if (keyValue != null) {
return base64(MD5(content + keyValue, charset), charset);
}
return base64(MD5(content, charset), charset);
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param params 请求的参数集合
* @return 远程资源的响应结果
*/
@SuppressWarnings("unused")
private String sendPost(String url, Map<String, String> params) {
OutputStreamWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
URL realUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
//发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
//POST方法
conn.setRequestMethod("POST");
//设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.connect();
//获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
//发送请求参数
if (params != null) {
StringBuilder param = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (param.length() > 0) {
param.append("&");
}
param.append(entry.getKey());
param.append("=");
param.append(entry.getValue());
}
out.write(param.toString());
}
//flush输出流的缓冲
out.flush();
//定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result.toString();
}
private static final char[] BASE64_ENCODE_CHARS = new char[]{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
public static String base64Encode(byte[] data) {
StringBuffer sb = new StringBuffer();
int len = data.length;
int i = 0;
int b1, b2, b3;
while (i < len) {
b1 = data[i++] & 0xff;
if (i == len) {
sb.append(BASE64_ENCODE_CHARS[b1 >>> 2]);
sb.append(BASE64_ENCODE_CHARS[(b1 & 0x3) << 4]);
sb.append("==");
break;
}
b2 = data[i++] & 0xff;
if (i == len) {
sb.append(BASE64_ENCODE_CHARS[b1 >>> 2]);
sb.append(BASE64_ENCODE_CHARS[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
sb.append(BASE64_ENCODE_CHARS[(b2 & 0x0f) << 2]);
sb.append("=");
break;
}
b3 = data[i++] & 0xff;
sb.append(BASE64_ENCODE_CHARS[b1 >>> 2]);
sb.append(BASE64_ENCODE_CHARS[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
sb.append(BASE64_ENCODE_CHARS[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
sb.append(BASE64_ENCODE_CHARS[b3 & 0x3f]);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,81 @@
package cn.lili.modules.member.entity.dos;
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.modules.member.entity.dto.ClerkAddDTO;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 店员Model
*
* @author wget
* @title: Clerk
* @projectName lilishop
* @date 2021/12/28 7:39 下午
*/
@Data
@TableName("li_clerk")
@ApiModel(value = "店员")
@NoArgsConstructor
@AllArgsConstructor
public class Clerk extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "店员名称")
private String clerkName;
@ApiModelProperty(value = "会员ID")
private String memberId;
@ApiModelProperty(value = "店铺ID")
private String storeId;
@ApiModelProperty(value = "所属部门id")
private String departmentId;
@ApiModelProperty(value = "角色id集合")
private String roleIds;
@ApiModelProperty(value = "是否是店主", hidden = true)
private Boolean shopkeeper = false;
@ApiModelProperty(value = "是否是超级管理员 超级管理员/普通管理员")
private Boolean isSuper = false;
@ApiModelProperty(value = "状态 默认true正常 false禁用")
private Boolean status = true;
/**
* 构建店员
*
* @param clerkAddDTO
*/
public Clerk(ClerkAddDTO clerkAddDTO) {
if (clerkAddDTO.getRoles()!=null && !clerkAddDTO.getRoles().isEmpty()) {
this.roleIds = CharSequenceUtil.join(",", clerkAddDTO.getRoles());
}
this.memberId = clerkAddDTO.getMemberId();
this.departmentId = clerkAddDTO.getDepartmentId();
this.storeId = clerkAddDTO.getStoreId();
this.clerkName = clerkAddDTO.getUsername();
}
public Clerk(Store store){
this.memberId = store.getMemberId();
this.storeId = store.getId();
this.clerkName = store.getMemberName();
this.setShopkeeper(true);
this.setIsSuper(true);
this.setStatus(true);
}
}

View File

@@ -101,7 +101,7 @@ public class Member extends BaseEntity {
this.username = username;
this.password = password;
this.mobile = mobile;
this.nickName = mobile;
this.nickName = "临时昵称";
this.disabled = true;
this.haveStore = false;
this.sex = 0;

View File

@@ -1,11 +1,13 @@
package cn.lili.modules.member.entity.dos;
import cn.lili.mybatis.BaseEntity;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.security.sensitive.Sensitive;
import cn.lili.common.security.sensitive.enums.SensitiveStrategy;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.member.entity.dto.MemberEvaluationDTO;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -50,6 +52,7 @@ public class MemberEvaluation extends BaseEntity {
@NotNull
@ApiModelProperty(value = "会员名称")
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String memberName;
@NotNull
@@ -108,28 +111,28 @@ public class MemberEvaluation extends BaseEntity {
private Integer descriptionScore;
public MemberEvaluation(MemberEvaluationDTO memberEvaluationDTO, GoodsSku goodsSku, Member member,Order order){
public MemberEvaluation(MemberEvaluationDTO memberEvaluationDTO, GoodsSku goodsSku, Member member, Order order) {
//复制评价信息
BeanUtils.copyProperties(memberEvaluationDTO, this);
//设置会员
this.memberId=member.getId();
this.memberId = member.getId();
//会员名称
this.memberName=member.getNickName();
this.memberName = member.getNickName();
//设置会员头像
this.memberProfile=member.getFace();
this.memberProfile = member.getFace();
//商品名称
this.goodsName=goodsSku.getGoodsName();
this.goodsName = goodsSku.getGoodsName();
//商品图片
this.goodsImage=goodsSku.getThumbnail();
this.goodsImage = goodsSku.getThumbnail();
//设置店铺ID
this.storeId=order.getStoreId();
this.storeId = order.getStoreId();
//设置店铺名称
this.storeName=order.getStoreName();
this.storeName = order.getStoreName();
//设置订单编号
this.orderNo=order.getSn();
this.orderNo = order.getSn();
//是否包含图片
this.haveImage=StringUtils.isNotEmpty(memberEvaluationDTO.getImages());
this.haveImage = StringUtils.isNotEmpty(memberEvaluationDTO.getImages());
//默认开启评价
this.status=SwitchEnum.OPEN.name();
this.status = SwitchEnum.OPEN.name();
}
}

View File

@@ -1,6 +1,8 @@
package cn.lili.modules.member.entity.dos;
import cn.lili.common.security.sensitive.Sensitive;
import cn.lili.common.security.sensitive.enums.SensitiveStrategy;
import cn.lili.mybatis.BaseIdEntity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
@@ -43,6 +45,8 @@ public class MemberPointsHistory extends BaseIdEntity {
@ApiModelProperty(value = "会员ID")
private String memberId;
@Sensitive(strategy = SensitiveStrategy.PHONE)
@ApiModelProperty(value = "会员名称")
private String memberName;

View File

@@ -0,0 +1,36 @@
package cn.lili.modules.member.entity.dos;
import cn.lili.mybatis.BaseIdEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户角色
*
* @author Chopper
* @since 2020/11/19 12:18
*/
@Data
@TableName("li_clerk_role")
@ApiModel(value = "用户角色")
@Builder
@NoArgsConstructor
public class StoreClerkRole extends BaseIdEntity {
@ApiModelProperty(value = "店员唯一id")
private String clerkId;
@ApiModelProperty(value = "角色唯一id")
private String roleId;
public StoreClerkRole(String clerkId, String roleId) {
this.clerkId = clerkId;
this.roleId = roleId;
}
}

View File

@@ -0,0 +1,37 @@
package cn.lili.modules.member.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 javax.validation.constraints.NotEmpty;
/**
* 部门
*
* @author Chopper
* @since 2020/11/19 11:57
*/
@Data
@TableName("li_store_department")
@ApiModel(value = "店铺部门")
public class StoreDepartment extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "店铺id", hidden = true)
private String storeId;
@ApiModelProperty(value = "部门名称")
@NotEmpty(message = "部门名称不能为空")
private String title;
@ApiModelProperty(value = "父id")
@NotEmpty(message = "父id不能为空")
private String parentId;
@ApiModelProperty(value = "排序值")
private Double sortOrder;
}

View File

@@ -0,0 +1,34 @@
package cn.lili.modules.member.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.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 角色部门绑定关系
*
* @author Chopper
* @since 2020/11/19 12:18
*/
@Data
@TableName("li_store_department_role")
@ApiModel(value = "店铺角色部门")
@NoArgsConstructor
@AllArgsConstructor
public class StoreDepartmentRole extends BaseEntity {
private static final long serialVersionUID = 2342812932116647050L;
@ApiModelProperty(value = "角色id")
private String roleId;
@ApiModelProperty(value = "部门id")
private String departmentId;
}

View File

@@ -0,0 +1,48 @@
package cn.lili.modules.member.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;
/**
* 菜单权限
*
* @author Chopper
* @since 2020/11/19 12:12
*/
@Data
@TableName("li_store_menu")
@ApiModel(value = "店铺菜单权限")
public class StoreMenu extends BaseEntity {
private static final long serialVersionUID = 7050744476203495207L;
@ApiModelProperty(value = "菜单标题")
private String title;
@ApiModelProperty(value = "路由名称")
private String name;
@ApiModelProperty(value = "路径")
private String path;
@ApiModelProperty(value = "菜单层级")
private Integer level;
@ApiModelProperty(value = "前端目录文件")
private String frontRoute;
@ApiModelProperty(value = "父id")
private String parentId = "0";
@ApiModelProperty(value = "排序值")
private Double sortOrder;
@ApiModelProperty(value = "权限URL*号模糊匹配,逗号分割")
private String permission;
}

View File

@@ -0,0 +1,35 @@
package cn.lili.modules.member.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;
/**
* 角色权限绑定关系
*
* @author Chopper
* @since 2020/11/19 12:18
*/
@Data
@TableName("li_store_menu_role")
@ApiModel(value = "店铺角色权限")
public class StoreMenuRole extends BaseEntity {
private static final long serialVersionUID = -4680260092546996026L;
@ApiModelProperty(value = "角色id")
private String roleId;
@ApiModelProperty(value = "菜单")
private String menuId;
@ApiModelProperty(value = "店铺id")
private String storeId;
@ApiModelProperty(value = "是否拥有操作数据权限,为否则只有查看权限")
private Boolean isSuper;
}

View File

@@ -0,0 +1,36 @@
package cn.lili.modules.member.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 javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* 部门
*
* @author Chopper
* @since 2020/11/19 11:57
*/
@Data
@TableName("li_store_role")
@ApiModel(value = "店铺角色")
public class StoreRole extends BaseEntity {
@ApiModelProperty(value = "角色名")
@NotEmpty(message = "角色名称必填")
private String name;
@ApiModelProperty(value = "店铺id", hidden = true)
private String storeId;
@ApiModelProperty(value = "是否为注册默认角色")
private Boolean defaultRole = false;
@ApiModelProperty(value = "备注")
private String description;
}

View File

@@ -0,0 +1,64 @@
package cn.lili.modules.member.entity.dto;
import cn.lili.common.security.sensitive.Sensitive;
import cn.lili.common.security.sensitive.enums.SensitiveStrategy;
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;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.List;
/**
* 店员dto
*
* @author wget
* @title: Clerk
* @projectName lilishop
* @date 2021/12/28 7:39 下午
*/
@Data
@NoArgsConstructor
public class ClerkAddDTO {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "会员用户名")
@NotEmpty(message = "会员用户名不能为空")
@Length(max = 30, message = "会员用户名不能超过20个字符")
private String username;
@ApiModelProperty(value = "会员密码")
@NotEmpty(message = "会员密码不能为空")
private String password;
@NotEmpty(message = "手机号码不能为空")
@ApiModelProperty(value = "手机号码", required = true)
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String mobile;
@ApiModelProperty(value = "所属部门id")
private String departmentId;
@ApiModelProperty(value = "是否是超级管理员 超级管理员/普通管理员")
private Boolean isSuper = false;
@ApiModelProperty(value = "角色")
private List<String> roles;
@ApiModelProperty(value = "会员id", required = true)
private String memberId;
@ApiModelProperty(value = "是否是店主", hidden = true)
private Boolean shopkeeper = false;
@ApiModelProperty(value = "店铺id", hidden = true)
private String storeId;
}

View File

@@ -0,0 +1,46 @@
package cn.lili.modules.member.entity.dto;
import cn.lili.common.security.sensitive.Sensitive;
import cn.lili.common.security.sensitive.enums.SensitiveStrategy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 店员dto
*
* @author wget
* @title: Clerk
* @projectName lilishop
* @date 2021/12/28 7:39 下午
*/
@Data
@NoArgsConstructor
public class ClerkEditDTO {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "店员id", hidden = true)
private String id;
@ApiModelProperty(value = "会员密码")
private String password;
@ApiModelProperty(value = "状态")
private Boolean status;
@ApiModelProperty(value = "所属部门id")
private String departmentId;
@ApiModelProperty(value = "是否是超级管理员 超级管理员/普通管理员")
private Boolean isSuper = false;
@ApiModelProperty(value = "角色")
private List<String> roles;
}

View File

@@ -0,0 +1,48 @@
package cn.lili.modules.member.entity.dto;
import cn.lili.mybatis.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
/**
* 管理员入库dto
*
* @author Chopper
* @since 2020/11/16 19:55
*/
@Data
@ApiModel(value = "店员操作dto")
public class ClerkOperationDTO extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户名")
@Length(max = 20,message = "用户名长度不能超过20个字符")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "昵称")
@Length(max = 10,message = "昵称长度不能超过10个字符")
private String nickName;
@ApiModelProperty(value = "手机")
@Length(max = 11,message = "手机号长度不能超过11")
private String mobile;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "描述/详情/备注")
private String description;
@ApiModelProperty(value = "所属部门id")
private String departmentId;
@ApiModelProperty(value = "是否为超级管理员")
private Boolean isSuper;
}

View File

@@ -0,0 +1,41 @@
package cn.lili.modules.member.entity.dto;
import cn.lili.mybatis.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
/**
* 店员查询
*
* @author Chopper
* @since 2020/11/16 19:55
*/
@Data
@ApiModel(value = "店员查询")
public class ClerkQueryDTO extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "店员名称")
@Length(max = 20, message = "用户名长度不能超过20个字符")
private String clerkName;
@ApiModelProperty(value = "手机")
@Length(max = 11, message = "手机号长度不能超过11")
private String mobile;
@ApiModelProperty(value = "所属部门id")
private String departmentId;
@ApiModelProperty(value = "是否为超级管理员")
private Boolean isSuper;
@ApiModelProperty(value = "状态")
private Boolean status;
@ApiModelProperty(value = "店铺id", hidden = true)
private String storeId;
}

View File

@@ -21,8 +21,7 @@ import java.util.Date;
@Data
public class ManagerMemberEditDTO {
@ApiModelProperty(value = "会员用户名,用户名不能进行修改", required = true)
@NotNull(message = "会员用户名不能为空")
@NotNull(message = "用户ID不能为空")
private String id;
@ApiModelProperty(value = "会员用户名,用户名不能进行修改", required = true)

View File

@@ -0,0 +1,46 @@
package cn.lili.modules.member.entity.enums;
import lombok.Getter;
@Getter
public enum QRCodeLoginSessionStatusEnum {
/**
* 二维码创建完毕等待app端扫码
*/
WAIT_SCANNING(0,"等待扫码"),
/**
* app端已经扫码等待确认同意登录
*/
SCANNING(1,"已经扫码"),
/**
* 用户在app端点击了同意登录
*/
VERIFIED(2,"确认登录"),
/**
* 用户在app端点击了取消登录
*/
CANCELED(3,"取消登录"),
/**
* 二维码不存在/或者已经过期
*/
NO_EXIST(4,"二维码已过期")
;
private Integer code;
private String desc;
QRCodeLoginSessionStatusEnum(Integer code,String desc){
this.code = code;
this.desc = desc;
}
}

View File

@@ -0,0 +1,44 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.common.utils.BeanUtil;
import cn.lili.modules.member.entity.dos.Clerk;
import cn.lili.modules.member.entity.dos.StoreMenu;
import cn.lili.modules.member.entity.dos.StoreRole;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 管理员VO
*
* @author Chopper
* @since 2020-11-22 09:17
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClerkVO extends Clerk {
private static final long serialVersionUID = -2378384199695839312L;
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "所属部门名称")
private String departmentTitle;
@ApiModelProperty(value = "用户拥有角色")
private List<StoreRole> roles;
@ApiModelProperty(value = "用户拥有的权限")
private List<StoreMenu> menus;
public ClerkVO(Clerk clerk) {
BeanUtil.copyProperties(clerk, this);
}
}

View File

@@ -32,7 +32,7 @@ public class MemberVO implements Serializable {
private String username;
@ApiModelProperty(value = "昵称")
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String nickName;
@ApiModelProperty(value = "会员性别,1为男0为女")

View File

@@ -0,0 +1,21 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.modules.member.entity.enums.QRCodeLoginSessionStatusEnum;
import lombok.Data;
import java.io.Serializable;
@Data
public class QRCodeLoginSessionVo implements Serializable {
private static final long serialVersionUID = 8793639296995408322L;
private String token;
private Integer status;
private long duration;
private long userId;
}

View File

@@ -0,0 +1,12 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.common.security.token.Token;
import lombok.Data;
@Data
public class QRLoginResultVo {
private Token token;
private int status;
}

View File

@@ -0,0 +1,28 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.common.utils.BeanUtil;
import cn.lili.modules.member.entity.dos.StoreDepartment;
import cn.lili.modules.permission.entity.dos.Department;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 部门VO
*
* @author Chopper
* @since 2020-11-23 18:48
*/
@Data
public class StoreDepartmentVO extends StoreDepartment {
private List<StoreDepartmentVO> children = new ArrayList<>();
public StoreDepartmentVO() {
}
public StoreDepartmentVO(StoreDepartment storeDepartment) {
BeanUtil.copyProperties(storeDepartment, this);
}
}

View File

@@ -0,0 +1,45 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.common.utils.BeanUtil;
import cn.lili.modules.member.entity.dos.StoreMenu;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* 菜单VO 展示模型
*
* @author Chopper
* @since 2020/11/20 15:38
*/
@Data
public class StoreMenuVO extends StoreMenu {
@ApiModelProperty(value = "子菜单")
private List<StoreMenuVO> children = new ArrayList<>();
public StoreMenuVO() {
}
public StoreMenuVO(StoreMenu storeMenu) {
BeanUtil.copyProperties(storeMenu, this);
}
public List<StoreMenuVO> getChildren() {
if (children != null) {
children.sort(new Comparator<StoreMenuVO>() {
@Override
public int compare(StoreMenuVO o1, StoreMenuVO o2) {
return o1.getSortOrder().compareTo(o2.getSortOrder());
}
});
return children;
}
return null;
}
}

View File

@@ -0,0 +1,29 @@
package cn.lili.modules.member.entity.vo;
import cn.lili.modules.member.entity.dos.StoreMenu;
import cn.lili.modules.permission.entity.dos.Menu;
import lombok.Data;
/**
* RoleMenuVO
*
* @author Chopper
* @since 2020-11-24 11:45
*/
@Data
public class StoreUserMenuVO extends StoreMenu {
private static final long serialVersionUID = -7478870595109016162L;
/**
* 是否是超级管理员
*/
private Boolean isSuper;
public Boolean getSuper() {
if (this.isSuper == null) {
return false;
}
return isSuper;
}
}

View File

@@ -0,0 +1,34 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.Clerk;
import cn.lili.modules.member.entity.vo.ClerkVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* 店员数据处理层
*
* @author wget
* @title: ClerkMapper
* @projectName lilishop
* @date 2021/12/28 7:39 下午
*/
public interface ClerkMapper extends BaseMapper<Clerk> {
/**
* 查询店员分页数据
* @param page 分页信息
* @param ew 店铺ID
* @return
*/
@Select("select li_clerk.*,m.id,m.mobile as mobile from li_clerk inner join li_member as m on li_clerk.member_id = m.id ${ew.customSqlSegment}")
IPage<ClerkVO> selectClerkPage(Page page, @Param(Constants.WRAPPER) QueryWrapper ew);
}

View File

@@ -23,7 +23,8 @@ public interface FootprintMapper extends BaseMapper<FootPrint> {
*
* @param memberId 会员ID
*/
@Delete("DELETE FROM li_foot_print l1 WHERE l1.id IN (" +
@Delete("DELETE FROM li_foot_print WHERE id IN ("+
"SELECT l2.id FROM (" +
"SELECT l3.id FROM li_foot_print l3 WHERE l3.member_id=${memberId} ORDER BY id DESC LIMIT 100,100) l2)")
void deleteLastFootPrint(String memberId);

View File

@@ -0,0 +1,13 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreClerkRole;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 角色权限数据处理层
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreClerkRoleMapper extends BaseMapper<StoreClerkRole> {
}

View File

@@ -0,0 +1,14 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreDepartment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 部门数据处理层
*
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreDepartmentMapper extends BaseMapper<StoreDepartment> {
}

View File

@@ -0,0 +1,14 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreDepartmentRole;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 店铺部门角色数据处理层
*
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreDepartmentRoleMapper extends BaseMapper<StoreDepartmentRole> {
}

View File

@@ -21,7 +21,7 @@ public interface StoreLogisticsMapper extends BaseMapper<StoreLogistics> {
* @param storeId 店铺ID
* @return 物流公司列表
*/
@Select("SELECT l.* FROM li_logistics l RIGHT JOIN li_store_logistics sl ON l.id=sl.logistics_id WHERE sl.store_id=#{storeId} AND l.disabled='OPEN'")
@Select("SELECT l.id as logistics_id,l.name FROM li_logistics l RIGHT JOIN li_store_logistics sl ON l.id=sl.logistics_id WHERE sl.store_id=#{storeId} AND l.disabled='OPEN'")
List<StoreLogisticsVO> getSelectedStoreLogistics(String storeId);
/**
@@ -39,7 +39,35 @@ public interface StoreLogisticsMapper extends BaseMapper<StoreLogistics> {
* @param storeId 店铺列表
* @return 店铺地址VO列表
*/
@Select("SELECT *, ( SELECT sl.id FROM li_store_logistics sl WHERE l.id = sl.logistics_id AND sl.store_id=#{storeId} ) AS selected FROM li_logistics l WHERE l.disabled='OPEN';")
@Select("SELECT id as logistics_id , `name` , ( SELECT sl.id FROM li_store_logistics sl WHERE l.id = sl.logistics_id AND sl.store_id=#{storeId} ) AS selected,(SELECT sl.face_sheet_flag FROM li_store_logistics sl WHERE l.id = sl.logistics_id AND sl.store_id = #{storeId}) as face_sheet_flag FROM li_logistics l WHERE l.disabled='OPEN';")
//@Select("SELECT *, ( SELECT sl.id FROM li_store_logistics sl WHERE l.id = sl.logistics_id AND sl.store_id=#{storeId} ) AS selected FROM li_logistics l WHERE l.disabled='OPEN';")
List<StoreLogisticsVO> getStoreLogistics(String storeId);
/**
* 店铺已选择的物流公司
* @param storeId 店铺Id
* @return 物流公司列表
*/
@Select("SELECT sl.logistics_id,l.name,sl.face_sheet_flag FROM li_logistics l INNER JOIN li_store_logistics sl on sl.logistics_id=l.id WHERE l.disabled = 'OPEN' AND store_id=#{storeId};")
List<StoreLogisticsVO> getOpenStoreLogistics(String storeId);
/**
* 店铺未选择的物流公司
* @param storeId 店铺Id
* @return 物流公司列表
*/
@Select("SELECT id as logistics_id,name FROM li_logistics WHERE id not in(SELECT logistics_id FROM li_store_logistics WHERE store_id=#{storeId}) AND disabled = 'OPEN'")
List<StoreLogisticsVO> getCloseStroreLogistics(String storeId);
/**
* 获取店铺选择的物流公司并使用了电子面单
*
* @param storeId 店铺ID
* @return 物流公司列表
*/
@Select("SELECT id as logistics_id , `name` FROM li_logistics WHERE disabled='OPEN'" +
"AND id in(SELECT logistics_id FROM li_store_logistics WHERE store_id=#{storeId} and face_sheet_flag=1)")
List<StoreLogisticsVO> getSelectedStoreLogisticsUseFaceSheet(String storeId);
}

View File

@@ -0,0 +1,44 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreMenu;
import cn.lili.modules.member.entity.vo.StoreUserMenuVO;
import cn.lili.modules.permission.entity.dos.Menu;
import cn.lili.modules.permission.entity.vo.UserMenuVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 菜单数据处理层
*
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreMenuMapper extends BaseMapper<StoreMenu> {
/**
* 根据用户获取菜单列表
*
* @param userId 用户ID
* @return 菜单列表
*/
@Select("SELECT menu.* FROM li_store_menu AS menu WHERE menu.id IN (" +
"SELECT rm.menu_id FROM li_store_menu_role AS rm WHERE rm.role_id IN (" +
"SELECT ur.role_id FROM li_clerk_role AS ur WHERE ur.clerk_id=#{userId}) OR rm.role_id IN (" +
"SELECT dr.role_id FROM li_store_department_role AS dr WHERE dr.department_id=(" +
"SELECT department_id FROM li_clerk AS au WHERE au.id = #{userId})))")
List<StoreMenu> findByUserId(String userId);
/**
* 根据用户获取菜单权限
*
* @param userId 用户ID
* @return 用户菜单VO列表
*/
@Select("SELECT rm.is_super as is_super,m.*FROM li_store_menu AS m INNER JOIN li_store_menu_role AS rm ON rm.menu_id=m.id WHERE rm.role_id IN (" +
"SELECT ur.role_id FROM li_clerk_role AS ur WHERE ur.clerk_id=#{userId}) OR rm.role_id IN (" +
"SELECT dr.role_id FROM li_store_department_role AS dr INNER JOIN li_clerk AS au ON au.department_id=dr.department_id " +
"WHERE au.id=#{userId}) GROUP BY m.id,rm.is_super ORDER BY rm.is_super desc")
List<StoreUserMenuVO> getUserRoleMenu(String userId);
}

View File

@@ -0,0 +1,14 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreMenuRole;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 角色菜单数据处理层
*
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreMenuRoleMapper extends BaseMapper<StoreMenuRole> {
}

View File

@@ -0,0 +1,15 @@
package cn.lili.modules.member.mapper;
import cn.lili.modules.member.entity.dos.StoreRole;
import cn.lili.modules.permission.entity.dos.Role;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 店铺角色数据处理层
*
* @author Chopper
* @since 2020-11-22 09:17
*/
public interface StoreRoleMapper extends BaseMapper<StoreRole> {
}

View File

@@ -0,0 +1,99 @@
package cn.lili.modules.member.service;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.member.entity.dos.Clerk;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dto.ClerkAddDTO;
import cn.lili.modules.member.entity.dto.ClerkEditDTO;
import cn.lili.modules.member.entity.dto.ClerkQueryDTO;
import cn.lili.modules.member.entity.vo.ClerkVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 店员业务层
*
* @author wget
* @title: ClerkService
* @projectName lilishop
* @date 2021/12/28 7:42 下午
*/
public interface ClerkService extends IService<Clerk> {
/**
* 店员查询
*
* @param page
* @param clerkQueryDTO
* @return
*/
IPage<ClerkVO> clerkForPage(PageVO page, ClerkQueryDTO clerkQueryDTO);
/**
* 查询店员详细
*
* @param id 店员id
* @return
*/
ClerkVO get(String id);
/**
* 修改店员信息
*
* @param clerkEditDTO 店员
* @return
*/
Clerk updateClerk(ClerkEditDTO clerkEditDTO);
/**
* 保存店员
*
* @param clerkAddDTO 店员
* @return
*/
Clerk saveClerk(ClerkAddDTO clerkAddDTO);
/**
* 根据会员id获取店员信息
*
* @param memberId 会员id
* @return
*/
Clerk getClerkByMemberId(String memberId);
/**
* 重置店员密码
*
* @param ids 店员ids
*/
void resetPassword(List<String> ids);
/**
* 删除店员
*
* @param ids 店员ids
*/
void deleteClerk(List<String> ids);
/**
* 检测会员有效性
*
* @param mobile 手机号码
* @return
*/
Member checkClerk(String mobile);
/**
* 店员状态操作
*
* @param id 店员id
* @param status 状态
*/
void disable(String id, Boolean status);
}

View File

@@ -11,6 +11,8 @@ import cn.lili.modules.member.entity.dto.MemberAddDTO;
import cn.lili.modules.member.entity.dto.MemberEditDTO;
import cn.lili.modules.member.entity.vo.MemberSearchVO;
import cn.lili.modules.member.entity.vo.MemberVO;
import cn.lili.modules.member.entity.vo.QRLoginResultVo;
import cn.lili.modules.member.entity.vo.QRCodeLoginSessionVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -24,7 +26,6 @@ import java.util.Map;
* @since 2020-02-25 14:10:16
*/
public interface MemberService extends IService<Member> {
/**
* 默认密码
*/
@@ -38,12 +39,13 @@ public interface MemberService extends IService<Member> {
Member getUserInfo();
/**
* 是否可以通过手机获取用户
* 通过手机获取用户
*
* @param uuid UUID
* @param mobile 手机号
* @return 操作状态
*/
Member findByMobile(String mobile);
boolean findByMobile(String uuid, String mobile);
/**
@@ -97,6 +99,16 @@ public interface MemberService extends IService<Member> {
*/
Member modifyPass(String oldPassword, String newPassword);
/**
* 注册会员
*
* @param userName 会员
* @param password 密码
* @param mobilePhone mobilePhone
* @return 处理结果
*/
Token register(String userName, String password, String mobilePhone);
/**
* 是否可以初始化密码
*
@@ -119,17 +131,6 @@ public interface MemberService extends IService<Member> {
* @return 操作结果
*/
void cancellation(String password);
/**
* 注册会员
*
* @param userName 会员
* @param password 密码
* @param mobilePhone mobilePhone
* @return 处理结果
*/
Token register(String userName, String password, String mobilePhone);
/**
* 修改当前会员的手机号
*
@@ -250,6 +251,24 @@ public interface MemberService extends IService<Member> {
*/
void logout(UserEnums userEnums);
/**
* <<<<<<< HEAD
* 修改会员是否拥有店铺
*
* @param haveStore 是否拥有店铺
* @param storeId 店铺id
* @param memberIds 会员id
* @return
*/
void updateHaveShop(Boolean haveStore, String storeId, List<String> memberIds);
/**
* 重置会员密码为123456
*
* @param ids 会员id
*/
void resetPassword(List<String> ids);
/**
* 获取所有会员的手机号
*
@@ -267,9 +286,16 @@ public interface MemberService extends IService<Member> {
/**
* 获取用户VO
*
* @param id 会员id
* @return 用户VO
*/
MemberVO getMember(String id);
QRCodeLoginSessionVo createPcSession();
Object appScanner(String token);
boolean appSConfirm(String token, Integer code);
QRLoginResultVo loginWithSession(String token);
}

View File

@@ -0,0 +1,41 @@
package cn.lili.modules.member.service;
import cn.lili.modules.member.entity.dos.StoreClerkRole;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 店铺店员角色业务层
*
* @author Chopper
* @since 2020/11/17 3:46 下午
*/
public interface StoreClerkRoleService extends IService<StoreClerkRole> {
/**
* 根据用户查看拥有的角色
*
* @param clerkId 店员id
* @return
*/
List<StoreClerkRole> listByUserId(String clerkId);
/**
* 根据店员id查看角色
*
* @param clerkId 店员id
* @return
*/
List<String> listId(String clerkId);
/**
* 更新用户拥有的角色
*
* @param clerkId 店员id
* @param storeClerkRoles 角色权限
*/
void updateClerkRole(String clerkId, List<StoreClerkRole> storeClerkRoles);
}

View File

@@ -0,0 +1,38 @@
package cn.lili.modules.member.service;
import cn.lili.modules.member.entity.dos.StoreDepartmentRole;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 部门角色业务层
*
* @author Chopper
* @since 2020/11/22 12:08
*/
public interface StoreDepartmentRoleService extends IService<StoreDepartmentRole> {
/**
* 根据部门获取角色集合
*
* @param storeDepartmentId 店铺部门id
* @return
*/
List<StoreDepartmentRole> listByDepartmentId(String storeDepartmentId);
/**
* 更新部门角色关联
*
* @param storeDepartmentId 店铺部门id
* @param storeDepartmentRoles 店铺部门角色
*/
void updateByDepartmentId(String storeDepartmentId, List<StoreDepartmentRole> storeDepartmentRoles);
/**
* 根据部门id删除部门与角色关联
*
* @param ids id集合
*/
void deleteByDepartment(List<String> ids);
}

View File

@@ -0,0 +1,40 @@
package cn.lili.modules.member.service;
import cn.lili.modules.member.entity.dos.StoreDepartment;
import cn.lili.modules.member.entity.vo.StoreDepartmentVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 店铺部门业务层
*
* @author Chopper
* @since 2020/11/17 3:43 下午
*/
public interface StoreDepartmentService extends IService<StoreDepartment> {
/**
* 获取部门树
*
* @param initWrapper
* @return
*/
List<StoreDepartmentVO> tree(QueryWrapper<StoreDepartment> initWrapper);
/**
* 删除部门
*
* @param ids
*/
void deleteByIds(List<String> ids);
/**
* 更新店铺部门
*
* @param storeDepartment 店铺部门
* @return
*/
Boolean update(StoreDepartment storeDepartment);
}

View File

@@ -1,6 +1,7 @@
package cn.lili.modules.member.service;
import cn.lili.modules.store.entity.dos.StoreLogistics;
import cn.lili.modules.store.entity.dto.StoreLogisticsCustomerDTO;
import cn.lili.modules.system.entity.vo.StoreLogisticsVO;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -45,7 +46,48 @@ public interface StoreLogisticsService extends IService<StoreLogistics> {
* @param storeId 店铺id
* @return 店铺物流公司
*/
StoreLogistics add(String logisticsId, String storeId);
StoreLogistics add(String logisticsId, String storeId, StoreLogisticsCustomerDTO storeLogisticsCustomerDTO);
/**
* 获取当前店铺已选择的物流公司并使用电子面单列表
*
* @param storeId 店铺id
* @return 物流公司列表
*/
List<StoreLogisticsVO> getStoreSelectedLogisticsUseFaceSheet(String storeId);
/**
* 修改店铺-物流公司电子面单参数
* @param logisticsId 物流公司设置id
* @param storeId 店铺id
* @return 店铺物流公司
*/
StoreLogistics update(String logisticsId, String storeId, StoreLogisticsCustomerDTO storeLogisticsCustomerDTO);
/**
* 获取店铺物流信息回填
* @param logisticsId 物流id
* @return 店铺物流信息
*/
StoreLogistics getStoreLogisticsInfo(String logisticsId);
/**
* 获取当前店铺已开启的物流公司列表
*
* @param storeId 店铺id
* @return 物流公司列表
*/
List<StoreLogisticsVO> getOpenStoreLogistics(String storeId);
/**
* 获取当前店铺未开启的物流公司列表
*
* @param storeId 店铺id
* @return 物流公司列表
*/
List<StoreLogisticsVO> getCloseStoreLogistics(String storeId);
}

View File

@@ -0,0 +1,57 @@
package cn.lili.modules.member.service;
import cn.lili.modules.member.entity.dos.StoreMenuRole;
import cn.lili.modules.member.entity.vo.StoreUserMenuVO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 角色菜单接口
*
* @author Chopper
* @since 2020/11/22 11:43
*/
public interface StoreMenuRoleService extends IService<StoreMenuRole> {
/**
* 通过角色获取菜单权限列表
*
* @param roleId
* @return
*/
List<StoreMenuRole> findByRoleId(String roleId);
/**
* 根据角色集合获取拥有的菜单具体权限
*
* @param clerkId
* @return
*/
List<StoreUserMenuVO> findAllMenu(String clerkId,String memberId);
/**
* 更新某角色拥有到菜单
*
* @param roleId 角色id
* @param roleMenus
*/
void updateRoleMenu(String roleId, List<StoreMenuRole> roleMenus);
/**
* 根据角色id 删除数据
*
* @param roleId
*/
void delete(String roleId);
/**
* 根据角色id 删除数据
*
* @param roleId
*/
void delete(List<String> roleId);
}

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