no message
parent
6d64ca5662
commit
50a9c19e15
|
|
@ -5,16 +5,18 @@ import com.baomidou.mybatisplus.annotation.DbType;
|
||||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.*;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
|
||||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhyd.oauth.log.Log;
|
import me.zhyd.oauth.log.Log;
|
||||||
import net.sf.jsqlparser.expression.Expression;
|
import net.sf.jsqlparser.expression.Expression;
|
||||||
import net.sf.jsqlparser.expression.LongValue;
|
import net.sf.jsqlparser.expression.LongValue;
|
||||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||||
|
import org.apache.ibatis.executor.Executor;
|
||||||
|
import org.apache.ibatis.mapping.BoundSql;
|
||||||
|
import org.apache.ibatis.mapping.MappedStatement;
|
||||||
|
import org.apache.ibatis.session.ResultHandler;
|
||||||
|
import org.apache.ibatis.session.RowBounds;
|
||||||
import org.jeecg.common.config.TenantContext;
|
import org.jeecg.common.config.TenantContext;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.constant.TenantConstant;
|
import org.jeecg.common.constant.TenantConstant;
|
||||||
|
|
@ -27,34 +29,37 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单数据源配置(jeecg.datasource.open = false时生效)
|
* 单数据源配置(jeecg.datasource.open = false时生效)
|
||||||
* @Author zhoujf
|
|
||||||
*
|
*
|
||||||
|
* @Author zhoujf
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@MapperScan(value={"org.jeecg.modules.**.mapper*", "org.jeecg.**.mapper*","org.cpte.modules.**.mapper*", "org.cpte.**.mapper*"})
|
@MapperScan(value = {"org.jeecg.modules.**.mapper*", "org.jeecg.**.mapper*", "org.cpte.modules.**.mapper*", "org.cpte.**.mapper*"})
|
||||||
public class MybatisPlusSaasConfig {
|
public class MybatisPlusSaasConfig {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启系统模块的租户隔离
|
* 是否开启系统模块的租户隔离
|
||||||
* 控制范围:用户、角色、部门、我的部门、字典、分类字典、多数据源、职务、通知公告
|
* 控制范围:用户、角色、部门、我的部门、字典、分类字典、多数据源、职务、通知公告
|
||||||
*
|
* <p>
|
||||||
* 实现功能
|
* 实现功能
|
||||||
* 1.用户表通过硬编码实现租户ID隔离
|
* 1.用户表通过硬编码实现租户ID隔离
|
||||||
* 2.角色、部门、我的部门、字典、分类字典、多数据源、职务、通知公告除了硬编码还加入的 TENANT_TABLE 配置中,实现租户隔离更安全
|
* 2.角色、部门、我的部门、字典、分类字典、多数据源、职务、通知公告除了硬编码还加入的 TENANT_TABLE 配置中,实现租户隔离更安全
|
||||||
* 3.菜单表、租户表不做租户隔离
|
* 3.菜单表、租户表不做租户隔离
|
||||||
* 4.通过拦截器MybatisInterceptor实现,增删改查数据 自动注入租户ID
|
* 4.通过拦截器MybatisInterceptor实现,增删改查数据 自动注入租户ID
|
||||||
*/
|
*/
|
||||||
public static final Boolean OPEN_SYSTEM_TENANT_CONTROL = false;
|
public static final Boolean OPEN_SYSTEM_TENANT_CONTROL = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 哪些表需要做多租户 表需要添加一个字段 tenant_id
|
* 哪些表需要做多租户 表需要添加一个字段 tenant_id
|
||||||
*/
|
*/
|
||||||
|
|
@ -82,6 +87,22 @@ public class MybatisPlusSaasConfig {
|
||||||
TENANT_TABLE.add("airag_knowledge");
|
TENANT_TABLE.add("airag_knowledge");
|
||||||
TENANT_TABLE.add("airag_knowledge_doc");
|
TENANT_TABLE.add("airag_knowledge_doc");
|
||||||
TENANT_TABLE.add("airag_model");
|
TENANT_TABLE.add("airag_model");
|
||||||
|
|
||||||
|
TENANT_TABLE.add("base_area");
|
||||||
|
TENANT_TABLE.add("base_item");
|
||||||
|
TENANT_TABLE.add("base_point");
|
||||||
|
TENANT_TABLE.add("base_stock");
|
||||||
|
|
||||||
|
TENANT_TABLE.add("data_asn");
|
||||||
|
TENANT_TABLE.add("data_asn_detail");
|
||||||
|
TENANT_TABLE.add("data_receive_record");
|
||||||
|
TENANT_TABLE.add("data_pick");
|
||||||
|
TENANT_TABLE.add("data_pick_detail");
|
||||||
|
TENANT_TABLE.add("data_task");
|
||||||
|
TENANT_TABLE.add("data_agv_task");
|
||||||
|
TENANT_TABLE.add("data_inventory");
|
||||||
|
TENANT_TABLE.add("data_inventory_log");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.示例测试
|
//2.示例测试
|
||||||
|
|
@ -94,35 +115,36 @@ public class MybatisPlusSaasConfig {
|
||||||
@Bean
|
@Bean
|
||||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||||
|
|
||||||
// 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
|
// 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
|
||||||
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
|
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
|
||||||
@Override
|
@Override
|
||||||
public Expression getTenantId() {
|
public Expression getTenantId() {
|
||||||
String tenantId = TenantContext.getTenant();
|
String tenantId = TenantContext.getTenant();
|
||||||
//如果通过线程获取租户ID为空,则通过当前请求的request获取租户(shiro排除拦截器的请求会获取不到租户ID)
|
//如果通过线程获取租户ID为空,则通过当前请求的request获取租户(shiro排除拦截器的请求会获取不到租户ID)
|
||||||
if(oConvertUtils.isEmpty(tenantId)){
|
if (oConvertUtils.isEmpty(tenantId)) {
|
||||||
try {
|
try {
|
||||||
tenantId = TokenUtils.getTenantIdByRequest(SpringContextUtils.getHttpServletRequest());
|
tenantId = TokenUtils.getTenantIdByRequest(SpringContextUtils.getHttpServletRequest());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(oConvertUtils.isEmpty(tenantId)){
|
if (oConvertUtils.isEmpty(tenantId)) {
|
||||||
tenantId = "0";
|
tenantId = "0";
|
||||||
}
|
}
|
||||||
return new LongValue(tenantId);
|
return new LongValue(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTenantIdColumn(){
|
public String getTenantIdColumn() {
|
||||||
return TenantConstant.TENANT_ID_TABLE;
|
return TenantConstant.TENANT_ID_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回 true 表示不走租户逻辑
|
// 返回 true 表示不走租户逻辑
|
||||||
@Override
|
@Override
|
||||||
public boolean ignoreTable(String tableName) {
|
public boolean ignoreTable(String tableName) {
|
||||||
for(String temp: TENANT_TABLE){
|
for (String temp : TENANT_TABLE) {
|
||||||
if(temp.equalsIgnoreCase(tableName)){
|
if (temp.equalsIgnoreCase(tableName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,38 +154,38 @@ public class MybatisPlusSaasConfig {
|
||||||
//update-begin-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
|
//update-begin-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
|
||||||
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
|
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
|
||||||
//update-end-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
|
//update-end-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
|
||||||
|
|
||||||
//update-begin---author:scott ---date:2025-08-02 for:【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错---
|
//update-begin---author:scott ---date:2025-08-02 for:【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错---
|
||||||
DbType dbType = null;
|
DbType dbType = null;
|
||||||
try {
|
try {
|
||||||
dbType = JdbcUtils.getDbType(dataSource.getConnection().getMetaData().getURL());
|
dbType = JdbcUtils.getDbType(dataSource.getConnection().getMetaData().getURL());
|
||||||
log.info("当前数据库类型: {}", dbType);
|
log.info("当前数据库类型: {}", dbType);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
Log.error(e.getMessage(), e);
|
Log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
if (dbType!=null && (dbType == DbType.SQL_SERVER || dbType == DbType.SQL_SERVER2005)) {
|
if (dbType != null && (dbType == DbType.SQL_SERVER || dbType == DbType.SQL_SERVER2005)) {
|
||||||
// 如果是SQL Server则覆盖为2005分页方式
|
// 如果是SQL Server则覆盖为2005分页方式
|
||||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.SQL_SERVER2005));
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.SQL_SERVER2005));
|
||||||
} else {
|
} else {
|
||||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
|
||||||
}
|
}
|
||||||
//update-end---author:scott ---date::2025-08-02 for:【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错---
|
//update-end---author:scott ---date::2025-08-02 for:【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错---
|
||||||
|
|
||||||
//【jeecg-boot/issues/3847】增加@Version乐观锁支持
|
//【jeecg-boot/issues/3847】增加@Version乐观锁支持
|
||||||
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
||||||
|
|
||||||
|
interceptor.addInnerInterceptor(fixForUpdateOrderInterceptor());
|
||||||
return interceptor;
|
return interceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态表名切换拦截器,用于适配vue2和vue3同一个表有多个的情况,如sys_role_index在vue3情况下表名为sys_role_index_v3
|
* 动态表名切换拦截器,用于适配vue2和vue3同一个表有多个的情况,如sys_role_index在vue3情况下表名为sys_role_index_v3
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
|
private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
|
||||||
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
|
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
|
||||||
dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
|
dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
|
||||||
/* if (sql.contains("FOR UPDATE")) {
|
|
||||||
return tableName;
|
|
||||||
}*/
|
|
||||||
//获取需要动态解析的表名
|
//获取需要动态解析的表名
|
||||||
String dynamicTableName = ThreadLocalDataHelper.get(CommonConstant.DYNAMIC_TABLE_NAME);
|
String dynamicTableName = ThreadLocalDataHelper.get(CommonConstant.DYNAMIC_TABLE_NAME);
|
||||||
//当dynamicTableName不为空时才走动态表名处理逻辑,否则返回原始表名
|
//当dynamicTableName不为空时才走动态表名处理逻辑,否则返回原始表名
|
||||||
|
|
@ -180,6 +202,66 @@ public class MybatisPlusSaasConfig {
|
||||||
return dynamicTableNameInnerInterceptor;
|
return dynamicTableNameInnerInterceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InnerInterceptor fixForUpdateOrderInterceptor() {
|
||||||
|
return new InnerInterceptor() {
|
||||||
|
@Override
|
||||||
|
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
|
||||||
|
ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
|
||||||
|
String originalSql = boundSql.getSql();
|
||||||
|
String upperSql = originalSql.toUpperCase();
|
||||||
|
if (upperSql.contains("FOR UPDATE") && upperSql.contains("ORDER BY")) {
|
||||||
|
// 检查FOR UPDATE是否在ORDER BY之后
|
||||||
|
String fixedSql = moveForUpdateToEnd(upperSql);
|
||||||
|
try {
|
||||||
|
Field sqlField = BoundSql.class.getDeclaredField("sql");
|
||||||
|
sqlField.setAccessible(true);
|
||||||
|
sqlField.set(boundSql, fixedSql);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to fix FOR UPDATE order in SQL: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String moveForUpdateToEnd(String originalSql) {
|
||||||
|
if (originalSql == null || originalSql.trim().isEmpty()) {
|
||||||
|
return originalSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 将 SQL 转换为大写,以简化匹配过程,但保留原始大小写用于最终输出(通过捕获组实现)。
|
||||||
|
// 同时在处理前和处理后去除多余的首尾空格。
|
||||||
|
String sql = originalSql.trim();
|
||||||
|
|
||||||
|
// 2. 正则表达式模式解释:
|
||||||
|
// - (.*?):捕获语句开头到 FOR UPDATE 之前的任何内容 (第1组:SELECT/FROM/WHERE 部分)。
|
||||||
|
// - (\sFOR\sUPDATE\s*):捕获 'FOR UPDATE' (第2组:FOR UPDATE)。
|
||||||
|
// - (\sORDER\sBY\s.*):捕获 'ORDER BY' 及其之后的所有内容 (第3组:ORDER BY 部分)。
|
||||||
|
// - $:确保匹配到字符串末尾。
|
||||||
|
// - 关键字之间使用 \s 匹配空白字符,防止误匹配。
|
||||||
|
// - 使用 (?i) 开启不区分大小写匹配。
|
||||||
|
//
|
||||||
|
// 完整的原始结构: (SELECT/FROM/WHERE...) (FOR UPDATE) (ORDER BY...)
|
||||||
|
// 期望的替换结构: (SELECT/FROM/WHERE...) (ORDER BY...) (FOR UPDATE)
|
||||||
|
|
||||||
|
// 模式: 捕获 (SELECT/FROM/WHERE) + (FOR UPDATE) + (ORDER BY ...)
|
||||||
|
String regex = "(?is)(.*?)(\\sFOR\\sUPDATE\\s*)(\\sORDER\\sBY.*)";
|
||||||
|
|
||||||
|
// 替换表达式: $1 是 SELECT/FROM/WHERE 部分, $3 是 ORDER BY 部分, $2 是 FOR UPDATE 部分
|
||||||
|
String replacement = "$1$3$2";
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile(regex);
|
||||||
|
Matcher matcher = pattern.matcher(sql);
|
||||||
|
|
||||||
|
if (matcher.find()) {
|
||||||
|
// 如果找到匹配,则进行替换
|
||||||
|
return matcher.replaceAll(replacement);
|
||||||
|
} else {
|
||||||
|
// 如果没有匹配到包含 FOR UPDATE 和 ORDER BY 的特定顺序,则返回原始语句
|
||||||
|
return originalSql;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * 下个版本会删除,现在为了避免缓存出现问题不得不配置
|
// * 下个版本会删除,现在为了避免缓存出现问题不得不配置
|
||||||
// * @return
|
// * @return
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ public enum AsnStatusEnum {
|
||||||
|
|
||||||
RECEIVED(3, "收货完成"),
|
RECEIVED(3, "收货完成"),
|
||||||
|
|
||||||
CANCELED(4, "已取消"),
|
CLOSED(4, "已关闭"),
|
||||||
|
|
||||||
|
CANCELED(5, "已取消"),
|
||||||
|
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,18 @@ public class ConveyorLineController {
|
||||||
@AutoLog(value = "输送线扫描")
|
@AutoLog(value = "输送线扫描")
|
||||||
@Operation(summary = "输送线-扫描托盘")
|
@Operation(summary = "输送线-扫描托盘")
|
||||||
@PostMapping(value = "/scanTray")
|
@PostMapping(value = "/scanTray")
|
||||||
@IgnoreAuth
|
|
||||||
public Result<String> scanTray(@RequestBody @Valid ScanTrayRequest scanTrayRequest) {
|
public Result<String> scanTray(@RequestBody @Valid ScanTrayRequest scanTrayRequest) {
|
||||||
iConveyorLineService.scanTray(scanTrayRequest);
|
iConveyorLineService.scanTray(scanTrayRequest);
|
||||||
return Result.OK("扫描成功");
|
return Result.OK("扫描成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "输送线大屏")
|
||||||
|
@Operation(summary = "输送线-大屏显示")
|
||||||
|
@PostMapping(value = "/")
|
||||||
|
public Result<String> showConveyorLineBigScreen() {
|
||||||
|
iConveyorLineService.showConveyorLineBigScreen();
|
||||||
|
|
||||||
|
return Result.OK();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,6 @@ public interface IConveyorLineService {
|
||||||
* @param scanTrayRequest 扫描托盘请求参数
|
* @param scanTrayRequest 扫描托盘请求参数
|
||||||
*/
|
*/
|
||||||
void scanTray(ScanTrayRequest scanTrayRequest);
|
void scanTray(ScanTrayRequest scanTrayRequest);
|
||||||
|
|
||||||
|
void showConveyorLineBigScreen();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.cpte.modules.conveyorLine.vo;
|
||||||
|
|
||||||
|
public class ConveyorLineBigScreenVo {
|
||||||
|
private String stockCode;
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#{whCode}
|
#{whCode}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
ORDER BY create_time
|
||||||
FOR UPDATE
|
FOR UPDATE
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -85,7 +85,7 @@ public class Asn implements Serializable {
|
||||||
private java.lang.Integer orderType;
|
private java.lang.Integer orderType;
|
||||||
/**
|
/**
|
||||||
* 订单状态
|
* 订单状态
|
||||||
* 1.已创建;2.部分收货;3.收货完成;4.已取消
|
* 1.已创建;2.部分收货;3.收货完成;4.已关闭、5.已取消
|
||||||
*/
|
*/
|
||||||
@Excel(name = "订单状态", width = 15)
|
@Excel(name = "订单状态", width = 15)
|
||||||
@Schema(description = "订单状态")
|
@Schema(description = "订单状态")
|
||||||
|
|
|
||||||
|
|
@ -279,16 +279,18 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void receiveCallback(Asn asn, AsnDetail asnDetail, Stock stock) {
|
public void receiveCallback(Asn asn, AsnDetail asnDetail, Stock stock) {
|
||||||
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK);
|
|
||||||
String json = receiveCallbackJson(asn, asnDetail, stock);
|
|
||||||
|
|
||||||
log.info("入库回传请求报文:{}", json);
|
|
||||||
// 检查接口开关, 未开启则返回
|
// 检查接口开关, 未开启则返回
|
||||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||||
updateAsnDetailResponse(asn, "接口未开启");
|
updateAsnDetailResponse(asn, "接口未开启");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(AsnStatusEnum.){
|
||||||
|
|
||||||
|
}
|
||||||
|
String json = receiveCallbackJson(asn, asnDetail, stock);
|
||||||
|
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK);
|
||||||
|
log.info("入库回传请求报文:{}", json);
|
||||||
Boolean Success = null;
|
Boolean Success = null;
|
||||||
String Message = null;
|
String Message = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
package org.cpte.modules.saiWms.service;
|
package org.cpte.modules.saiWms.service;
|
||||||
|
|
||||||
import org.cpte.modules.base.entity.Stock;
|
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
|
||||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,17 +58,11 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
@RequestMapping("/shipping/pick")
|
@RequestMapping("/shipping/pick")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class PickController {
|
public class PickController {
|
||||||
@Autowired
|
|
||||||
private PickMapper pickMapper;
|
|
||||||
@Autowired
|
|
||||||
private TaskMapper taskMapper;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPickService pickService;
|
private IPickService pickService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPickDetailService pickDetailService;
|
private IPickDetailService pickDetailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ITaskService taskService;
|
|
||||||
@Autowired
|
|
||||||
private PickSerialNumberRule pickSerialNumberRule;
|
private PickSerialNumberRule pickSerialNumberRule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -277,19 +271,4 @@ public class PickController {
|
||||||
}
|
}
|
||||||
return Result.OK("文件导入失败!");
|
return Result.OK("文件导入失败!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 出库分配
|
|
||||||
*/
|
|
||||||
@AutoLog(value = "出库分配")
|
|
||||||
@Operation(summary = "出库分配")
|
|
||||||
@PostMapping(value = "/allocatedPick")
|
|
||||||
@IgnoreAuth
|
|
||||||
public Result<String> allocatedPick() {
|
|
||||||
List<Long> pickList = pickMapper.queryUnallocatedPick();
|
|
||||||
pickService.allocatePick2(pickList);
|
|
||||||
taskService.generateAgvTask();
|
|
||||||
return Result.OK("操作成功!");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,6 @@ public interface TaskMapper extends BaseMapper<Task> {
|
||||||
*
|
*
|
||||||
* @return List<Pick>
|
* @return List<Pick>
|
||||||
*/
|
*/
|
||||||
@Select("SELECT t.* FROM data_task t WHERE t.agv_task_id IS NULL ORDER BY t.create_time ASC FOR UPDATE ")
|
@Select("SELECT * FROM data_task WHERE agv_task_id is null order by create_time for update ")
|
||||||
List<Task> queryUnallocatedTask();
|
List<Task> queryUnallocatedTask();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="org.cpte.modules.shipping.mapper.TaskMapper">
|
<mapper namespace="org.cpte.modules.shipping.mapper.TaskMapper">
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -3,6 +3,7 @@ package org.cpte.modules.shipping.service;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
import org.cpte.modules.shipping.entity.PickDetail;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.cpte.modules.shipping.entity.Task;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -60,4 +61,12 @@ public interface IPickService extends IService<Pick> {
|
||||||
*/
|
*/
|
||||||
List<String> allocatePick2(List<Long> pickIds);
|
List<String> allocatePick2(List<Long> pickIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出库任务回传
|
||||||
|
*
|
||||||
|
* @param task 任务
|
||||||
|
*/
|
||||||
|
void pickTaskCallback(Task task);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -542,4 +542,9 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
||||||
return new ArrayList<>(errorMsgSet);
|
return new ArrayList<>(errorMsgSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pickTaskCallback(Task task) {
|
||||||
|
Pick pick = pickMapper.selectById(task.getPickId());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void generateAgvTask() {
|
public void generateAgvTask() {
|
||||||
|
|
||||||
List<Task> taskList = taskMapper.queryUnallocatedTask();
|
List<Task> taskList = taskMapper.queryUnallocatedTask();
|
||||||
if (CollectionUtils.isEmpty(taskList)) {
|
if (CollectionUtils.isEmpty(taskList)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@ public class CodeGeneratorUtil {
|
||||||
try {
|
try {
|
||||||
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
||||||
|
|
||||||
// 使用 SELECT FOR UPDATE 加锁查询并更新
|
// 使用 SELECT for update 加锁查询并更新
|
||||||
String lockAndUpdateSql =
|
String lockAndUpdateSql =
|
||||||
"SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? FOR UPDATE";
|
"SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? for update";
|
||||||
|
|
||||||
List<Integer> result = jdbcTemplate.queryForList(lockAndUpdateSql, Integer.class, type, dateStr);
|
List<Integer> result = jdbcTemplate.queryForList(lockAndUpdateSql, Integer.class, type, dateStr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package org.cpte.modules.utils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Map<String, String> saiMap = new HashMap<>();
|
||||||
|
saiMap.put("ak", "ak-h98TNj1bO5258uuS");
|
||||||
|
saiMap.put("sk", "E20j9w4vkTkLkv6tjALrzYqcybrvDaCx");
|
||||||
|
|
||||||
|
Map<String, String> tesMap = new HashMap<>();
|
||||||
|
tesMap.put("ak", "ak-EMCNIpxwfMXzJ8rj");
|
||||||
|
tesMap.put("sk", "HtT14KlSwCfLfLyGe3FeJVPc3zmjZwXR");
|
||||||
|
|
||||||
|
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
System.out.println("sai-timestamp:" + timestamp);
|
||||||
|
System.out.println("sai-signature:" + md5(saiMap.get("ak")+ saiMap.get("sk") + timestamp));
|
||||||
|
System.out.println("=======================================================================================");
|
||||||
|
System.out.println("tes-timestamp:" + timestamp);
|
||||||
|
System.out.println("tes-signature:" + md5(tesMap.get("ak")+ tesMap.get("sk") + timestamp));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String md5(String sourceStr) {
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
md.update(sourceStr.getBytes(StandardCharsets.UTF_8));
|
||||||
|
byte[] hash = md.digest();
|
||||||
|
int i;
|
||||||
|
StringBuffer buf = new StringBuffer(32);
|
||||||
|
for (int offset = 0; offset < hash.length; offset++) {
|
||||||
|
i = hash[offset];
|
||||||
|
if (i < 0) {
|
||||||
|
i += 256;
|
||||||
|
}
|
||||||
|
if (i < 16) {
|
||||||
|
buf.append("0");
|
||||||
|
}
|
||||||
|
buf.append(Integer.toHexString(i));
|
||||||
|
}
|
||||||
|
result = buf.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("sign签名错误" + e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue