Kaynağa Gözat

2022年9月28日17:21:01

纪新园 3 yıl önce
ebeveyn
işleme
63762eda9b
17 değiştirilmiş dosya ile 2028 ekleme ve 201 silme
  1. 18 0
      blade-common/pom.xml
  2. 115 0
      blade-common/src/main/java/org/springblade/common/utils/ProtoStuffSerializerUtil.java
  3. 1406 0
      blade-common/src/main/java/org/springblade/common/utils/RedisUtil.java
  4. 8 0
      blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IGoodsDescClient.java
  5. 31 0
      blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IRedisClient.java
  6. 14 0
      blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IStorageClient.java
  7. 22 0
      blade-service-api/blade-client-api/src/main/java/org/springblade/client/goods/enums/RedisKey.java
  8. 10 0
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java
  9. 7 0
      blade-service-api/trade-purchase-api/src/main/java/com/trade/purchase/order/entity/Order.java
  10. 92 0
      blade-service/blade-client/src/main/java/org/springblade/client/RedisClient.java
  11. 9 0
      blade-service/blade-client/src/main/java/org/springblade/client/goods/feign/GoodsDescClient.java
  12. 17 0
      blade-service/blade-client/src/main/java/org/springblade/client/storage/feign/StorageClient.java
  13. 9 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java
  14. 50 54
      blade-service/trade-purchase/src/main/java/com/trade/purchase/excel/CMYWarehousingExcel.java
  15. 21 136
      blade-service/trade-purchase/src/main/java/com/trade/purchase/order/controller/WoodHarvestingCloudController.java
  16. 17 1
      blade-service/trade-purchase/src/main/java/com/trade/purchase/order/service/IOrderService.java
  17. 182 10
      blade-service/trade-purchase/src/main/java/com/trade/purchase/order/service/impl/OrderServiceImpl.java

+ 18 - 0
blade-common/pom.xml

@@ -22,6 +22,24 @@
             <version>3.1.1</version>
         </dependency>
 
+        <!--Redis 依赖包-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dyuproject.protostuff</groupId>
+            <artifactId>protostuff-core</artifactId>
+            <version>1.0.8</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dyuproject.protostuff</groupId>
+            <artifactId>protostuff-runtime</artifactId>
+            <version>1.0.8</version>
+        </dependency>
+
         <!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
         <dependency>
             <groupId>com.google.zxing</groupId>

+ 115 - 0
blade-common/src/main/java/org/springblade/common/utils/ProtoStuffSerializerUtil.java

@@ -0,0 +1,115 @@
+package org.springblade.common.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import com.dyuproject.protostuff.LinkedBuffer;
+import com.dyuproject.protostuff.ProtostuffIOUtil;
+import com.dyuproject.protostuff.Schema;
+import com.dyuproject.protostuff.runtime.RuntimeSchema;
+
+public class ProtoStuffSerializerUtil {
+
+	/**
+	 * 序列化对象
+	 * @param obj
+	 * @return
+	 */
+	public static <T> byte[] serialize(T obj) {
+		if (obj == null) {
+			throw new RuntimeException("序列化对象(" + obj + ")!");
+		}
+		@SuppressWarnings("unchecked")
+		Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(obj.getClass());
+		LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
+		byte[] protostuff = null;
+		try {
+			protostuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
+		} catch (Exception e) {
+			throw new RuntimeException("序列化(" + obj.getClass() + ")对象(" + obj + ")发生异常!", e);
+		} finally {
+			buffer.clear();
+		}
+		return protostuff;
+	}
+
+	/**
+	 * 反序列化对象
+	 * @param paramArrayOfByte
+	 * @param targetClass
+	 * @return
+	 */
+	public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
+		if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
+			throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
+		}
+		T instance = null;
+		try {
+			instance = targetClass.newInstance();
+		} catch (InstantiationException  e1) {
+			throw new RuntimeException("反序列化过程中依据类型创建对象失败!", e1);
+		} catch(IllegalAccessException e2){
+			throw new RuntimeException("反序列化过程中依据类型创建对象失败!", e2);
+		}
+		Schema<T> schema = RuntimeSchema.getSchema(targetClass);
+		ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
+		return instance;
+	}
+
+	/**
+	 * 序列化列表
+	 * @param objList
+	 * @return
+	 */
+	public static <T> byte[] serializeList(List<T> objList) {
+		if (objList == null || objList.isEmpty()) {
+			throw new RuntimeException("序列化对象列表(" + objList + ")参数异常!");
+		}
+		@SuppressWarnings("unchecked")
+		Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
+		LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
+		byte[] protostuff = null;
+		ByteArrayOutputStream bos = null;
+		try {
+			bos = new ByteArrayOutputStream();
+			ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
+			protostuff = bos.toByteArray();
+		} catch (Exception e) {
+			throw new RuntimeException("序列化对象列表(" + objList + ")发生异常!", e);
+		} finally {
+			buffer.clear();
+			try {
+				if (bos != null) {
+					bos.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+
+		return protostuff;
+	}
+
+	/**
+	 * 反序列化列表
+	 * @param paramArrayOfByte
+	 * @param targetClass
+	 * @return
+	 */
+	public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class<T> targetClass) {
+		if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
+			throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
+		}
+
+		Schema<T> schema = RuntimeSchema.getSchema(targetClass);
+		List<T> result = null;
+		try {
+			result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);
+		} catch (IOException e) {
+			throw new RuntimeException("反序列化对象列表发生异常!", e);
+		}
+		return result;
+	}
+
+}

+ 1406 - 0
blade-common/src/main/java/org/springblade/common/utils/RedisUtil.java

@@ -0,0 +1,1406 @@
+package org.springblade.common.utils;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.data.redis.connection.DataType;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.core.Cursor;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.ScanOptions;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+public class RedisUtil {
+
+	private StringRedisTemplate redisTemplate;
+
+	public void setRedisTemplate(StringRedisTemplate redisTemplate) {
+		this.redisTemplate = redisTemplate;
+	}
+
+	public StringRedisTemplate getRedisTemplate() {
+		return this.redisTemplate;
+	}
+
+	/** -------------------key相关操作--------------------- */
+
+	/**
+	 * 删除key
+	 *
+	 * @param key
+	 */
+	public void delete(String key) {
+		redisTemplate.delete(key);
+	}
+
+	/**
+	 * 批量删除key
+	 *
+	 * @param keys
+	 */
+	public void delete(Collection<String> keys) {
+		redisTemplate.delete(keys);
+	}
+
+	/**
+	 * 序列化key
+	 *
+	 * @param key
+	 * @return
+	 */
+	public byte[] dump(String key) {
+		return redisTemplate.dump(key);
+	}
+
+	/**
+	 * 是否存在key
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Boolean hasKey(String key) {
+		return redisTemplate.hasKey(key);
+	}
+
+	/**
+	 * 设置过期时间
+	 * TimeUnit是时间单位,可选值有:
+	 *
+	 * 天:TimeUnit.DAYS、
+	 * 小时:TimeUnit.HOURS、
+	 * 分钟:TimeUnit.MINUTES、
+	 * 秒:TimeUnit.SECONDS、
+	 * 毫秒:TimeUnit.MILLISECONDS。
+	 * @param key
+	 * @param timeout
+	 * @param unit
+	 * @return
+	 */
+	public Boolean expire(String key, long timeout, TimeUnit unit) {
+		return redisTemplate.expire(key, timeout, unit);
+	}
+
+	/**
+	 * 设置过期时间
+	 *
+	 * @param key
+	 * @param date
+	 * @return
+	 */
+	public Boolean expireAt(String key, Date date) {
+		return redisTemplate.expireAt(key, date);
+	}
+
+	/**
+	 * 查找匹配的key
+	 *
+	 * @param pattern
+	 * @return
+	 */
+	public Set<String> keys(String pattern) {
+		return redisTemplate.keys(pattern);
+	}
+
+	/**
+	 * 将当前数据库的 key 移动到给定的数据库 db 当中
+	 *
+	 * @param key
+	 * @param dbIndex
+	 * @return
+	 */
+	public Boolean move(String key, int dbIndex) {
+		return redisTemplate.move(key, dbIndex);
+	}
+
+	/**
+	 * 移除 key 的过期时间,key 将持久保持
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Boolean persist(String key) {
+		return redisTemplate.persist(key);
+	}
+
+	/**
+	 * 返回 key 的剩余的过期时间
+	 *
+	 * @param key
+	 * @param unit
+	 * @return
+	 */
+	public Long getExpire(String key, TimeUnit unit) {
+		return redisTemplate.getExpire(key, unit);
+	}
+
+	/**
+	 * 返回 key 的剩余的过期时间
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long getExpire(String key) {
+		return redisTemplate.getExpire(key);
+	}
+
+	/**
+	 * 从当前数据库中随机返回一个 key
+	 *
+	 * @return
+	 */
+	public String randomKey() {
+		return redisTemplate.randomKey();
+	}
+
+	/**
+	 * 修改 key 的名称
+	 *
+	 * @param oldKey
+	 * @param newKey
+	 */
+	public void rename(String oldKey, String newKey) {
+		redisTemplate.rename(oldKey, newKey);
+	}
+
+	/**
+	 * 仅当 newkey 不存在时,将 oldKey 改名为 newkey
+	 *
+	 * @param oldKey
+	 * @param newKey
+	 * @return
+	 */
+	public Boolean renameIfAbsent(String oldKey, String newKey) {
+		return redisTemplate.renameIfAbsent(oldKey, newKey);
+	}
+
+	/**
+	 * 返回 key 所储存的值的类型
+	 *
+	 * @param key
+	 * @return
+	 */
+	public DataType type(String key) {
+		return redisTemplate.type(key);
+	}
+
+	/** -------------------string相关操作--------------------- */
+
+	/**
+	 * 设置指定 key 的值
+	 * @param key
+	 * @param value
+	 */
+	public void set(String key, String value) {
+		redisTemplate.opsForValue().set(key, value);
+	}
+
+	/**
+	 * 获取指定 key 的值
+	 * @param key
+	 * @return
+	 */
+	public String get(String key) {
+		return redisTemplate.opsForValue().get(key);
+	}
+
+	/**
+	 * 返回 key 中字符串值的子字符
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public String getRange(String key, long start, long end) {
+		return redisTemplate.opsForValue().get(key, start, end);
+	}
+
+	/**
+	 * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public String getAndSet(String key, String value) {
+		return redisTemplate.opsForValue().getAndSet(key, value);
+	}
+
+	/**
+	 * 对 key 所储存的字符串值,获取指定偏移量上的位(bit)
+	 *
+	 * @param key
+	 * @param offset
+	 * @return
+	 */
+	public Boolean getBit(String key, long offset) {
+		return redisTemplate.opsForValue().getBit(key, offset);
+	}
+
+	/**
+	 * 批量获取
+	 *
+	 * @param keys
+	 * @return
+	 */
+	public List<String> multiGet(Collection<String> keys) {
+		return redisTemplate.opsForValue().multiGet(keys);
+	}
+
+	/**
+	 * bit 位示图
+	 * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value
+	 *
+	 * @param key
+	 * @param offset
+	 *            位置
+	 * @param value
+	 *            值,true为1, false为0
+	 * @return
+	 */
+	public boolean setBit(String key, long offset, boolean value) {
+		return redisTemplate.opsForValue().setBit(key, offset, value);
+	}
+
+	/**
+	 * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
+	 *
+	 * @param key
+	 * @param value
+	 * @param timeout
+	 *            过期时间
+	 * @param unit
+	 *            时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
+	 *            秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
+	 */
+	public void setEx(String key, String value, long timeout, TimeUnit unit) {
+		redisTemplate.opsForValue().set(key, value, timeout, unit);
+	}
+
+	/**
+	 * 只有在 key 不存在时设置 key 的值
+	 *
+	 * @param key
+	 * @param value
+	 * @return 之前已经存在返回false,不存在返回true
+	 */
+	public boolean setIfAbsent(String key, String value) {
+		return redisTemplate.opsForValue().setIfAbsent(key, value);
+	}
+
+	/**
+	 * 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
+	 *
+	 * @param key
+	 * @param value
+	 * @param offset
+	 *            从指定位置开始覆写
+	 */
+	public void setRange(String key, String value, long offset) {
+		redisTemplate.opsForValue().set(key, value, offset);
+	}
+
+	/**
+	 * 获取字符串的长度
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long size(String key) {
+		return redisTemplate.opsForValue().size(key);
+	}
+
+	/**
+	 * 批量添加
+	 *
+	 * @param maps
+	 */
+	public void multiSet(Map<String, String> maps) {
+		redisTemplate.opsForValue().multiSet(maps);
+	}
+
+	/**
+	 * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
+	 *
+	 * @param maps
+	 * @return 之前已经存在返回false,不存在返回true
+	 */
+	public boolean multiSetIfAbsent(Map<String, String> maps) {
+		return redisTemplate.opsForValue().multiSetIfAbsent(maps);
+	}
+
+	/**
+	 * 增加(自增长), 负数则为自减
+	 *
+	 * @param key
+	 * @param increment
+	 * @return
+	 */
+	public Long incrBy(String key, long increment) {
+		return redisTemplate.opsForValue().increment(key, increment);
+	}
+
+	/**
+	 * 增加(自增长), 负数则为自减
+	 * @param key
+	 * @param increment
+	 * @return
+	 */
+	public Double incrByFloat(String key, double increment) {
+		return redisTemplate.opsForValue().increment(key, increment);
+	}
+
+	/**
+	 * 追加到末尾
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Integer append(String key, String value) {
+		return redisTemplate.opsForValue().append(key, value);
+	}
+
+	/** -------------------hash相关操作------------------------- */
+
+	/**
+	 * 获取存储在哈希表中指定字段的值
+	 *
+	 * @param key
+	 * @param field
+	 * @return
+	 */
+	public Object hGet(String key, String field) {
+		return redisTemplate.opsForHash().get(key, field);
+	}
+
+	/**
+	 * 获取所有给定字段的值
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Map<Object, Object> hGetAll(String key) {
+		return redisTemplate.opsForHash().entries(key);
+	}
+
+	/**
+	 * 获取所有给定字段的值
+	 *
+	 * @param key
+	 * @param fields
+	 * @return
+	 */
+	public List<Object> hMultiGet(String key, Collection<Object> fields) {
+		return redisTemplate.opsForHash().multiGet(key, fields);
+	}
+
+	public void hPut(String key, String hashKey, String value) {
+		redisTemplate.opsForHash().put(key, hashKey, value);
+	}
+
+	public void hPutAll(String key, Map<String, String> maps) {
+		redisTemplate.opsForHash().putAll(key, maps);
+	}
+
+	/**
+	 * 仅当hashKey不存在时才设置
+	 *
+	 * @param key
+	 * @param hashKey
+	 * @param value
+	 * @return
+	 */
+	public Boolean hPutIfAbsent(String key, String hashKey, String value) {
+		return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
+	}
+
+	/**
+	 * 删除一个或多个哈希表字段
+	 *
+	 * @param key
+	 * @param fields
+	 * @return
+	 */
+	public Long hDelete(String key, Object... fields) {
+		return redisTemplate.opsForHash().delete(key, fields);
+	}
+
+	/**
+	 * 查看哈希表 key 中,指定的字段是否存在
+	 *
+	 * @param key
+	 * @param field
+	 * @return
+	 */
+	public boolean hExists(String key, String field) {
+		return redisTemplate.opsForHash().hasKey(key, field);
+	}
+
+	/**
+	 * 为哈希表 key 中的指定字段的整数值加上增量 increment
+	 *
+	 * @param key
+	 * @param field
+	 * @param increment
+	 * @return
+	 */
+	public Long hIncrBy(String key, Object field, long increment) {
+		return redisTemplate.opsForHash().increment(key, field, increment);
+	}
+
+	/**
+	 * 为哈希表 key 中的指定字段的整数值加上增量 increment
+	 *
+	 * @param key
+	 * @param field
+	 * @param delta
+	 * @return
+	 */
+	public Double hIncrByFloat(String key, Object field, double delta) {
+		return redisTemplate.opsForHash().increment(key, field, delta);
+	}
+
+	/**
+	 * 获取所有哈希表中的字段
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Set<Object> hKeys(String key) {
+		return redisTemplate.opsForHash().keys(key);
+	}
+
+	/**
+	 * 获取哈希表中字段的数量
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long hSize(String key) {
+		return redisTemplate.opsForHash().size(key);
+	}
+
+	/**
+	 * 获取哈希表中所有值
+	 *
+	 * @param key
+	 * @return
+	 */
+	public List<Object> hValues(String key) {
+		return redisTemplate.opsForHash().values(key);
+	}
+
+	/**
+	 * 迭代哈希表中的键值对
+	 *
+	 * @param key
+	 * @param options
+	 * @return
+	 */
+	public Cursor<Entry<Object, Object>> hScan(String key, ScanOptions options) {
+		return redisTemplate.opsForHash().scan(key, options);
+	}
+
+	/** ------------------------list相关操作---------------------------- */
+
+	/**
+	 * 通过索引获取列表中的元素
+	 *
+	 * @param key
+	 * @param index
+	 * @return
+	 */
+	public String lIndex(String key, long index) {
+		return redisTemplate.opsForList().index(key, index);
+	}
+
+	/**
+	 * 获取列表指定范围内的元素
+	 *
+	 * @param key
+	 * @param start
+	 *            开始位置, 0是开始位置
+	 * @param end
+	 *            结束位置, -1返回所有
+	 * @return
+	 */
+	public List<String> lRange(String key, long start, long end) {
+		return redisTemplate.opsForList().range(key, start, end);
+	}
+
+	/**
+	 * 存储在list头部
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lLeftPush(String key, String value) {
+		return redisTemplate.opsForList().leftPush(key, value);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lLeftPushAll(String key, String... value) {
+		return redisTemplate.opsForList().leftPushAll(key, value);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lLeftPushAll(String key, Collection<String> value) {
+		return redisTemplate.opsForList().leftPushAll(key, value);
+	}
+
+	/**
+	 * 当list存在的时候才加入
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lLeftPushIfPresent(String key, String value) {
+		return redisTemplate.opsForList().leftPushIfPresent(key, value);
+	}
+
+	/**
+	 * 如果pivot存在,再pivot前面添加
+	 *
+	 * @param key
+	 * @param pivot
+	 * @param value
+	 * @return
+	 */
+	public Long lLeftPush(String key, String pivot, String value) {
+		return redisTemplate.opsForList().leftPush(key, pivot, value);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lRightPush(String key, String value) {
+		return redisTemplate.opsForList().rightPush(key, value);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lRightPushAll(String key, String... value) {
+		return redisTemplate.opsForList().rightPushAll(key, value);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lRightPushAll(String key, Collection<String> value) {
+		return redisTemplate.opsForList().rightPushAll(key, value);
+	}
+
+	/**
+	 * 为已存在的列表添加值
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long lRightPushIfPresent(String key, String value) {
+		return redisTemplate.opsForList().rightPushIfPresent(key, value);
+	}
+
+	/**
+	 * 在pivot元素的右边添加值
+	 *
+	 * @param key
+	 * @param pivot
+	 * @param value
+	 * @return
+	 */
+	public Long lRightPush(String key, String pivot, String value) {
+		return redisTemplate.opsForList().rightPush(key, pivot, value);
+	}
+
+	/**
+	 * 通过索引设置列表元素的值
+	 *
+	 * @param key
+	 * @param index
+	 *            位置
+	 * @param value
+	 */
+	public void lSet(String key, long index, String value) {
+		redisTemplate.opsForList().set(key, index, value);
+	}
+
+	/**
+	 * 移出并获取列表的第一个元素
+	 *
+	 * @param key
+	 * @return 删除的元素
+	 */
+	public String lLeftPop(String key) {
+		return redisTemplate.opsForList().leftPop(key);
+	}
+
+	/**
+	 * 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+	 *
+	 * @param key
+	 * @param timeout
+	 *            等待时间
+	 * @param unit
+	 *            时间单位
+	 * @return
+	 */
+	public String lBLeftPop(String key, long timeout, TimeUnit unit) {
+		return redisTemplate.opsForList().leftPop(key, timeout, unit);
+	}
+
+	/**
+	 * 移除并获取列表最后一个元素
+	 *
+	 * @param key
+	 * @return 删除的元素
+	 */
+	public String lRightPop(String key) {
+		return redisTemplate.opsForList().rightPop(key);
+	}
+
+	/**
+	 * 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+	 *
+	 * @param key
+	 * @param timeout
+	 *            等待时间
+	 * @param unit
+	 *            时间单位
+	 * @return
+	 */
+	public String lBRightPop(String key, long timeout, TimeUnit unit) {
+		return redisTemplate.opsForList().rightPop(key, timeout, unit);
+	}
+
+	/**
+	 * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
+	 *
+	 * @param sourceKey
+	 * @param destinationKey
+	 * @return
+	 */
+	public String lRightPopAndLeftPush(String sourceKey, String destinationKey) {
+		return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+			destinationKey);
+	}
+
+	/**
+	 * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+	 *
+	 * @param sourceKey
+	 * @param destinationKey
+	 * @param timeout
+	 * @param unit
+	 * @return
+	 */
+	public String lBRightPopAndLeftPush(String sourceKey, String destinationKey,
+										long timeout, TimeUnit unit) {
+		return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+			destinationKey, timeout, unit);
+	}
+
+	/**
+	 * 删除集合中值等于value得元素
+	 *
+	 * @param key
+	 * @param index
+	 *            index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素;
+	 *            index<0, 从尾部开始删除第一个值等于value的元素;
+	 * @param value
+	 * @return
+	 */
+	public Long lRemove(String key, long index, String value) {
+		return redisTemplate.opsForList().remove(key, index, value);
+	}
+
+	/**
+	 * 裁剪list
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 */
+	public void lTrim(String key, long start, long end) {
+		redisTemplate.opsForList().trim(key, start, end);
+	}
+
+	/**
+	 * 获取列表长度
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long lLen(String key) {
+		return redisTemplate.opsForList().size(key);
+	}
+
+	/** --------------------set相关操作-------------------------- */
+
+	/**
+	 * set添加元素
+	 *
+	 * @param key
+	 * @param values
+	 * @return
+	 */
+	public Long sAdd(String key, String... values) {
+		return redisTemplate.opsForSet().add(key, values);
+	}
+
+	/**
+	 * set移除元素
+	 *
+	 * @param key
+	 * @param values
+	 * @return
+	 */
+	public Long sRemove(String key, Object... values) {
+		return redisTemplate.opsForSet().remove(key, values);
+	}
+
+	/**
+	 * 移除并返回集合的一个随机元素
+	 *
+	 * @param key
+	 * @return
+	 */
+	public String sPop(String key) {
+		return redisTemplate.opsForSet().pop(key);
+	}
+
+	/**
+	 * 将元素value从一个集合移到另一个集合
+	 *
+	 * @param key
+	 * @param value
+	 * @param destKey
+	 * @return
+	 */
+	public Boolean sMove(String key, String value, String destKey) {
+		return redisTemplate.opsForSet().move(key, value, destKey);
+	}
+
+	/**
+	 * 获取集合的大小
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long sSize(String key) {
+		return redisTemplate.opsForSet().size(key);
+	}
+
+	/**
+	 * 判断集合是否包含value
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Boolean sIsMember(String key, Object value) {
+		return redisTemplate.opsForSet().isMember(key, value);
+	}
+
+	/**
+	 * 获取两个集合的交集
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @return
+	 */
+	public Set<String> sIntersect(String key, String otherKey) {
+		return redisTemplate.opsForSet().intersect(key, otherKey);
+	}
+
+	/**
+	 * 获取key集合与多个集合的交集
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @return
+	 */
+	public Set<String> sIntersect(String key, Collection<String> otherKeys) {
+		return redisTemplate.opsForSet().intersect(key, otherKeys);
+	}
+
+	/**
+	 * key集合与otherKey集合的交集存储到destKey集合中
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @param destKey
+	 * @return
+	 */
+	public Long sIntersectAndStore(String key, String otherKey, String destKey) {
+		return redisTemplate.opsForSet().intersectAndStore(key, otherKey,
+			destKey);
+	}
+
+	/**
+	 * key集合与多个集合的交集存储到destKey集合中
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @param destKey
+	 * @return
+	 */
+	public Long sIntersectAndStore(String key, Collection<String> otherKeys,
+								   String destKey) {
+		return redisTemplate.opsForSet().intersectAndStore(key, otherKeys,
+			destKey);
+	}
+
+	/**
+	 * 获取两个集合的并集
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @return
+	 */
+	public Set<String> sUnion(String key, String otherKeys) {
+		return redisTemplate.opsForSet().union(key, otherKeys);
+	}
+
+	/**
+	 * 获取key集合与多个集合的并集
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @return
+	 */
+	public Set<String> sUnion(String key, Collection<String> otherKeys) {
+		return redisTemplate.opsForSet().union(key, otherKeys);
+	}
+
+	/**
+	 * key集合与otherKey集合的并集存储到destKey中
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @param destKey
+	 * @return
+	 */
+	public Long sUnionAndStore(String key, String otherKey, String destKey) {
+		return redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
+	}
+
+	/**
+	 * key集合与多个集合的并集存储到destKey中
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @param destKey
+	 * @return
+	 */
+	public Long sUnionAndStore(String key, Collection<String> otherKeys,
+							   String destKey) {
+		return redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
+	}
+
+	/**
+	 * 获取两个集合的差集
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @return
+	 */
+	public Set<String> sDifference(String key, String otherKey) {
+		return redisTemplate.opsForSet().difference(key, otherKey);
+	}
+
+	/**
+	 * 获取key集合与多个集合的差集
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @return
+	 */
+	public Set<String> sDifference(String key, Collection<String> otherKeys) {
+		return redisTemplate.opsForSet().difference(key, otherKeys);
+	}
+
+	/**
+	 * key集合与otherKey集合的差集存储到destKey中
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @param destKey
+	 * @return
+	 */
+	public Long sDifference(String key, String otherKey, String destKey) {
+		return redisTemplate.opsForSet().differenceAndStore(key, otherKey,
+			destKey);
+	}
+
+	/**
+	 * key集合与多个集合的差集存储到destKey中
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @param destKey
+	 * @return
+	 */
+	public Long sDifference(String key, Collection<String> otherKeys,
+							String destKey) {
+		return redisTemplate.opsForSet().differenceAndStore(key, otherKeys,
+			destKey);
+	}
+
+	/**
+	 * 获取集合所有元素
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Set<String> setMembers(String key) {
+		return redisTemplate.opsForSet().members(key);
+	}
+
+	/**
+	 * 随机获取集合中的一个元素
+	 *
+	 * @param key
+	 * @return
+	 */
+	public String sRandomMember(String key) {
+		return redisTemplate.opsForSet().randomMember(key);
+	}
+
+	/**
+	 * 随机获取集合中count个元素
+	 *
+	 * @param key
+	 * @param count
+	 * @return
+	 */
+	public List<String> sRandomMembers(String key, long count) {
+		return redisTemplate.opsForSet().randomMembers(key, count);
+	}
+
+	/**
+	 * 随机获取集合中count个元素并且去除重复的
+	 *
+	 * @param key
+	 * @param count
+	 * @return
+	 */
+	public Set<String> sDistinctRandomMembers(String key, long count) {
+		return redisTemplate.opsForSet().distinctRandomMembers(key, count);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param options
+	 * @return
+	 */
+	public Cursor<String> sScan(String key, ScanOptions options) {
+		return redisTemplate.opsForSet().scan(key, options);
+	}
+
+	/**------------------zSet相关操作--------------------------------*/
+
+	/**
+	 * 添加元素,有序集合是按照元素的score值由小到大排列
+	 *
+	 * @param key
+	 * @param value
+	 * @param score
+	 * @return
+	 */
+	public Boolean zAdd(String key, String value, double score) {
+		return redisTemplate.opsForZSet().add(key, value, score);
+	}
+
+	/**
+	 * 添加多个值
+	 * @param key
+	 * @param values
+	 * @return
+	 */
+	public Long zAdd(String key, Set<TypedTuple<String>> values) {
+		return redisTemplate.opsForZSet().add(key, values);
+	}
+
+	/**
+	 * 删除多个值
+	 * @param key
+	 * @param values
+	 * @return
+	 */
+	public Long zRemove(String key, Object... values) {
+		return redisTemplate.opsForZSet().remove(key, values);
+	}
+
+	/**
+	 * 增加元素的score值,并返回增加后的值
+	 *
+	 * @param key
+	 * @param value
+	 * @param delta
+	 * @return
+	 */
+	public Double zIncrementScore(String key, String value, double delta) {
+		return redisTemplate.opsForZSet().incrementScore(key, value, delta);
+	}
+
+	/**
+	 * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
+	 *
+	 * @param key
+	 * @param value
+	 * @return 0表示第一位
+	 */
+	public Long zRank(String key, Object value) {
+		return redisTemplate.opsForZSet().rank(key, value);
+	}
+
+	/**
+	 * 返回元素在集合的排名,按元素的score值由大到小排列
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Long zReverseRank(String key, Object value) {
+		return redisTemplate.opsForZSet().reverseRank(key, value);
+	}
+
+	/**
+	 * 获取集合的元素, 从小到大排序
+	 *
+	 * @param key
+	 * @param start
+	 *            开始位置
+	 * @param end
+	 *            结束位置, -1查询所有
+	 * @return
+	 */
+	public Set<String> zRange(String key, long start, long end) {
+		return redisTemplate.opsForZSet().range(key, start, end);
+	}
+
+	/**
+	 * 获取集合元素, 并且把score值也获取
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<TypedTuple<String>> zRangeWithScores(String key, long start,
+													long end) {
+		return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
+	}
+
+	/**
+	 * 根据Score值查询集合元素
+	 *
+	 * @param key
+	 * @param min
+	 *            最小值
+	 * @param max
+	 *            最大值
+	 * @return
+	 */
+	public Set<String> zRangeByScore(String key, double min, double max) {
+		return redisTemplate.opsForZSet().rangeByScore(key, min, max);
+	}
+
+	/**
+	 * 根据Score值查询集合元素, 从小到大排序
+	 * 根据score范围查询元素,并返回score
+	 * @param key
+	 * @param min
+	 *            最小值
+	 * @param max
+	 *            最大值
+	 * @return
+	 */
+	public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+														   double min, double max) {
+		return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
+	}
+
+	/**
+	 *
+	 * 根据score查询元素,s开始e结束位置
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+														   double min, double max, long start, long end) {
+		return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,
+			start, end);
+	}
+
+	/**
+	 * 获取集合的元素, 从大到小排序
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<String> zReverseRange(String key, long start, long end) {
+		return redisTemplate.opsForZSet().reverseRange(key, start, end);
+	}
+
+	/**
+	 * 获取集合的元素, 从大到小排序, 并返回score值
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<TypedTuple<String>> zReverseRangeWithScores(String key,
+														   long start, long end) {
+		return redisTemplate.opsForZSet().reverseRangeWithScores(key, start,
+			end);
+	}
+
+	/**
+	 * 根据Score值查询集合元素, 从大到小排序
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	public Set<String> zReverseRangeByScore(String key, double min,
+											double max) {
+		return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
+	}
+
+	/**
+	 * 根据Score值查询集合元素, 从大到小排序
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	public Set<TypedTuple<String>> zReverseRangeByScoreWithScores(
+		String key, double min, double max) {
+		return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,
+			min, max);
+	}
+
+	/**
+	 * 根据score范围查询元素,从大到小排序 s开始 end 结束位置
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<String> zReverseRangeByScore(String key, double min,
+											double max, long start, long end) {
+		return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max,
+			start, end);
+	}
+
+	/**
+	 * 根据score值获取集合元素数量
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	public Long zCount(String key, double min, double max) {
+		return redisTemplate.opsForZSet().count(key, min, max);
+	}
+
+	/**
+	 * 获取集合大小
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long zSize(String key) {
+		return redisTemplate.opsForZSet().size(key);
+	}
+
+	/**
+	 * 获取集合大小
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long zZCard(String key) {
+		return redisTemplate.opsForZSet().zCard(key);
+	}
+
+	/**
+	 * 获取集合中value元素的score值
+	 *
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	public Double zScore(String key, Object value) {
+		return redisTemplate.opsForZSet().score(key, value);
+	}
+
+	/**
+	 * 移除指定索引位置的成员
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Long zRemoveRange(String key, long start, long end) {
+		return redisTemplate.opsForZSet().removeRange(key, start, end);
+	}
+
+	/**
+	 * 根据指定的score值的范围来移除成员
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	public Long zRemoveRangeByScore(String key, double min, double max) {
+		return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
+	}
+
+	/**
+	 * 获取key和otherKey的并集并存储在destKey中
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @param destKey
+	 * @return
+	 */
+	public Long zUnionAndStore(String key, String otherKey, String destKey) {
+		return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @param destKey
+	 * @return
+	 */
+	public Long zUnionAndStore(String key, Collection<String> otherKeys,
+							   String destKey) {
+		return redisTemplate.opsForZSet()
+			.unionAndStore(key, otherKeys, destKey);
+	}
+
+	/**
+	 * 交集
+	 *
+	 * @param key
+	 * @param otherKey
+	 * @param destKey
+	 * @return
+	 */
+	public Long zIntersectAndStore(String key, String otherKey,
+								   String destKey) {
+		return redisTemplate.opsForZSet().intersectAndStore(key, otherKey,
+			destKey);
+	}
+
+	/**
+	 * 交集
+	 *
+	 * @param key
+	 * @param otherKeys
+	 * @param destKey
+	 * @return
+	 */
+	public Long zIntersectAndStore(String key, Collection<String> otherKeys,
+								   String destKey) {
+		return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys,
+			destKey);
+	}
+
+	/**
+	 *
+	 * @param key
+	 * @param options
+	 * @return
+	 */
+	public Cursor<TypedTuple<String>> zScan(String key, ScanOptions options) {
+		return redisTemplate.opsForZSet().scan(key, options);
+	}
+
+	/**
+	 * 获取Redis List 序列化
+	 * @param key
+	 * @param targetClass
+	 * @param <T>
+	 * @return
+	 */
+	public <T> List<T> getListCache(final String key, Class<T> targetClass) {
+		byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
+			@Override
+			public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
+				return connection.get(key.getBytes());
+			}
+		});
+		if (result == null) {
+			return null;
+		}
+		return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
+	}
+
+	/***
+	 * 将List 放进缓存里面
+	 * @param key
+	 * @param objList
+	 * @param expireTime
+	 * @param <T>
+	 * @return
+	 */
+	public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
+		final byte[] bkey = key.getBytes();
+		final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
+		boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
+			@Override
+			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
+				connection.setEx(bkey, expireTime, bvalue);
+				return true;
+			}
+		});
+		return result;
+	}
+
+}

