diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql
index ae49821..5b6be1f 100644
--- a/sql/sqlserver/ruoyi-vue-pro.sql
+++ b/sql/sqlserver/ruoyi-vue-pro.sql
@@ -43,7 +43,7 @@ CREATE TABLE infra_api_access_log (
id bigint NOT NULL PRIMARY KEY IDENTITY,
trace_id nvarchar(64) DEFAULT '' NOT NULL,
user_id bigint DEFAULT 0 NOT NULL,
- user_type tinyint DEFAULT 0 NOT NULL,
+ user_type smallint DEFAULT 0 NOT NULL,
application_name nvarchar(50) NOT NULL,
request_method nvarchar(16) DEFAULT '' NOT NULL,
request_url nvarchar(255) DEFAULT '' NOT NULL,
@@ -53,7 +53,7 @@ CREATE TABLE infra_api_access_log (
user_agent nvarchar(512) NOT NULL,
operate_module nvarchar(50) DEFAULT NULL NULL,
operate_name nvarchar(50) DEFAULT NULL NULL,
- operate_type tinyint DEFAULT 0 NULL,
+ operate_type smallint DEFAULT 0 NULL,
begin_time datetime2 NOT NULL,
end_time datetime2 NOT NULL,
duration int NOT NULL,
@@ -260,7 +260,7 @@ CREATE TABLE infra_api_error_log (
id bigint NOT NULL PRIMARY KEY IDENTITY,
trace_id nvarchar(64) NOT NULL,
user_id bigint DEFAULT 0 NOT NULL,
- user_type tinyint DEFAULT 0 NOT NULL,
+ user_type smallint DEFAULT 0 NOT NULL,
application_name nvarchar(50) NOT NULL,
request_method nvarchar(16) NOT NULL,
request_url nvarchar(255) NOT NULL,
@@ -276,7 +276,7 @@ CREATE TABLE infra_api_error_log (
exception_file_name nvarchar(512) NOT NULL,
exception_method_name nvarchar(512) NOT NULL,
exception_line_number int NOT NULL,
- process_status tinyint NOT NULL,
+ process_status smallint NOT NULL,
process_time datetime2 DEFAULT NULL NULL,
process_user_id int DEFAULT 0 NULL,
creator nvarchar(64) DEFAULT '' NULL,
@@ -503,18 +503,18 @@ CREATE TABLE infra_codegen_column (
column_name nvarchar(200) NOT NULL,
data_type nvarchar(100) NOT NULL,
column_comment nvarchar(500) NOT NULL,
- nullable varchar(1) NOT NULL,
- primary_key varchar(1) NOT NULL,
+ nullable bit NOT NULL,
+ primary_key bit NOT NULL,
ordinal_position int NOT NULL,
java_type nvarchar(32) NOT NULL,
java_field nvarchar(64) NOT NULL,
dict_type nvarchar(200) DEFAULT '' NULL,
example nvarchar(64) DEFAULT NULL NULL,
- create_operation varchar(1) NOT NULL,
- update_operation varchar(1) NOT NULL,
- list_operation varchar(1) NOT NULL,
+ create_operation bit NOT NULL,
+ update_operation bit NOT NULL,
+ list_operation bit NOT NULL,
list_operation_condition nvarchar(32) DEFAULT '=' NOT NULL,
- list_operation_result varchar(1) NOT NULL,
+ list_operation_result bit NOT NULL,
html_type nvarchar(32) NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -701,7 +701,7 @@ GO
CREATE TABLE infra_codegen_table (
id bigint NOT NULL PRIMARY KEY IDENTITY,
data_source_config_id bigint NOT NULL,
- scene tinyint DEFAULT 1 NOT NULL,
+ scene smallint DEFAULT 1 NOT NULL,
table_name nvarchar(200) DEFAULT '' NOT NULL,
table_comment nvarchar(500) DEFAULT '' NOT NULL,
remark nvarchar(500) DEFAULT NULL NULL,
@@ -710,12 +710,12 @@ CREATE TABLE infra_codegen_table (
class_name nvarchar(100) DEFAULT '' NOT NULL,
class_comment nvarchar(50) NOT NULL,
author nvarchar(50) NOT NULL,
- template_type tinyint DEFAULT 1 NOT NULL,
- front_type tinyint NOT NULL,
+ template_type smallint DEFAULT 1 NOT NULL,
+ front_type smallint NOT NULL,
parent_menu_id bigint DEFAULT NULL NULL,
master_table_id bigint DEFAULT NULL NULL,
sub_join_column_id bigint DEFAULT NULL NULL,
- sub_join_many varchar(1) DEFAULT NULL NULL,
+ sub_join_many bit DEFAULT NULL NULL,
tree_parent_column_id bigint DEFAULT NULL NULL,
tree_name_column_id bigint DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
@@ -907,11 +907,11 @@ GO
CREATE TABLE infra_config (
id bigint NOT NULL PRIMARY KEY IDENTITY,
category nvarchar(50) NOT NULL,
- type tinyint NOT NULL,
+ type smallint NOT NULL,
name nvarchar(100) DEFAULT '' NOT NULL,
config_key nvarchar(100) DEFAULT '' NOT NULL,
value nvarchar(500) DEFAULT '' NOT NULL,
- visible varchar(1) NOT NULL,
+ visible bit NOT NULL,
remark nvarchar(500) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -1260,9 +1260,9 @@ GO
CREATE TABLE infra_file_config (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(63) NOT NULL,
- storage tinyint NOT NULL,
+ storage smallint NOT NULL,
remark nvarchar(255) DEFAULT NULL NULL,
- master varchar(1) NOT NULL,
+ master bit NOT NULL,
config nvarchar(4000) NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -1487,7 +1487,7 @@ GO
CREATE TABLE infra_job (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(32) NOT NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
handler_name nvarchar(64) NOT NULL,
handler_param nvarchar(255) DEFAULT NULL NULL,
cron_expression nvarchar(32) NOT NULL,
@@ -1687,11 +1687,11 @@ CREATE TABLE infra_job_log (
job_id bigint NOT NULL,
handler_name nvarchar(64) NOT NULL,
handler_param nvarchar(255) DEFAULT NULL NULL,
- execute_index tinyint DEFAULT 1 NOT NULL,
+ execute_index smallint DEFAULT 1 NOT NULL,
begin_time datetime2 NOT NULL,
end_time datetime2 DEFAULT NULL NULL,
duration int DEFAULT NULL NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
result nvarchar(4000) DEFAULT '' NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -1829,7 +1829,7 @@ CREATE TABLE system_dept (
leader_user_id bigint DEFAULT NULL NULL,
phone nvarchar(11) DEFAULT NULL NULL,
email nvarchar(50) DEFAULT NULL NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -1999,7 +1999,7 @@ CREATE TABLE system_dict_data (
label nvarchar(100) DEFAULT '' NOT NULL,
value nvarchar(100) DEFAULT '' NOT NULL,
dict_type nvarchar(100) DEFAULT '' NOT NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
color_type nvarchar(100) DEFAULT '' NULL,
css_class nvarchar(100) DEFAULT '' NULL,
remark nvarchar(500) DEFAULT NULL NULL,
@@ -5251,7 +5251,7 @@ CREATE TABLE system_dict_type (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(100) DEFAULT '' NOT NULL,
type nvarchar(100) DEFAULT '' NOT NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
remark nvarchar(500) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -6056,9 +6056,9 @@ CREATE TABLE system_login_log (
log_type bigint NOT NULL,
trace_id nvarchar(64) DEFAULT '' NOT NULL,
user_id bigint DEFAULT 0 NOT NULL,
- user_type tinyint DEFAULT 0 NOT NULL,
+ user_type smallint DEFAULT 0 NOT NULL,
username nvarchar(50) DEFAULT '' NOT NULL,
- result tinyint NOT NULL,
+ result smallint NOT NULL,
user_ip nvarchar(50) NOT NULL,
user_agent nvarchar(512) NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
@@ -6197,8 +6197,8 @@ CREATE TABLE system_mail_account (
password nvarchar(255) NOT NULL,
host nvarchar(255) NOT NULL,
port int NOT NULL,
- ssl_enable varchar(1) DEFAULT '0' NOT NULL,
- starttls_enable varchar(1) DEFAULT '0' NOT NULL,
+ ssl_enable bit DEFAULT 0 NOT NULL,
+ starttls_enable bit DEFAULT 0 NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -6333,7 +6333,7 @@ GO
CREATE TABLE system_mail_log (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint DEFAULT NULL NULL,
- user_type tinyint DEFAULT NULL NULL,
+ user_type smallint DEFAULT NULL NULL,
to_mails nvarchar(1024) NOT NULL,
cc_mails nvarchar(1024) DEFAULT NULL NULL,
bcc_mails nvarchar(1024) DEFAULT NULL NULL,
@@ -6345,7 +6345,7 @@ CREATE TABLE system_mail_log (
template_title nvarchar(255) NOT NULL,
template_content nvarchar(max) NOT NULL,
template_params nvarchar(255) NOT NULL,
- send_status tinyint DEFAULT 0 NOT NULL,
+ send_status smallint DEFAULT 0 NOT NULL,
send_time datetime2 DEFAULT NULL NULL,
send_message_id nvarchar(255) DEFAULT NULL NULL,
send_exception nvarchar(4000) DEFAULT NULL NULL,
@@ -6537,7 +6537,7 @@ CREATE TABLE system_mail_template (
title nvarchar(255) NOT NULL,
content nvarchar(4000) NOT NULL,
params nvarchar(255) NOT NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
remark nvarchar(255) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -6686,17 +6686,17 @@ CREATE TABLE system_menu (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(50) NOT NULL,
permission nvarchar(100) DEFAULT '' NOT NULL,
- type tinyint NOT NULL,
+ type smallint NOT NULL,
sort int DEFAULT 0 NOT NULL,
parent_id bigint DEFAULT 0 NOT NULL,
path nvarchar(200) DEFAULT '' NULL,
icon nvarchar(100) DEFAULT '#' NULL,
component nvarchar(255) DEFAULT NULL NULL,
component_name nvarchar(255) DEFAULT NULL NULL,
- status tinyint DEFAULT 0 NOT NULL,
- visible varchar(1) DEFAULT '1' NOT NULL,
- keep_alive varchar(1) DEFAULT '1' NOT NULL,
- always_show varchar(1) DEFAULT '1' NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ visible bit DEFAULT 1 NOT NULL,
+ keep_alive bit DEFAULT 1 NOT NULL,
+ always_show bit DEFAULT 1 NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -11190,8 +11190,8 @@ CREATE TABLE system_notice (
id bigint NOT NULL PRIMARY KEY IDENTITY,
title nvarchar(50) NOT NULL,
content nvarchar(max) NOT NULL,
- type tinyint NOT NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ type smallint NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -11311,14 +11311,14 @@ GO
CREATE TABLE system_notify_message (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
- user_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
template_id bigint NOT NULL,
template_code nvarchar(64) NOT NULL,
template_nickname nvarchar(63) NOT NULL,
template_content nvarchar(1024) NOT NULL,
template_type int NOT NULL,
template_params nvarchar(255) NOT NULL,
- read_status varchar(1) NOT NULL,
+ read_status bit NOT NULL,
read_time datetime2 DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -11671,9 +11671,9 @@ CREATE TABLE system_notify_template (
code nvarchar(64) NOT NULL,
nickname nvarchar(255) NOT NULL,
content nvarchar(1024) NOT NULL,
- type tinyint NOT NULL,
+ type smallint NOT NULL,
params nvarchar(255) DEFAULT NULL NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
remark nvarchar(255) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -11794,7 +11794,7 @@ GO
CREATE TABLE system_oauth2_access_token (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
- user_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
user_info nvarchar(512) NOT NULL,
access_token nvarchar(255) NOT NULL,
refresh_token nvarchar(32) NOT NULL,
@@ -11933,10 +11933,10 @@ GO
CREATE TABLE system_oauth2_approve (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
- user_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
client_id nvarchar(255) NOT NULL,
scope nvarchar(255) DEFAULT '' NOT NULL,
- approved varchar(1) DEFAULT '0' NOT NULL,
+ approved bit DEFAULT 0 NOT NULL,
expires_time datetime2 NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -12058,7 +12058,7 @@ CREATE TABLE system_oauth2_client (
name nvarchar(255) NOT NULL,
logo nvarchar(255) NOT NULL,
description nvarchar(255) DEFAULT NULL NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
access_token_validity_seconds int NOT NULL,
refresh_token_validity_seconds int NOT NULL,
redirect_uris nvarchar(255) NOT NULL,
@@ -12261,7 +12261,7 @@ GO
CREATE TABLE system_oauth2_code (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
- user_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
code nvarchar(32) NOT NULL,
client_id nvarchar(255) NOT NULL,
scopes nvarchar(255) DEFAULT '' NULL,
@@ -12399,7 +12399,7 @@ CREATE TABLE system_oauth2_refresh_token (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
refresh_token nvarchar(32) NOT NULL,
- user_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
client_id nvarchar(255) NOT NULL,
scopes nvarchar(255) DEFAULT NULL NULL,
expires_time datetime2 NOT NULL,
@@ -12520,12 +12520,12 @@ CREATE TABLE system_operate_log (
id bigint NOT NULL PRIMARY KEY IDENTITY,
trace_id nvarchar(64) DEFAULT '' NOT NULL,
user_id bigint NOT NULL,
- user_type tinyint DEFAULT 0 NOT NULL,
+ user_type smallint DEFAULT 0 NOT NULL,
type nvarchar(50) NOT NULL,
sub_type nvarchar(50) NOT NULL,
biz_id bigint NOT NULL,
action nvarchar(2000) DEFAULT '' NOT NULL,
- success varchar(1) DEFAULT '1' NOT NULL,
+ success bit DEFAULT 1 NOT NULL,
extra nvarchar(2000) DEFAULT '' NOT NULL,
request_method nvarchar(16) DEFAULT '' NULL,
request_url nvarchar(255) DEFAULT '' NULL,
@@ -12700,7 +12700,7 @@ CREATE TABLE system_post (
code nvarchar(64) NOT NULL,
name nvarchar(50) NOT NULL,
sort int NOT NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
remark nvarchar(500) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -12832,10 +12832,10 @@ CREATE TABLE system_role (
name nvarchar(30) NOT NULL,
code nvarchar(100) NOT NULL,
sort int NOT NULL,
- data_scope tinyint DEFAULT 1 NOT NULL,
+ data_scope smallint DEFAULT 1 NOT NULL,
data_scope_dept_ids nvarchar(500) DEFAULT '' NOT NULL,
- status tinyint NOT NULL,
- type tinyint NOT NULL,
+ status smallint NOT NULL,
+ type smallint NOT NULL,
remark nvarchar(500) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -16200,7 +16200,7 @@ CREATE TABLE system_sms_channel (
id bigint NOT NULL PRIMARY KEY IDENTITY,
signature nvarchar(12) NOT NULL,
code nvarchar(63) NOT NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
remark nvarchar(255) DEFAULT NULL NULL,
api_key nvarchar(128) NOT NULL,
api_secret nvarchar(128) DEFAULT NULL NULL,
@@ -16339,9 +16339,9 @@ CREATE TABLE system_sms_code (
mobile nvarchar(11) NOT NULL,
code nvarchar(6) NOT NULL,
create_ip nvarchar(15) NOT NULL,
- scene tinyint NOT NULL,
- today_index tinyint NOT NULL,
- used tinyint NOT NULL,
+ scene smallint NOT NULL,
+ today_index smallint NOT NULL,
+ used smallint NOT NULL,
used_time datetime2 DEFAULT NULL NULL,
used_ip nvarchar(255) DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
@@ -16477,20 +16477,20 @@ CREATE TABLE system_sms_log (
channel_code nvarchar(63) NOT NULL,
template_id bigint NOT NULL,
template_code nvarchar(63) NOT NULL,
- template_type tinyint NOT NULL,
+ template_type smallint NOT NULL,
template_content nvarchar(255) NOT NULL,
template_params nvarchar(255) NOT NULL,
api_template_id nvarchar(63) NOT NULL,
mobile nvarchar(11) NOT NULL,
user_id bigint DEFAULT NULL NULL,
- user_type tinyint DEFAULT NULL NULL,
- send_status tinyint DEFAULT 0 NOT NULL,
+ user_type smallint DEFAULT NULL NULL,
+ send_status smallint DEFAULT 0 NOT NULL,
send_time datetime2 DEFAULT NULL NULL,
api_send_code nvarchar(63) DEFAULT NULL NULL,
api_send_msg nvarchar(255) DEFAULT NULL NULL,
api_request_id nvarchar(255) DEFAULT NULL NULL,
api_serial_no nvarchar(255) DEFAULT NULL NULL,
- receive_status tinyint DEFAULT 0 NOT NULL,
+ receive_status smallint DEFAULT 0 NOT NULL,
receive_time datetime2 DEFAULT NULL NULL,
api_receive_code nvarchar(63) DEFAULT NULL NULL,
api_receive_msg nvarchar(255) DEFAULT NULL NULL,
@@ -16703,8 +16703,8 @@ DROP TABLE IF EXISTS system_sms_template
GO
CREATE TABLE system_sms_template (
id bigint NOT NULL PRIMARY KEY IDENTITY,
- type tinyint NOT NULL,
- status tinyint NOT NULL,
+ type smallint NOT NULL,
+ status smallint NOT NULL,
code nvarchar(63) NOT NULL,
name nvarchar(63) NOT NULL,
content nvarchar(255) NOT NULL,
@@ -16890,13 +16890,13 @@ GO
CREATE TABLE system_social_client (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(255) NOT NULL,
- social_type tinyint NOT NULL,
- user_type tinyint NOT NULL,
+ social_type smallint NOT NULL,
+ user_type smallint NOT NULL,
client_id nvarchar(255) NOT NULL,
client_secret nvarchar(255) NOT NULL,
agent_id nvarchar(255) DEFAULT NULL NULL,
public_key nvarchar(2048) DEFAULT NULL NULL,
- status tinyint NOT NULL,
+ status smallint NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -17053,7 +17053,7 @@ DROP TABLE IF EXISTS system_social_user
GO
CREATE TABLE system_social_user (
id bigint NOT NULL PRIMARY KEY IDENTITY,
- type tinyint NOT NULL,
+ type smallint NOT NULL,
openid nvarchar(32) NOT NULL,
token nvarchar(256) DEFAULT NULL NULL,
raw_token_info nvarchar(1024) NOT NULL,
@@ -17201,8 +17201,8 @@ GO
CREATE TABLE system_social_user_bind (
id bigint NOT NULL PRIMARY KEY IDENTITY,
user_id bigint NOT NULL,
- user_type tinyint NOT NULL,
- social_type tinyint NOT NULL,
+ user_type smallint NOT NULL,
+ social_type smallint NOT NULL,
social_user_id bigint NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
@@ -17309,7 +17309,7 @@ CREATE TABLE system_tenant (
contact_user_id bigint DEFAULT NULL NULL,
contact_name nvarchar(30) NOT NULL,
contact_mobile nvarchar(500) DEFAULT NULL NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
websites nvarchar(1024) DEFAULT '' NULL,
package_id bigint NOT NULL,
expire_time datetime2 NOT NULL,
@@ -17460,7 +17460,7 @@ GO
CREATE TABLE system_tenant_package (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(30) NOT NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
remark nvarchar(256) DEFAULT '' NULL,
menu_ids nvarchar(4000) NOT NULL,
creator nvarchar(64) DEFAULT '' NOT NULL,
@@ -17850,9 +17850,9 @@ CREATE TABLE system_users (
post_ids nvarchar(255) DEFAULT NULL NULL,
email nvarchar(50) DEFAULT '' NULL,
mobile nvarchar(11) DEFAULT '' NULL,
- sex tinyint DEFAULT 0 NULL,
+ sex smallint DEFAULT 0 NULL,
avatar nvarchar(512) DEFAULT '' NULL,
- status tinyint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
login_ip nvarchar(50) DEFAULT '' NULL,
login_date datetime2 DEFAULT NULL NULL,
creator nvarchar(64) DEFAULT '' NULL,
@@ -18082,7 +18082,7 @@ GO
CREATE TABLE yudao_demo01_contact (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(100) DEFAULT '' NOT NULL,
- sex tinyint NOT NULL,
+ sex smallint NOT NULL,
birthday datetime2 NOT NULL,
description nvarchar(255) NOT NULL,
avatar nvarchar(512) DEFAULT NULL NULL,
@@ -18323,7 +18323,7 @@ CREATE TABLE yudao_demo03_course (
id bigint NOT NULL PRIMARY KEY IDENTITY,
student_id bigint NOT NULL,
name nvarchar(100) DEFAULT '' NOT NULL,
- score tinyint NOT NULL,
+ score smallint NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
create_time datetime2 DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater nvarchar(64) DEFAULT '' NULL,
@@ -18578,7 +18578,7 @@ GO
CREATE TABLE yudao_demo03_student (
id bigint NOT NULL PRIMARY KEY IDENTITY,
name nvarchar(100) DEFAULT '' NOT NULL,
- sex tinyint NOT NULL,
+ sex smallint NOT NULL,
birthday datetime2 NOT NULL,
description nvarchar(255) NOT NULL,
creator nvarchar(64) DEFAULT '' NULL,
diff --git a/sql/tools/convertor.py b/sql/tools/convertor.py
index b2e804a..22b8d06 100644
--- a/sql/tools/convertor.py
+++ b/sql/tools/convertor.py
@@ -800,9 +800,20 @@ class SQLServerConvertor(Convertor):
if type in ("datetime", "timestamp"):
return "datetime2"
if type == "bit":
- return "varchar(1)"
+ # MySQL bit(1) 与 SQL Server bit 均只有 0、1、NULL;多位的位串不是布尔值,暂不支持
+ if size not in (None, 1):
+ raise ValueError(f"SQL Server 转换暂不支持 bit({size}),仅支持 bit(1)")
+ return "bit"
+ # SQL Server 的 tinyint 为 0 ~ 255,smallint 为 -32768 ~ 32767,需要选择能容纳 MySQL 取值范围的类型
if type in ("tinyint", "smallint"):
+ # 有符号:MySQL tinyint 为 -128 ~ 127,smallint 为 -32768 ~ 32767
+ return "smallint"
+ if type == "tinyint unsigned":
+ # 无符号:0 ~ 255
return "tinyint"
+ if type == "smallint unsigned":
+ # 无符号:0 ~ 65535
+ return "int"
if type in ("text", "longtext"):
return "nvarchar(max)"
if type in ("blob", "mediumblob"):
@@ -825,7 +836,11 @@ class SQLServerConvertor(Convertor):
type = col["type"].lower()
full_type = self.translate_type(type, col["size"])
nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
+ default_value = col["default"]
+ # bit 的默认值使用数字常量:b'0'、b'1' 在清理后为 '0'、'1'
+ if full_type == "bit" and default_value in ("'0'", "'1'"):
+ default_value = default_value.strip("'")
+ default = f"DEFAULT {default_value}" if default_value is not None else ""
return f"{name} {full_type} {default} {nullable}"
table_name = ddl["table_name"].lower()
diff --git a/sql/tools/test_convertor.py b/sql/tools/test_convertor.py
index 8090c7a..910b209 100644
--- a/sql/tools/test_convertor.py
+++ b/sql/tools/test_convertor.py
@@ -286,6 +286,130 @@ INSERT INTO `demo_bom` (`id`, `name`) VALUES (1, 'a\ufeffb');
self.assertNotIn("Table structure for ghost", out)
+class SQLServerConvertorTest(unittest.TestCase):
+ # MySQL 整数取值范围:https://dev.mysql.com/doc/refman/8.4/en/integer-types.html
+ MYSQL_INTEGER_RANGES = {
+ "tinyint": (-128, 127),
+ "tinyint unsigned": (0, 255),
+ "smallint": (-32768, 32767),
+ "smallint unsigned": (0, 65535),
+ }
+ # SQL Server 整数取值范围:https://learn.microsoft.com/sql/t-sql/data-types/int-bigint-smallint-and-tinyint-transact-sql
+ SQLSERVER_INTEGER_RANGES = {
+ "tinyint": (0, 255),
+ "smallint": (-32768, 32767),
+ "int": (-2 ** 31, 2 ** 31 - 1),
+ "bigint": (-2 ** 63, 2 ** 63 - 1),
+ }
+
+ TYPE_TABLE = """
+DROP TABLE IF EXISTS `demo_type`;
+CREATE TABLE `demo_type` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+ `grade` tinyint NOT NULL DEFAULT 0 COMMENT '有符号 tinyint',
+ `sex` tinyint(1) NOT NULL DEFAULT 0 COMMENT '性别',
+ `score` smallint NOT NULL DEFAULT 0 COMMENT '有符号 smallint',
+ `ratio` tinyint unsigned NOT NULL DEFAULT 255 COMMENT '无符号 tinyint',
+ `port` smallint unsigned NOT NULL DEFAULT 65535 COMMENT '无符号 smallint',
+ `enabled` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否启用',
+ `visible` bit(1) NULL DEFAULT NULL COMMENT '是否可见',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '类型表';
+
+BEGIN;
+INSERT INTO `demo_type` (`id`, `grade`, `sex`, `score`, `ratio`, `port`, `enabled`, `visible`, `deleted`) VALUES (1, -128, 1, -32768, 255, 65535, b'0', NULL, b'0');
+INSERT INTO `demo_type` (`id`, `grade`, `sex`, `score`, `ratio`, `port`, `enabled`, `visible`, `deleted`) VALUES (2, 127, 0, 32767, 0, 0, b'1', b'1', b'0');
+COMMIT;
+"""
+
+ def setUp(self):
+ directory = tempfile.TemporaryDirectory()
+ self.addCleanup(directory.cleanup)
+ self.directory = directory.name
+
+ def write_sql(self, content):
+ path = os.path.join(self.directory, "dump.sql")
+ with open(path, "w", encoding="utf-8") as f:
+ f.write(content)
+ return path
+
+ def test_translate_type_integer_range(self):
+ convertor = SQLServerConvertor(self.write_sql(HEADER + DEMO_TABLE))
+ for mysql_type, (mysql_min, mysql_max) in self.MYSQL_INTEGER_RANGES.items():
+ with self.subTest(mysql_type):
+ target_type = convertor.translate_type(mysql_type, None)
+ target_min, target_max = self.SQLSERVER_INTEGER_RANGES[target_type]
+ # 目标类型需要容纳负数、大于 255 等全部取值
+ self.assertLessEqual(target_min, mysql_min)
+ self.assertGreaterEqual(target_max, mysql_max)
+ # tinyint(1) 的显示宽度不影响取值范围
+ self.assertEqual("smallint", convertor.translate_type("tinyint", 1))
+ # 无符号 tinyint 保持 tinyint,不扩大类型
+ self.assertEqual("tinyint", convertor.translate_type("TINYINT UNSIGNED", None))
+
+ def test_translate_type_bit(self):
+ convertor = SQLServerConvertor(self.write_sql(HEADER + DEMO_TABLE))
+ self.assertEqual("bit", convertor.translate_type("bit", 1))
+ self.assertEqual("bit", convertor.translate_type("bit", None))
+ # 多位的位串不是布尔值,不能转换为 bit
+ with self.assertRaises(ValueError):
+ convertor.translate_type("bit", 8)
+
+ def test_integer_and_bit(self):
+ out, err = convert(SQLServerConvertor(self.write_sql(HEADER + self.TYPE_TABLE)))
+ self.assertNotIn("无法正常解析", err)
+ # 有符号 tinyint、smallint:smallint
+ self.assertIn("grade smallint DEFAULT 0 NOT NULL", out)
+ self.assertIn("sex smallint DEFAULT 0 NOT NULL", out)
+ self.assertIn("score smallint DEFAULT 0 NOT NULL", out)
+ # 无符号 tinyint:tinyint;无符号 smallint:int
+ self.assertIn("ratio tinyint DEFAULT 255 NOT NULL", out)
+ self.assertIn("port int DEFAULT 65535 NOT NULL", out)
+ # bit(1):bit,默认值为数字常量,允许 NULL
+ self.assertIn("enabled bit DEFAULT 1 NOT NULL", out)
+ self.assertIn("visible bit DEFAULT NULL NULL", out)
+ self.assertIn("deleted bit DEFAULT 0 NOT NULL", out)
+ self.assertNotIn("varchar(1)", out)
+ # INSERT 保留负数、大于 255 的取值;bit 的 '0'、'1' 由 SQL Server 隐式转换
+ self.assertIn("INSERT INTO demo_type (id, grade, sex, score, ratio, port, enabled, visible, deleted)"
+ " VALUES (1, -128, 1, -32768, 255, 65535, N'0', NULL, N'0')\nGO", out)
+ self.assertIn("INSERT INTO demo_type (id, grade, sex, score, ratio, port, enabled, visible, deleted)"
+ " VALUES (2, 127, 0, 32767, 0, 0, N'1', N'1', N'0')\nGO", out)
+
+ def test_bit_multiple(self):
+ sql = HEADER + """
+CREATE TABLE `demo_flags` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+ `flags` bit(8) NOT NULL COMMENT '位串',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB COMMENT = '位串表';
+"""
+ # 明确失败,不把多位的位串当成布尔值
+ with self.assertRaises(ValueError):
+ convert(SQLServerConvertor(self.write_sql(sql)))
+
+ def test_ruoyi_vue_pro(self):
+ convertor = SQLServerConvertor(os.path.join(MYSQL_DIR, "ruoyi-vue-pro.sql"))
+ source_bits, source_integers = [], []
+ for table_sql in convertor.original_table_script_list:
+ source_bits += re.findall(r"^\s*`(\w+)`\s+bit\b[^\n]*", table_sql, flags=re.MULTILINE)
+ source_integers += re.findall(r"^\s*`\w+`\s+(?:tinyint|smallint)\b[^\n]*", table_sql, flags=re.MULTILINE)
+ self.assertTrue(source_bits)
+ self.assertTrue(source_integers)
+ # 官方脚本只有 bit(1)、有符号的 tinyint / smallint
+ for table_sql in convertor.original_table_script_list:
+ self.assertFalse(re.findall(r"^\s*`\w+`\s+bit\((?!1\))", table_sql, flags=re.MULTILINE))
+ self.assertFalse([line for line in source_integers if "unsigned" in line.lower()])
+
+ out, err = convert(convertor)
+ self.assertNotIn("无法正常解析", err)
+ self.assertNotIn("varchar(1)", out)
+ self.assertEqual(len(source_bits), len(re.findall(r"^ \w+ bit\b", out, flags=re.MULTILINE)))
+ self.assertEqual(len(source_integers), len(re.findall(r"^ \w+ smallint\b", out, flags=re.MULTILINE)))
+ self.assertFalse(re.findall(r"^ \w+ tinyint\b", out, flags=re.MULTILINE))
+
+
class ConvertorOfficialDumpTest(unittest.TestCase):
def test_ruoyi_vue_pro(self):
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
index be0556b..4c685ef 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
@@ -112,6 +112,11 @@
spring-boot-starter-test
test
+
+ org.mockito
+ mockito-inline
+ test
+
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandler.java
new file mode 100644
index 0000000..3204155
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandler.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.framework.mybatis.core.type;
+
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Boolean 的类型转换器实现类,对应数据库的整数类型(tinyint、smallint、int2、number 等)
+ *
+ * 写入时 true 存 1、false 存 0;读取时非 0 为 true、0 为 false、NULL 为 null。
+ * 用于数据库列是整数、而 Java 字段是 Boolean 的场景,避免 PostgreSQL 等数据库不允许 boolean 与整数隐式转换。
+ *
+ * 使用时在字段上配置 {@code @TableField(typeHandler = IntegerBooleanTypeHandler.class)},
+ * 并在实体上开启 {@code @TableName(autoResultMap = true)},使查询结果也使用该转换器。
+ * 自定义 SQL 或 Wrapper 的独立参数需显式指定此转换器。
+ *
+ * 注意:仅按字段使用,
+ * 不要注册为全局的 Boolean 类型转换器,否则会影响真正的 boolean / bit 列。
+ *
+ * @author 芋道源码
+ */
+public class IntegerBooleanTypeHandler extends BaseTypeHandler {
+
+ @Override
+ public void setParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
+ if (parameter == null) {
+ // 未显式指定 jdbcType 时,按整数类型写入 NULL,避免 JdbcType.OTHER 在部分驱动上无法推断类型
+ ps.setNull(i, jdbcType == null || jdbcType == JdbcType.OTHER ? Types.INTEGER : jdbcType.TYPE_CODE);
+ return;
+ }
+ setNonNullParameter(ps, i, parameter, jdbcType);
+ }
+
+ @Override
+ public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
+ ps.setInt(i, parameter ? 1 : 0);
+ }
+
+ @Override
+ public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {
+ int value = rs.getInt(columnName);
+ return rs.wasNull() ? null : value != 0;
+ }
+
+ @Override
+ public Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+ int value = rs.getInt(columnIndex);
+ return rs.wasNull() ? null : value != 0;
+ }
+
+ @Override
+ public Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+ int value = cs.getInt(columnIndex);
+ return cs.wasNull() ? null : value != 0;
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandlerTest.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandlerTest.java
new file mode 100644
index 0000000..8f9dafa
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerBooleanTypeHandlerTest.java
@@ -0,0 +1,108 @@
+package cn.iocoder.yudao.framework.mybatis.core.type;
+
+import org.apache.ibatis.type.JdbcType;
+import org.junit.jupiter.api.Test;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * {@link IntegerBooleanTypeHandler} 的单元测试
+ *
+ * @author 芋道源码
+ */
+public class IntegerBooleanTypeHandlerTest {
+
+ private final IntegerBooleanTypeHandler handler = new IntegerBooleanTypeHandler();
+
+ // ========== 写入 ==========
+
+ @Test
+ public void testSetParameter_true() throws SQLException {
+ PreparedStatement ps = mock(PreparedStatement.class);
+
+ handler.setParameter(ps, 1, true, null);
+
+ verify(ps).setInt(1, 1);
+ verify(ps, never()).setBoolean(anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testSetParameter_false() throws SQLException {
+ PreparedStatement ps = mock(PreparedStatement.class);
+
+ handler.setParameter(ps, 2, false, JdbcType.TINYINT);
+
+ verify(ps).setInt(2, 0);
+ }
+
+ @Test
+ public void testSetParameter_nullWithoutJdbcType() throws SQLException {
+ PreparedStatement ps = mock(PreparedStatement.class);
+
+ // MyBatis 未指定 jdbcType 时,可能传入 null 或 jdbcTypeForNull 默认的 OTHER
+ handler.setParameter(ps, 1, null, null);
+ handler.setParameter(ps, 2, null, JdbcType.OTHER);
+
+ verify(ps).setNull(1, Types.INTEGER);
+ verify(ps).setNull(2, Types.INTEGER);
+ }
+
+ @Test
+ public void testSetParameter_nullWithJdbcType() throws SQLException {
+ PreparedStatement ps = mock(PreparedStatement.class);
+
+ handler.setParameter(ps, 1, null, JdbcType.SMALLINT);
+
+ verify(ps).setNull(1, Types.SMALLINT);
+ }
+
+ // ========== 读取 ==========
+
+ @Test
+ public void testGetResult_byColumnName() throws SQLException {
+ ResultSet rs = mock(ResultSet.class);
+ when(rs.getInt("used")).thenReturn(1, 0, 2, 0);
+ when(rs.wasNull()).thenReturn(false, false, false, true);
+
+ assertEquals(Boolean.TRUE, handler.getResult(rs, "used"));
+ assertEquals(Boolean.FALSE, handler.getResult(rs, "used"));
+ assertEquals(Boolean.TRUE, handler.getResult(rs, "used")); // 非 0 均为 true
+ assertNull(handler.getResult(rs, "used")); // NULL
+ }
+
+ @Test
+ public void testGetResult_byColumnIndex() throws SQLException {
+ ResultSet rs = mock(ResultSet.class);
+ when(rs.getInt(3)).thenReturn(1, 0, 0);
+ when(rs.wasNull()).thenReturn(false, false, true);
+
+ assertEquals(Boolean.TRUE, handler.getResult(rs, 3));
+ assertEquals(Boolean.FALSE, handler.getResult(rs, 3));
+ assertNull(handler.getResult(rs, 3));
+ }
+
+ @Test
+ public void testGetResult_callableStatement() throws SQLException {
+ CallableStatement cs = mock(CallableStatement.class);
+ when(cs.getInt(1)).thenReturn(1, 0, 0);
+ when(cs.wasNull()).thenReturn(false, false, true);
+
+ assertEquals(Boolean.TRUE, handler.getResult(cs, 1));
+ assertEquals(Boolean.FALSE, handler.getResult(cs, 1));
+ assertNull(handler.getResult(cs, 1));
+ }
+
+}
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/slip/HrmSalarySlipTemplateDO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/slip/HrmSalarySlipTemplateDO.java
index b13ed40..b013f81 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/slip/HrmSalarySlipTemplateDO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/dataobject/salary/slip/HrmSalarySlipTemplateDO.java
@@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.hrm.dal.dataobject.salary.slip;
import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.config.HrmSalaryOptionDO;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import cn.iocoder.yudao.module.hrm.enums.salary.slip.HrmSalarySlipTemplateOptionTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
@@ -20,6 +20,8 @@ import java.util.List;
/**
* HRM 工资条模板 DO
*
+ * 平台级默认模板保存在 {@link cn.iocoder.yudao.framework.tenant.core.util.TenantUtils#GLOBAL_TENANT_ID} 下,由所有租户只读共享
+ *
* @author 芋道源码
*/
@TableName(value = "hrm_salary_slip_template", autoResultMap = true)
@@ -30,7 +32,7 @@ import java.util.List;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class HrmSalarySlipTemplateDO extends BaseDO {
+public class HrmSalarySlipTemplateDO extends TenantBaseDO {
/**
* 编号
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/slip/HrmSalarySlipTemplateMapper.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/slip/HrmSalarySlipTemplateMapper.java
index 23e2a35..03687e0 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/slip/HrmSalarySlipTemplateMapper.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/slip/HrmSalarySlipTemplateMapper.java
@@ -26,7 +26,7 @@ public interface HrmSalarySlipTemplateMapper extends BaseMapperX()
- .apply("tenant_id = {0}", TenantUtils.GLOBAL_TENANT_ID)
+ .eq(HrmSalarySlipTemplateDO::getTenantId, TenantUtils.GLOBAL_TENANT_ID)
.eq(HrmSalarySlipTemplateDO::getDefaultStatus, true)
.orderByDesc(HrmSalarySlipTemplateDO::getId));
}
diff --git a/yudao-module-hrm/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipTemplateServiceImplTest.java b/yudao-module-hrm/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipTemplateServiceImplTest.java
index 9da2b15..2f9e581 100644
--- a/yudao-module-hrm/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipTemplateServiceImplTest.java
+++ b/yudao-module-hrm/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipTemplateServiceImplTest.java
@@ -34,6 +34,7 @@ import java.util.Objects;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_DATA_ILLEGAL;
+import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_SLIP_TEMPLATE_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -51,6 +52,7 @@ import static org.mockito.Mockito.when;
public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
private static final Long TENANT_ID = 2L;
+ private static final Long OTHER_TENANT_ID = 3L;
@TestConfiguration(proxyBeanMethods = false)
static class TenantTestConfiguration {
@@ -108,6 +110,8 @@ public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
// 断言
assertNotNull(templateId);
HrmSalarySlipTemplateDO template = salarySlipTemplateService.getSalarySlipTemplate(templateId);
+ // 新增时不传租户编号,由租户拦截器按当前租户填充
+ assertEquals(TENANT_ID, template.getTenantId());
assertEquals("研发工资条", template.getName());
assertFalse(template.getHideEmpty());
assertFalse(template.getDefaultStatus());
@@ -173,6 +177,7 @@ public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
HrmSalarySlipTemplateDO template = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
o.setId(null).setName("默认工资条模板").setHideEmpty(false).setDefaultStatus(true);
o.setOptions(Collections.emptyList());
+ o.setTenantId(TENANT_ID);
});
salarySlipTemplateMapper.insert(template);
@@ -258,6 +263,7 @@ public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
HrmSalarySlipTemplateDO defaultTemplate = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
o.setId(null).setName("默认工资条模板").setHideEmpty(false).setDefaultStatus(true);
o.setOptions(Collections.emptyList());
+ o.setTenantId(TENANT_ID);
});
salarySlipTemplateMapper.insert(defaultTemplate);
when(salaryOptionService.getSalaryOptionList(false)).thenReturn(Arrays.asList(
@@ -286,11 +292,13 @@ public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
HrmSalarySlipTemplateDO globalDefaultTemplate = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
o.setId(null).setName("平台默认工资条模板").setHideEmpty(false).setDefaultStatus(true);
o.setOptions(Collections.emptyList());
+ o.setTenantId(TenantUtils.GLOBAL_TENANT_ID);
});
TenantUtils.executeIgnore(() -> salarySlipTemplateMapper.insert(globalDefaultTemplate));
HrmSalarySlipTemplateDO tenantTemplate = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
o.setId(null).setName("租户自定义工资条模板").setHideEmpty(false).setDefaultStatus(false);
o.setOptions(Collections.emptyList());
+ o.setTenantId(TENANT_ID);
});
salarySlipTemplateMapper.insert(tenantTemplate);
when(salaryOptionService.getSalaryOptionList(false)).thenReturn(Collections.emptyList());
@@ -301,13 +309,73 @@ public class HrmSalarySlipTemplateServiceImplTest extends BaseDbUnitTest {
// 断言:普通查询被租户隔离,但 Service 可只读回退平台默认模板
assertNull(salarySlipTemplateMapper.selectById(globalDefaultTemplate.getId()));
- assertEquals(globalDefaultTemplate.getId(),
- TenantUtils.executeIgnore(salarySlipTemplateMapper::selectGlobalDefaultTemplate).getId());
+ HrmSalarySlipTemplateDO dbGlobalDefaultTemplate =
+ TenantUtils.executeIgnore(salarySlipTemplateMapper::selectGlobalDefaultTemplate);
+ assertEquals(globalDefaultTemplate.getId(), dbGlobalDefaultTemplate.getId());
+ assertEquals(TenantUtils.GLOBAL_TENANT_ID, dbGlobalDefaultTemplate.getTenantId());
assertEquals(globalDefaultTemplate.getId(), salarySlipTemplateService
.getSalarySlipTemplate(globalDefaultTemplate.getId()).getId());
assertEquals(2, templates.size());
assertEquals(globalDefaultTemplate.getId(), templates.get(0).getId());
assertEquals(tenantTemplate.getId(), templates.get(1).getId());
+ assertEquals(TENANT_ID, templates.get(1).getTenantId());
+
+ // 调用,并断言:平台默认模板只读,租户不能修改、删除
+ HrmSalarySlipTemplateSaveReqVO updateReqVO = randomPojo(HrmSalarySlipTemplateSaveReqVO.class, o -> {
+ o.setId(globalDefaultTemplate.getId());
+ o.setName("租户改写的默认模板");
+ o.setOptions(Collections.singletonList(createTemplateOption("基本工资", 10101, 1)));
+ });
+ assertServiceException(() -> salarySlipTemplateService.updateSalarySlipTemplate(updateReqVO),
+ SALARY_DATA_ILLEGAL);
+ assertServiceException(() -> salarySlipTemplateService.deleteSalarySlipTemplate(globalDefaultTemplate.getId()),
+ SALARY_DATA_ILLEGAL);
+ HrmSalarySlipTemplateDO dbTemplate = TenantUtils.executeIgnore(
+ () -> salarySlipTemplateMapper.selectById(globalDefaultTemplate.getId()));
+ assertEquals("平台默认工资条模板", dbTemplate.getName());
+ assertEquals(TenantUtils.GLOBAL_TENANT_ID, dbTemplate.getTenantId());
+ }
+
+ @Test
+ public void testSalarySlipTemplate_otherTenantIsolated() {
+ // mock 数据:其它租户的自定义模板、默认模板,按其它租户的上下文新增
+ HrmSalarySlipTemplateDO otherTemplate = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
+ o.setId(null).setName("其它租户工资条模板").setHideEmpty(false).setDefaultStatus(false);
+ o.setOptions(Collections.emptyList());
+ o.setTenantId(null);
+ });
+ HrmSalarySlipTemplateDO otherDefaultTemplate = randomPojo(HrmSalarySlipTemplateDO.class, o -> {
+ o.setId(null).setName("其它租户默认工资条模板").setHideEmpty(false).setDefaultStatus(true);
+ o.setOptions(Collections.emptyList());
+ o.setTenantId(null);
+ });
+ TenantUtils.execute(OTHER_TENANT_ID, () -> salarySlipTemplateMapper.insert(otherTemplate));
+ TenantUtils.execute(OTHER_TENANT_ID, () -> salarySlipTemplateMapper.insert(otherDefaultTemplate));
+ when(salaryOptionService.getSalaryOptionList(false)).thenReturn(Collections.emptyList());
+
+ // 调用,并断言:当前租户读不到,也不会把其它租户的默认模板当作平台默认模板
+ assertNull(salarySlipTemplateMapper.selectById(otherTemplate.getId()));
+ assertNull(salarySlipTemplateService.getSalarySlipTemplate(otherTemplate.getId()));
+ assertNull(salarySlipTemplateService.getSalarySlipTemplate(otherDefaultTemplate.getId()));
+ assertNull(TenantUtils.executeIgnore(salarySlipTemplateMapper::selectGlobalDefaultTemplate));
+ assertTrue(salarySlipTemplateService.getSalarySlipTemplateList().isEmpty());
+
+ // 调用,并断言:当前租户不能修改、删除
+ HrmSalarySlipTemplateSaveReqVO updateReqVO = randomPojo(HrmSalarySlipTemplateSaveReqVO.class, o -> {
+ o.setId(otherTemplate.getId());
+ o.setName("当前租户改写的模板");
+ o.setOptions(Collections.singletonList(createTemplateOption("基本工资", 10101, 1)));
+ });
+ assertServiceException(() -> salarySlipTemplateService.updateSalarySlipTemplate(updateReqVO),
+ SALARY_SLIP_TEMPLATE_NOT_EXISTS);
+ assertServiceException(() -> salarySlipTemplateService.deleteSalarySlipTemplate(otherTemplate.getId()),
+ SALARY_SLIP_TEMPLATE_NOT_EXISTS);
+
+ // 断言:其它租户的数据不变
+ HrmSalarySlipTemplateDO dbTemplate = TenantUtils.executeIgnore(
+ () -> salarySlipTemplateMapper.selectById(otherTemplate.getId()));
+ assertEquals("其它租户工资条模板", dbTemplate.getName());
+ assertEquals(OTHER_TENANT_ID, dbTemplate.getTenantId());
}
@Test
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java
index 63c5481..e6b877e 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java
@@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.mybatis.core.type.IntegerBooleanTypeHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@@ -15,7 +17,7 @@ import java.time.LocalDateTime;
*
* @author 芋道源码
*/
-@TableName("system_sms_code")
+@TableName(value = "system_sms_code", autoResultMap = true)
@KeySequence("system_sms_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@@ -54,6 +56,7 @@ public class SmsCodeDO extends BaseDO {
/**
* 是否使用
*/
+ @TableField(typeHandler = IntegerBooleanTypeHandler.class)
private Boolean used;
/**
* 使用时间
diff --git a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java
index b492f12..8dbe592 100644
--- a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java
+++ b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java
@@ -77,7 +77,7 @@ public class SmsCodeServiceImplTest extends BaseDbUnitTest {
public void sendSmsCode_tooFast() {
// mock 数据
SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
- o -> o.setMobile("15601691300").setTodayIndex(1));
+ o -> o.setMobile("15601691300").setTodayIndex(1).setUsed(false));
smsCodeMapper.insert(smsCodeDO);
// 准备参数
SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
@@ -94,7 +94,7 @@ public class SmsCodeServiceImplTest extends BaseDbUnitTest {
public void sendSmsCode_exceedDay() {
// mock 数据
SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
- o -> o.setMobile("15601691300").setTodayIndex(10).setCreateTime(LocalDateTime.now()));
+ o -> o.setMobile("15601691300").setTodayIndex(10).setUsed(false).setCreateTime(LocalDateTime.now()));
smsCodeMapper.insert(smsCodeDO);
// 准备参数
SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
diff --git a/yudao-module-system/src/test/resources/sql/create_tables.sql b/yudao-module-system/src/test/resources/sql/create_tables.sql
index 9970065..8fe671b 100644
--- a/yudao-module-system/src/test/resources/sql/create_tables.sql
+++ b/yudao-module-system/src/test/resources/sql/create_tables.sql
@@ -321,7 +321,7 @@ CREATE TABLE IF NOT EXISTS "system_sms_code" (
"scene" bigint NOT NULL,
"create_ip" varchar NOT NULL,
"today_index" int NOT NULL,
- "used" bit NOT NULL DEFAULT FALSE,
+ "used" tinyint NOT NULL DEFAULT 0,
"used_time" timestamp DEFAULT NULL,
"used_ip" varchar NULL,
"creator" varchar(64) DEFAULT '',