+ 8 - 0
blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IGoodsDescClient.java

@@ -33,6 +33,7 @@ public interface IGoodsDescClient {
 	String GET_GOODS_DESC_DETIAL = API_PREFIX+ "getGoodsDescDetail";
 	String GET_GOODS_DESC_BY_CNAME = API_PREFIX+ "getGoodsDescByCname";
 	String GOODS_ITEMSID = API_PREFIX+ "selectItemsIdGoods";
+	String GOODS_ALL = API_PREFIX+ "selectGoodsDescAll";
 
 	/**
 	 * 根据销售明细的商品id获得商品信息
@@ -169,4 +170,11 @@ public interface IGoodsDescClient {
 	 */
 	@GetMapping(GET_GOODS_DESC_BY_CNAME)
 	GoodsDesc getGoodsDescByCname(@RequestParam("cname") String cname);
+
+	/**
+	 * 获取租户号下所有商品
+	 * @return
+	 */
+	@GetMapping(GOODS_ALL)
+	List<GoodsDesc> selectGoodsDescAll();
 }

+ 31 - 0
blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IRedisClient.java

@@ -0,0 +1,31 @@
+package org.springblade.client.feign;
+
+import org.springblade.client.entity.GoodsDesc;
+import org.springblade.common.constant.LauncherConstant;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+/**
+ * redis基础资料缓存
+ */
+@FeignClient(
+	value = LauncherConstant.APPLICATION_CLIENT_NAME
+)
+public interface IRedisClient {
+
+	String API_PREFIX = "/client";
+	String REFRESH_REDIS = API_PREFIX + "/refreshRedis";
+
+	/**
+	 * 刷新redis缓存
+	 *
+	 * @param type  业务类型
+	 * @return
+	 */
+	@GetMapping(REFRESH_REDIS)
+	boolean selectItemsIdGoods(@RequestParam("type") String type);
+
+}

+ 14 - 0
blade-service-api/blade-client-api/src/main/java/org/springblade/client/feign/IStorageClient.java

@@ -27,6 +27,8 @@ public interface IStorageClient {
 	String STORAGE_NAME = API_PREFIX + "/storageName";
 	String STORAGE_TYPE_NAME = API_PREFIX + "/storageTypeName";
 	String GET_STORAGE_TYPE = API_PREFIX + "/getStorageType";
+	String GET_STORAGE_TYPE_ALL = API_PREFIX + "/selectStorageTypeAll";
+	String GET_STORAGE_DESC_ALL = API_PREFIX + "/selectStorageDescAll";
 
     @GetMapping(FIND_BY_ID)
 	StorageDesc findById(@RequestParam(value = "id",required = true) Long id);
@@ -52,4 +54,16 @@ public interface IStorageClient {
 	 */
 	@GetMapping(STORAGE_TYPE_NAME)
 	StorageDesc getName(@RequestParam(value = "name",required = true) String name);
+
+	/***
+	 * 获取租户下所有仓库
+	 */
+	@GetMapping(GET_STORAGE_TYPE_ALL)
+	List<StorageType> selectStorageTypeAll();
+
+	/***
+	 * 获取租户下所有库区
+	 */
+	@GetMapping(GET_STORAGE_DESC_ALL)
+	List<StorageDesc> selectStorageDescAll();
 }

+ 22 - 0
blade-service-api/blade-client-api/src/main/java/org/springblade/client/goods/enums/RedisKey.java

@@ -0,0 +1,22 @@
+package org.springblade.client.goods.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class RedisKey {
+
+	//商品
+	public static final String REDIS_GOODS = "goods";
+	//客户
+	public static final String REDIS_CORPS = "corps";
+	//仓库
+	public static final String REDIS_STORAGE_TYPE = "storageType";
+	//库区
+	public static final String REDIS_STORAGE_DESC = "storageDesc";
+	//用户
+	public static final String REDIS_USER = "user";
+
+
+}

+ 10 - 0
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java

@@ -60,6 +60,7 @@ public interface IUserClient {
 	String LIST_USER_BY_ROLE_ID=API_PREFIX+"/listUserByRoleId";
 	String GET_USER_PAGE=API_PREFIX+"/getUserPage";
 	String USER_BY_IDS = API_PREFIX+ "/selectUserIds";
+	String USER_ALL = API_PREFIX+ "/selectUserAll";
 
 	@GetMapping(LIST_USER_BY_ROLE_ID)
 	R<List<User>> listUserByRoleId(@RequestParam("roleId")Long roleId);
@@ -175,4 +176,13 @@ public interface IUserClient {
 	/*@GetMapping(GET_USER_PAGE)
 	R<IPage<UserVO>> getUserPage(@RequestBody User user, Query query, Long deptId, BladeUser bladeUser);*/
 
+	/**
+	 * 获取租户号下所有用户信息
+	 *
+	 * @param
+	 * @return
+	 */
+	@GetMapping(USER_ALL)
+	List<User> selectUserAll();
+
 }

+ 7 - 0
blade-service-api/trade-purchase-api/src/main/java/com/trade/purchase/order/entity/Order.java

@@ -838,4 +838,11 @@ public class Order extends OrderBase {
 	 */
 	@TableField(exist = false)
 	private String specialCheckStatusApp;
+
+	/**
+	 * 采木云是否出库状态(app)
+	 */
+	@TableField(exist = false)
+	private String statuss;
+
 }

+ 92 - 0
blade-service/blade-client/src/main/java/org/springblade/client/RedisClient.java

@@ -0,0 +1,92 @@
+package org.springblade.client;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.client.feign.ICorpsDescClient;
+import org.springblade.client.feign.IGoodsDescClient;
+import org.springblade.client.feign.IRedisClient;
+import org.springblade.client.feign.IStorageClient;
+import org.springblade.client.goods.enums.RedisKey;
+import org.springblade.client.vo.CorpsDescVO;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.util.List;
+
+@Slf4j
+@NonDS
+@ApiIgnore()
+@RestController
+@AllArgsConstructor
+public class RedisClient implements IRedisClient {
+
+
+	private final IUserClient userClient;//获取用户信息
+	private final IGoodsDescClient goodsDescClient;//获取商品信息
+	private final ICorpsDescClient corpsDescClient;//获取客户信息
+	private final IStorageClient iStorageClient;//获取仓库,库区信息
+	private final RedisTemplate<String, Object> redisTemplate;
+
+	@Override
+	public boolean selectItemsIdGoods(String type) {
+
+
+		//redis缓存基础资料数据
+		//判断key是否存在
+		//用户
+		if (RedisKey.REDIS_USER.equals(type)) {
+			if (redisTemplate.hasKey(type)) {
+				redisTemplate.opsForValue().set(type, userClient.selectUserAll());
+			} else {
+				redisTemplate.opsForValue().getAndSet(type, userClient.selectUserAll());
+			}
+		}
+		//商品
+		if (RedisKey.REDIS_GOODS.equals(type)) {
+			if (redisTemplate.hasKey(type)) {
+				redisTemplate.opsForValue().set(type, goodsDescClient.selectGoodsDescAll());
+			} else {
+				redisTemplate.opsForValue().getAndSet(type, goodsDescClient.selectGoodsDescAll());
+			}
+		}
+
+		//客户
+		if (RedisKey.REDIS_CORPS.equals(type)) {
+			R<List<CorpsDescVO>> list = corpsDescClient.selCorpsDetails(AuthUtil.getTenantId());
+			if (list.isSuccess()) {
+				if (redisTemplate.hasKey(type)) {
+					redisTemplate.opsForValue().set(type, list.getData());
+				} else {
+					redisTemplate.opsForValue().getAndSet(type, list.getData());
+				}
+			}
+		}
+		//仓库
+		if (RedisKey.REDIS_STORAGE_TYPE.equals(type)) {
+			if (redisTemplate.hasKey(type)) {
+				redisTemplate.opsForValue().set(type, iStorageClient.selectStorageTypeAll());
+			} else {
+				redisTemplate.opsForValue().getAndSet(type, iStorageClient.selectStorageTypeAll());
+			}
+		}
+		//库区
+		if (RedisKey.REDIS_STORAGE_DESC.equals(type)) {
+			if (redisTemplate.hasKey(type)) {
+				redisTemplate.opsForValue().set(type, iStorageClient.selectStorageDescAll());
+			} else {
+				redisTemplate.opsForValue().getAndSet(type, iStorageClient.selectStorageDescAll());
+			}
+		}
+
+		System.out.println("商品:" + redisTemplate.opsForValue().get("goods"));
+		System.out.println("客户:" + redisTemplate.opsForValue().get("corps"));
+		System.out.println("仓库:" + redisTemplate.opsForValue().get("storageType"));
+		System.out.println("库区:" + redisTemplate.opsForValue().get("storageDesc"));
+		return true;
+	}
+}

+ 9 - 0
blade-service/blade-client/src/main/java/org/springblade/client/goods/feign/GoodsDescClient.java

@@ -209,6 +209,15 @@ public class GoodsDescClient implements IGoodsDescClient {
 		return goodsDescService.getOne(lambdaQueryWrapper);
 	}
 
+
+	@Override
+	public List<GoodsDesc> selectGoodsDescAll() {
+		LambdaQueryWrapper<GoodsDesc> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+		lambdaQueryWrapper.eq(GoodsDesc::getIsDeleted, 0);
+		lambdaQueryWrapper.eq(GoodsDesc::getTenantId, AuthUtil.getTenantId());
+		return goodsDescService.list(lambdaQueryWrapper);
+	}
+
 	/**
 	 * 递归查询ID
 	 */

+ 17 - 0
blade-service/blade-client/src/main/java/org/springblade/client/storage/feign/StorageClient.java

@@ -8,6 +8,7 @@ import lombok.AllArgsConstructor;
 import org.springblade.client.corps.assemble.mapstruct.CorpsDescMapstructMapper;
 import org.springblade.client.corps.service.ICorpsDescService;
 import org.springblade.client.entity.CorpsDesc;
+import org.springblade.client.entity.GoodsDesc;
 import org.springblade.client.entity.StorageDesc;
 import org.springblade.client.entity.StorageType;
 import org.springblade.client.feign.ICorpsDescClient;
@@ -68,5 +69,21 @@ public class StorageClient implements IStorageClient {
 		return storageDescService.getOne(new QueryWrapper<StorageDesc>().eq("cname",name).eq("tenant_id", SecureUtil.getTenantId()).eq("is_deleted",0));
 	}
 
+	@Override
+	public List<StorageType> selectStorageTypeAll() {
+		LambdaQueryWrapper<StorageType> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+		lambdaQueryWrapper.eq(StorageType::getIsDeleted, 0);
+		lambdaQueryWrapper.eq(StorageType::getTenantId, AuthUtil.getTenantId());
+		return storageTypeService.list(lambdaQueryWrapper);
+	}
+
+	@Override
+	public List<StorageDesc> selectStorageDescAll() {
+		LambdaQueryWrapper<StorageDesc> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+		lambdaQueryWrapper.eq(StorageDesc::getIsDeleted, 0);
+		lambdaQueryWrapper.eq(StorageDesc::getTenantId, AuthUtil.getTenantId());
+		return storageDescService.list(lambdaQueryWrapper);
+	}
+
 
 }

+ 9 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java

@@ -138,6 +138,15 @@ public class UserClient implements IUserClient {
 		return R.data(service.gainUser(SecureUtil.getTenantId()));
 	}
 
+	@Override
+	@GetMapping(USER_ALL)
+	public List<User> selectUserAll() {
+		LambdaQueryWrapper<User> userLambdaQueryWrapper=new LambdaQueryWrapper<>();
+		userLambdaQueryWrapper.eq(User::getTenantId,AuthUtil.getTenantId());
+		userLambdaQueryWrapper.eq(User::getIsDeleted,0);
+		return service.list(userLambdaQueryWrapper);
+	}
+
 	/**
 	 * 获取用户
 	 * @param user

+ 50 - 54
blade-service/trade-purchase/src/main/java/com/trade/purchase/excel/CMYWarehousingExcel.java

@@ -20,25 +20,6 @@ import java.math.BigDecimal;
 public class CMYWarehousingExcel {
 
 	/**
-	 * 库区
-	 */
-	@ExcelProperty(value = "库区(必填)")
-	@ExcelPropertyCheck(required = false)
-	private String reservoirAreaName;
-
-	/**
-	 * 库区Id
-	 */
-	@ExcelIgnore
-	private Long storageId;
-
-	/**
-	 * 箱号
-	 */
-	@ExcelProperty(value = "箱号")
-	private String containerNo;
-
-	/**
 	 * 品名
 	 */
 	@ExcelProperty(value = "品名(必填)")
@@ -52,33 +33,15 @@ public class CMYWarehousingExcel {
 	private Long itemId;
 
 	/**
-	 * 等级
-	 */
-	@ExcelProperty(value = "等级(必填)")
-	@ExcelPropertyCheck(required = false)
-	private String grade;
-	/**
-	 * 品牌
-	 */
-	@ExcelProperty(value = "品牌(必填)")
-	@ExcelPropertyCheck(required = false)
-	private String itemType;
-	/**
-	 * 产地
-	 */
-	@ExcelProperty(value = "产地")
-	private String itemProp;
-
-	/**
 	 * 长度(m)
 	 */
-	@ExcelProperty(value = "长度(m)")
+	@ExcelProperty(value = "长度(必填)")
 	private String length;
 
 	/**
 	 * 厚度(mm)
 	 */
-	@ExcelProperty(value = "厚度(mm)")
+	@ExcelProperty(value = "厚度(必填)")
 	private String thickness;
 
 	/**
@@ -89,12 +52,6 @@ public class CMYWarehousingExcel {
 	private String billNo;
 
 	/**
-	 * 片数
-	 */
-	@ExcelProperty(value = "片数(必填)")
-	@ExcelPropertyCheck(required = false)
-	private BigDecimal sliceNumber;
-	/**
 	 * 入库数量
 	 */
 	@ExcelProperty(value = "入库数量(必填)")
@@ -102,24 +59,63 @@ public class CMYWarehousingExcel {
 	private BigDecimal storageInQuantity;
 
 	/**
+	 * 入库单价
+	 */
+	@ExcelProperty(value = "入库单价")
+	private BigDecimal price;
+
+	/**
+	 * 入库总金额
+	 */
+	@ExcelProperty(value = "入库总金额")
+	private BigDecimal storageAmount;
+
+	/**
 	 * 入库单位
 	 */
-	@ExcelProperty(value = "入库单位(必填)")
-	@ExcelPropertyCheck(required = false)
+	@ExcelProperty(value = "入库单位")
 	private String unit;
 
 	/**
-	 * 入库单价
+	 * 等级
 	 */
-	@ExcelProperty(value = "入库单价(必填)")
-	@ExcelPropertyCheck(required = false)
-	private BigDecimal price;
+	@ExcelProperty(value = "等级")
+	private String grade;
 
 	/**
-	 * 入库总金额
+	 * 库区
 	 */
-	@ExcelProperty(value = "入库总金额(元)")
-	private BigDecimal storageAmount;
+	@ExcelProperty(value = "库区")
+	private String reservoirAreaName;
+
+	/**
+	 * 库区Id
+	 */
+	@ExcelIgnore
+	private Long storageId;
+
+	/**
+	 * 箱号
+	 */
+	@ExcelProperty(value = "箱号")
+	private String containerNo;
+
+	/**
+	 * 品牌
+	 */
+	@ExcelProperty(value = "品牌")
+	private String itemType;
+	/**
+	 * 产地
+	 */
+	@ExcelProperty(value = "产地")
+	private String itemProp;
+
+	/**
+	 * 片数
+	 */
+	@ExcelProperty(value = "片数")
+	private BigDecimal sliceNumber;
 
 	/**
 	 * 备注

+ 21 - 136
blade-service/trade-purchase/src/main/java/com/trade/purchase/order/controller/WoodHarvestingCloudController.java

@@ -1,6 +1,5 @@
 package com.trade.purchase.order.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -8,7 +7,6 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import com.trade.purchase.excel.CMYWarehousingExcel;
 import com.trade.purchase.excel.GeneralLedgerExcel;
-import com.trade.purchase.financing.entity.Financing;
 import com.trade.purchase.financing.service.IFinancingService;
 import com.trade.purchase.order.dto.OrderSubmitDto;
 import com.trade.purchase.order.entity.Order;
@@ -23,11 +21,8 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
-import org.springblade.client.entity.CorpsDesc;
-import org.springblade.client.entity.StorageType;
-import org.springblade.client.feign.ICorpsDescClient;
 import org.springblade.client.feign.IGoodsDescClient;
-import org.springblade.client.feign.IStorageClient;
+import org.springblade.client.feign.IRedisClient;
 import org.springblade.client.vo.GoodsDescVO;
 import org.springblade.core.excel.util.ExcelUtil;
 import org.springblade.core.mp.support.Condition;
@@ -35,15 +30,11 @@ import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
-import org.springblade.system.user.entity.User;
-import org.springblade.system.user.feign.IUserClient;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
-import java.math.BigDecimal;
-import java.math.MathContext;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -67,14 +58,9 @@ public class WoodHarvestingCloudController {
 
 	private final IOrderItemsService orderItemsService;
 
-	private final IStorageClient iStorageClient;
-
-	private ICorpsDescClient corpsDescClient;//获取客户信息
-
 	private IGoodsDescClient goodsDescClient;//获取商品信息
-	private final IFinancingService financingService;
 
-	private IUserClient userClient;
+	private IRedisClient redisClient;//获取商品信息
 
 	/**
 	 * 导出采木云入库模板
@@ -119,75 +105,12 @@ public class WoodHarvestingCloudController {
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "查询所有", notes = "传入order")
 	public R<IPage<Order>> list(Order order, Query query) {
-		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
-		queryWrapper.eq("is_deleted", 0)
-			.eq("tenant_id", AuthUtil.getTenantId())
-			.eq(ObjectUtils.isNotNull(order.getBillType()), "bill_type", order.getBillType())
-			.eq("trade_type", OrderTypeEnum.WOOD_HARVESTING_CLOUD.getType())
-			.eq(ObjectUtils.isNotNull(order.getBusinessType()), "business_type", order.getBusinessType());
-		if (ObjectUtils.isNotNull(order.getPurchaser())) {
-			//货权人
-			R<CorpsDesc> corpsDesc = corpsDescClient.getCorpByName(order.getPurchaser(), AuthUtil.getTenantId());
-			if (corpsDesc.isSuccess()) {
-				queryWrapper.eq(ObjectUtils.isNotNull(order.getPurchaserId()), "purchaser_id", corpsDesc.getData().getId());
-			}
-		} else {
-			queryWrapper.eq(ObjectUtils.isNotNull(order.getPurchaserId()), "purchaser_id", order.getPurchaserId());
-		}
-		if (ObjectUtils.isNotNull(order.getStorageName())) {
-			//仓库
-			StorageType storageType = iStorageClient.storageTypeName(order.getStorageName());
-			if (ObjectUtils.isNotNull(storageType)) {
-				queryWrapper.eq("storage_id", storageType.getId());
-			}
-		} else {
-			queryWrapper.eq(ObjectUtils.isNotNull(order.getStorageId()), "storage_id", order.getStorageId());
-		}
-		queryWrapper.like(ObjectUtils.isNotNull(order.getSysNo()), "sys_no", order.getSysNo())
-			.like(ObjectUtils.isNotNull(order.getBillNo()), "bill_no", order.getBillNo())
-			.like(ObjectUtils.isNotNull(order.getVehicleShipNumber()), "vehicle_ship_number", order.getVehicleShipNumber())
-			.eq(ObjectUtils.isNotNull(order.getCorpId()), "corp_id", order.getCorpId());
-		if (ObjectUtils.isNotNull(order.getSpecialCheckStatusApp())) {
-			queryWrapper.eq("special_check_status", 0);
-		} else {
-			if (OrderTypeEnum.INVENTORY.getType().equals(order.getBillType())) {
-				queryWrapper.eq("special_check_status", 0);
-			}
-		}
-		queryWrapper.like(ObjectUtils.isNotNull(order.getOrderRemark()), "order_remark", order.getOrderRemark())
-			.eq(ObjectUtils.isNotNull(order.getStatus()), "status", order.getStatus())
-			.ge(ObjectUtils.isNotNull(order.getCreateStartTime()), "DATE_FORMAT(stock_time,'%Y-%m-%d')", order.getCreateStartTime())
-			.le(ObjectUtils.isNotNull(order.getCreateEndTime()), "DATE_FORMAT(stock_time,'%Y-%m-%d')", order.getCreateEndTime())
-			.orderByDesc("stock_time");
-		IPage<Order> pages = orderService.page(Condition.getPage(query), queryWrapper);
-		List<Order> orderList = pages.getRecords();
-		for (Order orders : orderList) {
-			if (ObjectUtils.isNotNull(orders.getStorageId())) {
-				//仓库
-				StorageType storageType = iStorageClient.getStorageType(orders.getStorageId());
-				if (ObjectUtils.isNotNull(storageType)) {
-					orders.setStorageName(storageType.getCname());
-				}
-			}
-			//货权人
-			if (ObjectUtils.isNotNull(orders.getPurchaserId())) {
-				R<CorpsDesc> corpsDesc = corpsDescClient.getCorpMessage(orders.getPurchaserId());
-				if (corpsDesc.isSuccess()) {
-					orders.setPurchaser(corpsDesc.getData().getCname());
-				}
-			}
-			//供应商
-			if (ObjectUtils.isNotNull(orders.getCorpId())) {
-				R<CorpsDesc> corpsDesc = corpsDescClient.getCorpMessage(orders.getCorpId());
-				if (corpsDesc.isSuccess()) {
-					orders.setCorpName(corpsDesc.getData().getCname());
-				}
-			}
-			R<User> userR = userClient.userInfoById(orders.getCreateUser());
-			if (userR.isSuccess()) {
-				orders.setSalesName(userR.getData().getName());
-			}
-		}
+		/*redisClient.selectItemsIdGoods("goods");
+		redisClient.selectItemsIdGoods("corps");
+		redisClient.selectItemsIdGoods("storageType");
+		redisClient.selectItemsIdGoods("storageDesc");
+		redisClient.selectItemsIdGoods("user");*/
+		IPage<Order> pages = orderService.selectOrderList(order, query);
 		return R.data(pages);
 	}
 
@@ -271,14 +194,15 @@ public class WoodHarvestingCloudController {
 	@GetMapping("/withdraw")
 	@ApiOperationSupport(order = 7)
 	@ApiOperation(value = "电脑端提交", notes = "传入id")
-	public R pcSubmit( @RequestParam(value = "id") Long id,
-					   @RequestParam(value = "type") String type,
-					   @RequestParam(value = "status") int status,
-					   @RequestParam(value = "isIssue") String isIssue) {
+	public R pcSubmit(@RequestParam(value = "id") Long id,
+					  @RequestParam(value = "type") String type,
+					  @RequestParam(value = "toolType",required = false) String toolType,
+					  @RequestParam(value = "status") int status,
+					  @RequestParam(value = "isIssue") String isIssue) {
 		if (id == null) {
 			return R.fail("缺少必要参数");
 		}
-		return R.data(orderService.withdraw(id,type,status,isIssue));
+		return R.data(orderService.withdraw(id, type, status, isIssue, toolType));
 	}
 
 	/**
@@ -312,46 +236,7 @@ public class WoodHarvestingCloudController {
 	 */
 	@PostMapping("/financingExcess")
 	public R financingExcess(@RequestBody Order order) {
-		//获取该客户是否有融资
-		//借款
-		LambdaQueryWrapper<Financing> borrowLambdaQueryWrapper = new LambdaQueryWrapper<>();
-		borrowLambdaQueryWrapper
-			.eq(Financing::getIsDeleted, 0)
-			.eq(Financing::getTenantId, AuthUtil.getTenantId())
-			.eq(Financing::getFinancingType, "1")
-			.eq(Financing::getCorpId, order.getId());
-		List<Financing> borrowList = financingService.list(borrowLambdaQueryWrapper);
-		BigDecimal borrow = borrowList.stream().map(Financing::getFinancingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
-		//还款
-		LambdaQueryWrapper<Financing> stillLambdaQueryWrapper = new LambdaQueryWrapper<>();
-		stillLambdaQueryWrapper
-			.eq(Financing::getIsDeleted, 0)
-			.eq(Financing::getTenantId, AuthUtil.getTenantId())
-			.eq(Financing::getFinancingType, "2")
-			.eq(Financing::getCorpId, order.getId());
-		List<Financing> stillList = financingService.list(stillLambdaQueryWrapper);
-		BigDecimal still = stillList.stream().map(Financing::getFinancingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
-
-		BigDecimal financing = still.subtract(borrow, MathContext.UNLIMITED);
-
-		//获取该客户还在库的货物金额
-		LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
-		orderLambdaQueryWrapper
-			.eq(Order::getIsDeleted, 0)
-			.eq(Order::getTenantId, AuthUtil.getTenantId())
-			.eq(Order::getBillType, OrderTypeEnum.WAREHOUSING.getType())
-			.eq(Order::getTradeType, OrderTypeEnum.WOOD_HARVESTING_CLOUD.getType())
-			.eq(Order::getSpecialCheckStatus, 0)
-			.eq(Order::getPurchaserId, order.getId());
-		List<Order> orderList = orderService.list(orderLambdaQueryWrapper);
-		BigDecimal storageAmount = orderList.stream().map(Order::getStorageAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
-		int num = financing.signum();
-		if (num == -1) {
-			if (storageAmount.compareTo(financing.abs()) < 0) {
-				return R.data("融资金额:" + financing + "大于 库存金额 :" + storageAmount + " 不能出库");
-			}
-		}
-		return R.data("操作成功");
+		return orderService.financingExcess(order);
 	}
 
 	/**
@@ -360,8 +245,8 @@ public class WoodHarvestingCloudController {
 	@PostMapping("/passCheck")
 	@ApiOperationSupport(order = 8)
 	@ApiOperation(value = "Feign-审核通过", notes = "传入财务id")
-	public R passCheck(@ApiParam(value = "财务主表id", required = true) @RequestParam Long id,@RequestParam("times") int times) {
-		orderService.passCheck(id,times);
+	public R passCheck(@ApiParam(value = "财务主表id", required = true) @RequestParam Long id, @RequestParam("times") int times) {
+		orderService.passCheck(id, times);
 		return R.success("操作成功");
 	}
 
@@ -369,8 +254,8 @@ public class WoodHarvestingCloudController {
 	 * 审核中
 	 */
 	@PostMapping("/underReview")
-	public R underReview(@ApiParam(value = "主表id", required = true) @RequestParam Long id,@RequestParam("times") int times) {
-		orderService.underReview(id,times);
+	public R underReview(@ApiParam(value = "主表id", required = true) @RequestParam Long id, @RequestParam("times") int times) {
+		orderService.underReview(id, times);
 		return R.success("操作成功");
 	}
 
@@ -380,8 +265,8 @@ public class WoodHarvestingCloudController {
 	@PostMapping("/passCancel")
 	@ApiOperationSupport(order = 8)
 	@ApiOperation(value = "Feign-审核不通过", notes = "传入财务id")
-	public R passCancel(@ApiParam(value = "财务主表id", required = true) @RequestParam Long id,@RequestParam("times") int times) {
-		orderService.passCancel(id,times);
+	public R passCancel(@ApiParam(value = "财务主表id", required = true) @RequestParam Long id, @RequestParam("times") int times) {
+		orderService.passCancel(id, times);
 		return R.success("操作成功");
 	}
 

+ 17 - 1
blade-service/trade-purchase/src/main/java/com/trade/purchase/order/service/IOrderService.java

@@ -211,5 +211,21 @@ public interface IOrderService extends IService<Order> {
 	/**
 	 * 状态修改
 	 */
-	boolean withdraw(Long id, String type, int status, String isIssue);
+	boolean withdraw(Long id, String type, int status, String isIssue,String toolType);
+
+	/**
+	 * 木材库列表查询
+	 * @param order
+	 * @param query
+	 * @return
+	 */
+	IPage<Order> selectOrderList(Order order, Query query);
+
+	/**
+	 * 客户现有资产是否超出融资金额
+	 *
+	 * @param order
+	 * @return
+	 */
+	R financingExcess(Order order);
 }

+ 182 - 10
blade-service/trade-purchase/src/main/java/com/trade/purchase/order/service/impl/OrderServiceImpl.java

@@ -18,6 +18,7 @@ import com.trade.purchase.excel.CMYWarehousingExcel;
 import com.trade.purchase.excel.GeneralLedgerExcel;
 import com.trade.purchase.excel.PurchaseOrderExcel;
 import com.trade.purchase.exception.OrderException;
+import com.trade.purchase.financing.entity.Financing;
 import com.trade.purchase.financing.service.impl.FinancingServiceImpl;
 import com.trade.purchase.order.assemble.mapstruct.OrderItemMapstructMapper;
 import com.trade.purchase.order.assemble.mapstruct.OrderMapstructMapper;
@@ -45,6 +46,8 @@ import org.springblade.client.feign.*;
 import org.springblade.client.vo.GoodsDescVO;
 import org.springblade.common.utils.BarCodeTest;
 import org.springblade.common.utils.QRCodeTest;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
@@ -967,7 +970,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @param excelList
 	 * @return
 	 */
-	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public List<CMYWarehousingExcel> warehousing(List<CMYWarehousingExcel> excelList) {
 
 		for (CMYWarehousingExcel cMYWarehousingExcel : excelList) {
@@ -1014,7 +1018,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @return
 	 */
 	@Override
-	@Transactional
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R saveWarehousing(OrderSubmitDto submitDto) {
 		List<OrderItems> orderItemsList = submitDto.getItemsList();
 		//获取系统编号
@@ -1124,7 +1129,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @return
 	 */
 	@Override
-	@Transactional
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R updateWarehousing(OrderSubmitDto submitDto) {
 		//明细数据
 		List<OrderItemsVO> orderItemsList = submitDto.getItemsVOList();
@@ -1201,7 +1207,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @return
 	 */
 	@Override
-	@Transactional
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R submitWarehousing(OrderSubmitDto submitDto) {
 		List<OrderItemsVO> orderItemsList = submitDto.getItemsVOList();
 		//获取系统编号
@@ -1573,6 +1580,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	}
 
 	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R passCheck(Long id, int times) {
 		// ===========================start 审核通过修改入出库,盘点单信息==========================
 		Order order = baseMapper.selectById(id);
@@ -1698,6 +1707,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	}
 
 	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R underReview(Long id, int times) {
 		Order order = baseMapper.selectById(id);
 		if (order == null) {
@@ -1726,6 +1737,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	}
 
 	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public R passCancel(Long id, int times) {
 		Order order = baseMapper.selectById(id);
 		if (order == null) {
@@ -1859,6 +1872,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @return
 	 */
 	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public Order updateOutInStatus(Long id) {
 		Order order = orderMapper.selectById(id);
 		if (ObjectUtils.isNotNull(order)) {
@@ -1935,7 +1950,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	 * @return
 	 */
 	@Override
-	@Transactional
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public OrderSubmitDto revokeWarehousing(OrderSubmitDto submitDto) {
 		Order order = orderMapper.selectById(submitDto.getId());
 		if (order == null) {
@@ -2078,12 +2094,24 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	}
 
 	@Override
-	public boolean withdraw(Long id, String type, int status, String isIssue) {
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
+	public boolean withdraw(Long id, String type, int status, String isIssue, String toolType) {
+		Order order = baseMapper.selectById(id);
 		if (OrderTypeEnum.WAREHOUSING.getType().equals(type)) {
+			if ("app".equals(toolType)) {
+				if (3 == order.getStatus()) {
+					throw new SecurityException("已提交审核,撤回失败");
+				}
+			}
 			//修改明细状态
 			orderItemsService.updateByPId(id, isIssue);
 		} else if (OrderTypeEnum.OUT_WAREHOUSING.getType().equals(type)) {
-			Order order = baseMapper.selectById(id);
+			if ("app".equals(toolType)) {
+				if (3 == order.getStatus()) {
+					throw new SecurityException("已提交审核,撤回失败");
+				}
+			}
 			//获取入库
 			LambdaQueryWrapper<Order> RKOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
 			RKOrderLambdaQueryWrapper
@@ -2123,8 +2151,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 				}
 			}
 		}
-		Order order = new Order();
-		order.setId(id);
 		order.setStatus(status);
 		order.setUpdateUser(AuthUtil.getUserId());
 		order.setUpdateTime(new Date());
@@ -2134,13 +2160,159 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 	}
 
 	/**
+	 * 木材库列表查询
+	 *
+	 * @param order
+	 * @param query
+	 * @return
+	 */
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
+	public IPage<Order> selectOrderList(Order order, Query query) {
+		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
+		queryWrapper.eq("is_deleted", 0)
+			.eq("tenant_id", AuthUtil.getTenantId())
+			.eq(ObjectUtils.isNotNull(order.getBillType()), "bill_type", order.getBillType())
+			.eq("trade_type", OrderTypeEnum.WOOD_HARVESTING_CLOUD.getType())
+			.eq(ObjectUtils.isNotNull(order.getBusinessType()), "business_type", order.getBusinessType());
+		if (ObjectUtils.isNotNull(order.getPurchaser())) {
+			//货权人
+			R<CorpsDesc> corpsDesc = corpsDescClient.getCorpByName(order.getPurchaser(), AuthUtil.getTenantId());
+			if (corpsDesc.isSuccess()) {
+				queryWrapper.eq(ObjectUtils.isNotNull(order.getPurchaserId()), "purchaser_id", corpsDesc.getData().getId());
+			}
+		} else {
+			queryWrapper.eq(ObjectUtils.isNotNull(order.getPurchaserId()), "purchaser_id", order.getPurchaserId());
+		}
+		if (ObjectUtils.isNotNull(order.getStorageName())) {
+			//仓库
+			StorageType storageType = iStorageClient.storageTypeName(order.getStorageName());
+			if (ObjectUtils.isNotNull(storageType)) {
+				queryWrapper.eq("storage_id", storageType.getId());
+			}
+		} else {
+			queryWrapper.eq(ObjectUtils.isNotNull(order.getStorageId()), "storage_id", order.getStorageId());
+		}
+		queryWrapper.like(ObjectUtils.isNotNull(order.getSysNo()), "sys_no", order.getSysNo())
+			.like(ObjectUtils.isNotNull(order.getBillNo()), "bill_no", order.getBillNo())
+			.like(ObjectUtils.isNotNull(order.getVehicleShipNumber()), "vehicle_ship_number", order.getVehicleShipNumber())
+			.eq(ObjectUtils.isNotNull(order.getCorpId()), "corp_id", order.getCorpId());
+		if (ObjectUtils.isNotNull(order.getSpecialCheckStatusApp())) {
+			queryWrapper.eq("special_check_status", 0);
+		} else {
+			if (OrderTypeEnum.INVENTORY.getType().equals(order.getBillType())) {
+				queryWrapper.eq("special_check_status", 0);
+			}
+		}
+		queryWrapper.like(ObjectUtils.isNotNull(order.getOrderRemark()), "order_remark", order.getOrderRemark());
+		if (ObjectUtils.isNotNull(order.getStatuss())) {
+			String[] arrs = order.getStatuss().split(",");
+			for (int i = 0; i < arrs.length; i++) {
+				if (i > 0) {
+					queryWrapper.or().eq("status", arrs[i]);
+				} else {
+					queryWrapper.eq("status", arrs[i]);
+				}
+			}
+		}
+		queryWrapper.ge(ObjectUtils.isNotNull(order.getCreateStartTime()), "DATE_FORMAT(stock_time,'%Y-%m-%d')", order.getCreateStartTime())
+			.le(ObjectUtils.isNotNull(order.getCreateEndTime()), "DATE_FORMAT(stock_time,'%Y-%m-%d')", order.getCreateEndTime())
+			.orderByDesc("stock_time");
+		IPage<Order> pages = baseMapper.selectPage(Condition.getPage(query), queryWrapper);
+		List<Order> orderList = pages.getRecords();
+
+		for (Order orders : orderList) {
+			if (ObjectUtils.isNotNull(orders.getStorageId())) {
+				//仓库
+				StorageType storageType = iStorageClient.getStorageType(orders.getStorageId());
+				if (ObjectUtils.isNotNull(storageType)) {
+					orders.setStorageName(storageType.getCname());
+				}
+			}
+			//货权人
+			if (ObjectUtils.isNotNull(orders.getPurchaserId())) {
+				R<CorpsDesc> corpsDesc = corpsDescClient.getCorpMessage(orders.getPurchaserId());
+				if (corpsDesc.isSuccess()) {
+					orders.setPurchaser(corpsDesc.getData().getCname());
+				}
+			}
+			//供应商
+			if (ObjectUtils.isNotNull(orders.getCorpId())) {
+				R<CorpsDesc> corpsDesc = corpsDescClient.getCorpMessage(orders.getCorpId());
+				if (corpsDesc.isSuccess()) {
+					orders.setCorpName(corpsDesc.getData().getCname());
+				}
+			}
+			R<User> userR = userClient.userInfoById(orders.getCreateUser());
+			if (userR.isSuccess()) {
+				orders.setSalesName(userR.getData().getName());
+			}
+		}
+		return pages;
+	}
+
+	/**
+	 * 客户现有资产是否超出融资金额
+	 *
+	 * @param order
+	 * @return
+	 */
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
+	public R financingExcess(Order order) {
+		//获取该客户是否有融资
+		//借款
+		LambdaQueryWrapper<Financing> borrowLambdaQueryWrapper = new LambdaQueryWrapper<>();
+		borrowLambdaQueryWrapper
+			.eq(Financing::getIsDeleted, 0)
+			.eq(Financing::getTenantId, AuthUtil.getTenantId())
+			.eq(Financing::getFinancingType, "1")
+			.eq(Financing::getCorpId, order.getId());
+		List<Financing> borrowList = financingService.list(borrowLambdaQueryWrapper);
+		BigDecimal borrow = borrowList.stream().map(Financing::getFinancingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+		//还款
+		LambdaQueryWrapper<Financing> stillLambdaQueryWrapper = new LambdaQueryWrapper<>();
+		stillLambdaQueryWrapper
+			.eq(Financing::getIsDeleted, 0)
+			.eq(Financing::getTenantId, AuthUtil.getTenantId())
+			.eq(Financing::getFinancingType, "2")
+			.eq(Financing::getCorpId, order.getId());
+		List<Financing> stillList = financingService.list(stillLambdaQueryWrapper);
+		BigDecimal still = stillList.stream().map(Financing::getFinancingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+		BigDecimal financing = still.subtract(borrow, MathContext.UNLIMITED);
+
+		//获取该客户还在库的货物金额
+		LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+		orderLambdaQueryWrapper
+			.eq(Order::getIsDeleted, 0)
+			.eq(Order::getTenantId, AuthUtil.getTenantId())
+			.eq(Order::getBillType, OrderTypeEnum.WAREHOUSING.getType())
+			.eq(Order::getTradeType, OrderTypeEnum.WOOD_HARVESTING_CLOUD.getType())
+			.eq(Order::getSpecialCheckStatus, 0)
+			.eq(Order::getPurchaserId, order.getId());
+		List<Order> orderList = baseMapper.selectList(orderLambdaQueryWrapper);
+		BigDecimal storageAmount = orderList.stream().map(Order::getStorageAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+		int num = financing.signum();
+		if (num == -1) {
+			if (storageAmount.compareTo(financing.abs()) < 0) {
+				return R.data("融资金额:" + financing + "大于 库存金额 :" + storageAmount + " 是否继续操作?");
+			}
+		}
+		return R.data("操作成功");
+	}
+
+	/**
 	 * 订单生成账单 并且推送财务消息
 	 *
 	 * @param order    订单信息
 	 * @param billType 货款类型: 申请 收费 付费
 	 * @param itemType 付款类型: 采购 销售 收货 发货
 	 */
-	@Transactional
+	@Transactional(rollbackFor = Exception.class)
+	@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 12000000)
 	public void paymentApply(OrderSubmitDto order, String billType, String itemType) {
 		//获取所属公司中文名
 		if (order.getBelongToCorpId() != null) {