From 3a3a41f9cf1b34477756c8e0b240f3e444af2c46 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Fri, 20 Feb 2026 15:49:44 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E5=89=A5=E7=A6=BB=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E4=B8=8E=E6=9D=83=E9=99=90=E4=BB=A3=E7=A0=81=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SystemManagement/Role/RoleController.cs | 10 + .../Extensions/PermissionSyncExtensions.cs | 7 +- .../GrantRolePermissionsInputDto.cs | 4 +- .../Dto/Permission/ReadRoleGrantOutputDto.cs | 14 + .../Permission/UserRolePermissionOutputDto.cs | 4 +- .../DatabaseInitializer.cs | 135 ++++++- .../SystemManagement/RolePermission.cs | 19 +- .../EntityBuilder.cs | 343 +++++++++--------- .../Permission/CustomerPermissionService.cs | 63 +++- .../Permission/EmployeePermissionService.cs | 63 +++- .../Administrator/AdminService.cs | 68 +++- .../SystemManagement/Menu/MenuService.cs | 214 ++++++----- .../SystemManagement/Role/IRoleAppService.cs | 7 + .../SystemManagement/Role/RoleAppService.cs | 145 +++++++- 14 files changed, 772 insertions(+), 324 deletions(-) create mode 100644 EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/ReadRoleGrantOutputDto.cs diff --git a/EOM.TSHotelManagement.API/Controllers/SystemManagement/Role/RoleController.cs b/EOM.TSHotelManagement.API/Controllers/SystemManagement/Role/RoleController.cs index 04c9eeb..7657333 100644 --- a/EOM.TSHotelManagement.API/Controllers/SystemManagement/Role/RoleController.cs +++ b/EOM.TSHotelManagement.API/Controllers/SystemManagement/Role/RoleController.cs @@ -87,6 +87,16 @@ namespace EOM.TSHotelManagement.WebApi.Controllers return _roleAppService.ReadRolePermissions(input.RoleNumber); } + /// + /// 读取指定角色菜单和权限授权(菜单与权限独立) + /// + [RequirePermission("system:role:rrg")] + [HttpPost] + public SingleOutputDto ReadRoleGrants([FromBody] ReadByRoleNumberInputDto input) + { + return _roleAppService.ReadRoleGrants(input.RoleNumber); + } + /// /// 读取隶属于指定角色的管理员用户编码集合 /// diff --git a/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs b/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs index 53b4718..fc19b52 100644 --- a/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs @@ -104,7 +104,10 @@ namespace EOM.TSHotelManagement.WebApi // 默认将所有扫描到的权限与超级管理员角色关联 // 如角色不存在,DatabaseInitializer 已负责创建;此处仅做映射补齐 var existingRolePerms = db.Queryable() - .Where(rp => rp.RoleNumber == AdminRoleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == AdminRoleNumber + && rp.IsDelete != 1 + && rp.PermissionNumber != null + && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) .ToList(); @@ -161,4 +164,4 @@ namespace EOM.TSHotelManagement.WebApi return "api"; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/GrantRolePermissionsInputDto.cs b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/GrantRolePermissionsInputDto.cs index f593d5a..769edea 100644 --- a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/GrantRolePermissionsInputDto.cs +++ b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/GrantRolePermissionsInputDto.cs @@ -10,5 +10,7 @@ namespace EOM.TSHotelManagement.Contract.SystemManagement.Dto.Permission [Required(ErrorMessage = "权限编码集合为必填字段")] public List PermissionNumbers { get; set; } = new List(); + + public List MenuIds { get; set; } = new List(); } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/ReadRoleGrantOutputDto.cs b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/ReadRoleGrantOutputDto.cs new file mode 100644 index 0000000..7f5e87b --- /dev/null +++ b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/ReadRoleGrantOutputDto.cs @@ -0,0 +1,14 @@ +namespace EOM.TSHotelManagement.Contract.SystemManagement.Dto.Permission +{ + /// + /// 角色授权读取结果(菜单与权限独立) + /// + public class ReadRoleGrantOutputDto : BaseOutputDto + { + public string RoleNumber { get; set; } = string.Empty; + + public List PermissionNumbers { get; set; } = new(); + + public List MenuIds { get; set; } = new(); + } +} diff --git a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/UserRolePermissionOutputDto.cs b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/UserRolePermissionOutputDto.cs index 2e22503..59830c4 100644 --- a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/UserRolePermissionOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/UserRolePermissionOutputDto.cs @@ -16,7 +16,9 @@ namespace EOM.TSHotelManagement.Contract [MaxLength(256, ErrorMessage = "菜单键长度不超过256字符")] public string? MenuKey { get; set; } + public int? MenuId { get; set; } + [MaxLength(256, ErrorMessage = "菜单名称长度不超过256字符")] public string? MenuName { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index e86d9cf..c5e00af 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -103,6 +103,7 @@ namespace EOM.TSHotelManagement.Data db.CodeFirst.InitTables(needCreateTableTypes); EnsureTwoFactorForeignKeys(db, dbSettings.DbType); + EnsureRolePermissionSchema(db, dbSettings.DbType); Console.WriteLine("Database schema initialized"); @@ -277,6 +278,112 @@ namespace EOM.TSHotelManagement.Data } } + private void EnsureRolePermissionSchema(ISqlSugarClient db, DbType dbType) + { + try + { + if (dbType is DbType.MySql or DbType.MySqlConnector) + { + EnsureMySqlRolePermissionColumnsAndKeys(db); + BackfillRolePermissionMenuIdsFromLegacyData(db); + } + } + catch (Exception ex) + { + Console.WriteLine($"EnsureRolePermissionSchema skipped: {ex.Message}"); + } + } + + private static void EnsureMySqlRolePermissionColumnsAndKeys(ISqlSugarClient db) + { + var tableExists = db.Ado.GetInt( + @"SELECT COUNT(1) + FROM information_schema.TABLES + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'role_permission'") > 0; + if (!tableExists) + { + return; + } + + var hasMenuId = db.Ado.GetInt( + @"SELECT COUNT(1) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'role_permission' + AND COLUMN_NAME = 'menu_id'") > 0; + if (!hasMenuId) + { + db.Ado.ExecuteCommand( + "ALTER TABLE `role_permission` ADD COLUMN `menu_id` int NULL COMMENT '关联菜单主键 (Linked Menu Id)'"); + } + + var permissionNullable = string.Equals( + db.Ado.GetString( + @"SELECT IS_NULLABLE + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'role_permission' + AND COLUMN_NAME = 'permission_number' + LIMIT 1"), + "YES", + StringComparison.OrdinalIgnoreCase); + if (!permissionNullable) + { + db.Ado.ExecuteCommand( + "ALTER TABLE `role_permission` MODIFY COLUMN `permission_number` varchar(128) NULL COMMENT '关联权限编码 (Linked Permission Code)'"); + } + + var pkColumns = db.Ado.SqlQuery( + @"SELECT COLUMN_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'role_permission' + AND CONSTRAINT_NAME = 'PRIMARY' + ORDER BY ORDINAL_POSITION"); + + var needResetPrimaryKey = pkColumns.Count != 1 + || !string.Equals(pkColumns[0], "id", StringComparison.OrdinalIgnoreCase); + if (needResetPrimaryKey) + { + if (pkColumns.Count > 0) + { + db.Ado.ExecuteCommand("ALTER TABLE `role_permission` DROP PRIMARY KEY"); + } + db.Ado.ExecuteCommand("ALTER TABLE `role_permission` ADD PRIMARY KEY (`id`)"); + } + + EnsureMySqlIndex(db, "role_permission", "Index_role_permission_role_number", "`role_number`"); + EnsureMySqlIndex(db, "role_permission", "Index_role_permission_permission_number", "`permission_number`"); + EnsureMySqlIndex(db, "role_permission", "Index_role_permission_menu_id", "`menu_id`"); + } + + private static void BackfillRolePermissionMenuIdsFromLegacyData(ISqlSugarClient db) + { + var hasPermissionMenuKey = db.Ado.GetInt( + @"SELECT COUNT(1) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'permission' + AND COLUMN_NAME = 'menu_key'") > 0; + if (!hasPermissionMenuKey) + { + return; + } + + var sql = @" +UPDATE `role_permission` rp +INNER JOIN `permission` p ON p.`permission_number` = rp.`permission_number` AND IFNULL(p.`delete_mk`, 0) <> 1 +INNER JOIN `menu` m ON m.`key` = p.`menu_key` AND IFNULL(m.`delete_mk`, 0) <> 1 +SET rp.`menu_id` = m.`id` +WHERE rp.`menu_id` IS NULL + AND rp.`permission_number` IS NOT NULL + AND p.`menu_key` IS NOT NULL + AND p.`menu_key` <> '';"; + + db.Ado.ExecuteCommand(sql); + } + private static void EnsureMySqlForeignKey( ISqlSugarClient db, string tableName, @@ -311,6 +418,28 @@ namespace EOM.TSHotelManagement.Data db.Ado.ExecuteCommand(addConstraintSql); } + private static void EnsureMySqlIndex( + ISqlSugarClient db, + string tableName, + string indexName, + string columnExpression) + { + var exists = db.Ado.GetInt( + @"SELECT COUNT(1) + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = @tableName + AND INDEX_NAME = @indexName", + new SugarParameter("@tableName", tableName), + new SugarParameter("@indexName", indexName)) > 0; + if (exists) + { + return; + } + + db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` ADD INDEX `{indexName}` ({columnExpression})"); + } + private void SeedInitialData(ISqlSugarClient db) { Console.WriteLine("Initializing database data..."); @@ -538,7 +667,10 @@ namespace EOM.TSHotelManagement.Data .ToList(); var existingRolePerms = db.Queryable() - .Where(rp => rp.RoleNumber == adminRoleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == adminRoleNumber + && rp.IsDelete != 1 + && rp.PermissionNumber != null + && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) .ToList(); @@ -650,4 +782,3 @@ namespace EOM.TSHotelManagement.Data #endregion } } - diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs b/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs index b2737df..3c0b45c 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs @@ -18,7 +18,6 @@ namespace EOM.TSHotelManagement.Domain /// [SugarColumn( ColumnName = "role_number", - IsPrimaryKey = true, ColumnDescription = "关联角色编码 (Linked Role Code)", IsNullable = false, Length = 128, @@ -31,13 +30,23 @@ namespace EOM.TSHotelManagement.Domain /// [SugarColumn( ColumnName = "permission_number", - IsPrimaryKey = true, ColumnDescription = "关联权限编码 (Linked Permission Code)", - IsNullable = false, + IsNullable = true, Length = 128, IndexGroupNameList = new[] { "IX_permission_number" } )] - public string PermissionNumber { get; set; } = null!; + public string? PermissionNumber { get; set; } + + /// + /// 菜单主键(关联菜单表) (Menu Id) + /// + [SugarColumn( + ColumnName = "menu_id", + ColumnDescription = "关联菜单主键 (Linked Menu Id)", + IsNullable = true, + IndexGroupNameList = new[] { "IX_menu_id" } + )] + public int? MenuId { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 97c460d..3ef761a 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -666,230 +666,243 @@ namespace EOM.TSHotelManagement.Migration , // ===== Permission seeds synced from controller [RequirePermission] ===== - // 客户信息 - new Permission { PermissionNumber = "customer.dci", PermissionName = "删除客户信息", Module = "customer", Description = "删除客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.ici", PermissionName = "添加客户信息", Module = "customer", Description = "添加客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.scbi", PermissionName = "查询指定客户信息", Module = "customer", Description = "查询指定客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.scs", PermissionName = "查询所有客户信息", Module = "customer", Description = "查询所有客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.uci", PermissionName = "更新客户信息", Module = "customer", Description = "更新客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.uctbcn", PermissionName = "更新会员等级", Module = "customer", Description = "更新会员等级", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - - // 客户消费信息 - new Permission { PermissionNumber = "customerspend.acs", PermissionName = "添加客户消费信息", Module = "customerspend", Description = "添加客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ssbrn", PermissionName = "查询房间消费信息", Module = "customerspend", Description = "查询房间消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ssia", PermissionName = "查询所有消费信息", Module = "customerspend", Description = "查询所有消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.shsia", PermissionName = "查询客户历史消费信息", Module = "customerspend", Description = "查询客户历史消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.sca", PermissionName = "查询消费总金额", Module = "customerspend", Description = "查询消费总金额", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ucs", PermissionName = "撤回客户消费信息", Module = "customerspend", Description = "撤回客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.usi", PermissionName = "更新消费信息", Module = "customerspend", Description = "更新消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - - // 客户类型 - new Permission { PermissionNumber = "customertype.create", PermissionName = "新增客户类型", Module = "customertype", Description = "基础信息-客户类型-新增", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.delete", PermissionName = "删除客户类型", Module = "customertype", Description = "基础信息-客户类型-删除", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.update", PermissionName = "更新客户类型", Module = "customertype", Description = "基础信息-客户类型-更新", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.view", PermissionName = "查询客户类型列表", Module = "customertype", Description = "基础信息-客户类型-查询列表", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + // Basic (基础信息管理) // 部门 - new Permission { PermissionNumber = "department.create", PermissionName = "新增部门", Module = "department", Description = "基础信息-部门-新增", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.delete", PermissionName = "删除部门", Module = "department", Description = "基础信息-部门-删除", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.update", PermissionName = "更新部门", Module = "department", Description = "基础信息-部门-更新", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.view", PermissionName = "查询部门列表", Module = "department", Description = "基础信息-部门-查询列表", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.create", PermissionName = "新增部门", Module = "basic", Description = "基础信息-部门-新增", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.delete", PermissionName = "删除部门", Module = "basic", Description = "基础信息-部门-删除", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.update", PermissionName = "更新部门", Module = "basic", Description = "基础信息-部门-更新", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.view", PermissionName = "查询部门列表", Module = "basic", Description = "基础信息-部门-查询列表", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 民族 - new Permission { PermissionNumber = "nation.create", PermissionName = "新增民族", Module = "nation", Description = "基础信息-民族-新增", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.delete", PermissionName = "删除民族", Module = "nation", Description = "基础信息-民族-删除", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.update", PermissionName = "更新民族", Module = "nation", Description = "基础信息-民族-更新", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.view", PermissionName = "查询民族列表", Module = "nation", Description = "基础信息-民族-查询列表", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.create", PermissionName = "新增民族", Module = "basic", Description = "基础信息-民族-新增", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.delete", PermissionName = "删除民族", Module = "basic", Description = "基础信息-民族-删除", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.update", PermissionName = "更新民族", Module = "basic", Description = "基础信息-民族-更新", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.view", PermissionName = "查询民族列表", Module = "basic", Description = "基础信息-民族-查询列表", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 证件类型 - new Permission { PermissionNumber = "passport.create", PermissionName = "新增证件类型", Module = "passport", Description = "基础信息-证件类型-新增", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.delete", PermissionName = "删除证件类型", Module = "passport", Description = "基础信息-证件类型-删除", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.update", PermissionName = "更新证件类型", Module = "passport", Description = "基础信息-证件类型-更新", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.view", PermissionName = "查询证件类型列表", Module = "passport", Description = "基础信息-证件类型-查询列表", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.create", PermissionName = "新增证件类型", Module = "basic", Description = "基础信息-证件类型-新增", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.delete", PermissionName = "删除证件类型", Module = "basic", Description = "基础信息-证件类型-删除", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.update", PermissionName = "更新证件类型", Module = "basic", Description = "基础信息-证件类型-更新", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.view", PermissionName = "查询证件类型列表", Module = "basic", Description = "基础信息-证件类型-查询列表", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 职位 - new Permission { PermissionNumber = "position.create", PermissionName = "新增职位", Module = "position", Description = "基础信息-职位-新增", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.delete", PermissionName = "删除职位", Module = "position", Description = "基础信息-职位-删除", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.update", PermissionName = "更新职位", Module = "position", Description = "基础信息-职位-更新", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.view", PermissionName = "查询职位列表", Module = "position", Description = "基础信息-职位-查询列表", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.create", PermissionName = "新增职位", Module = "basic", Description = "基础信息-职位-新增", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.delete", PermissionName = "删除职位", Module = "basic", Description = "基础信息-职位-删除", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.update", PermissionName = "更新职位", Module = "basic", Description = "基础信息-职位-更新", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.view", PermissionName = "查询职位列表", Module = "basic", Description = "基础信息-职位-查询列表", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 学历 - new Permission { PermissionNumber = "qualification.create", PermissionName = "新增学历", Module = "qualification", Description = "基础信息-学历-新增", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.delete", PermissionName = "删除学历", Module = "qualification", Description = "基础信息-学历-删除", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.update", PermissionName = "更新学历", Module = "qualification", Description = "基础信息-学历-更新", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.view", PermissionName = "查询学历列表", Module = "qualification", Description = "基础信息-学历-查询列表", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.create", PermissionName = "新增学历", Module = "basic", Description = "基础信息-学历-新增", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.delete", PermissionName = "删除学历", Module = "basic", Description = "基础信息-学历-删除", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.update", PermissionName = "更新学历", Module = "basic", Description = "基础信息-学历-更新", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.view", PermissionName = "查询学历列表", Module = "basic", Description = "基础信息-学历-查询列表", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 会员等级规则管理 - new Permission { PermissionNumber = "viplevel.addviprule", PermissionName = "添加会员等级规则", Module = "viplevel", Description = "添加会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.delviprule", PermissionName = "删除会员等级规则", Module = "viplevel", Description = "删除会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.svr", PermissionName = "查询会员等级规则", Module = "viplevel", Description = "查询会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.svrlist", PermissionName = "查询会员等级规则列表", Module = "viplevel", Description = "查询会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.updviprule", PermissionName = "更新会员等级规则", Module = "viplevel", Description = "更新会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - - // 仪表盘 - new Permission { PermissionNumber = "dashboard.bs", PermissionName = "获取业务统计信息", Module = "dashboard", Description = "获取业务统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.hrs", PermissionName = "获取人事统计信息", Module = "dashboard", Description = "获取人事统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.ls", PermissionName = "获取后勤统计信息", Module = "dashboard", Description = "获取后勤统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.rs", PermissionName = "获取房间统计信息", Module = "dashboard", Description = "获取房间统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - - // 商品管理 - new Permission { PermissionNumber = "goodsmanagement.dst", PermissionName = "删除商品信息", Module = "goodsmanagement", Description = "删除商品信息", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ist", PermissionName = "添加商品", Module = "goodsmanagement", Description = "添加商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ssta", PermissionName = "查询所有商品", Module = "goodsmanagement", Description = "查询所有商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.sstbnap", PermissionName = "根据商品名称和价格查询商品编号", Module = "goodsmanagement", Description = "根据商品名称和价格查询商品编号", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ust", PermissionName = "修改商品", Module = "goodsmanagement", Description = "修改商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - - // 水电费信息管理 - new Permission { PermissionNumber = "hydroelectricinformation.demi", PermissionName = "删除水电费信息", Module = "hydroelectricinformation", Description = "删除水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.iemi", PermissionName = "添加水电费信息", Module = "hydroelectricinformation", Description = "添加水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.semi", PermissionName = "查询水电费信息", Module = "hydroelectricinformation", Description = "查询水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.uemi", PermissionName = "修改水电费信息", Module = "hydroelectricinformation", Description = "修改水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 公告类型 + new Permission { PermissionNumber = "noticetype.create", PermissionName = "添加公告类型", Module = "basic", Description = "添加公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.delete", PermissionName = "删除公告类型", Module = "basic", Description = "删除公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.update", PermissionName = "更新公告类型", Module = "basic", Description = "更新公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.view", PermissionName = "查询所有公告类型", Module = "basic", Description = "查询所有公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // 宣传联动内容 + new Permission { PermissionNumber = "promotioncontent.apc", PermissionName = "添加宣传联动内容", Module = "basic", Description = "添加宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.dpc", PermissionName = "删除宣传联动内容", Module = "basic", Description = "删除宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.spca", PermissionName = "查询所有宣传联动内容", Module = "basic", Description = "查询所有宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.spcs", PermissionName = "查询所有宣传联动内容(跑马灯)", Module = "basic", Description = "查询所有宣传联动内容(跑马灯)", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.upc", PermissionName = "更新宣传联动内容", Module = "basic", Description = "更新宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // Finance (财务信息管理) // 资产信息管理 new Permission { PermissionNumber = "internalfinance.aai", PermissionName = "添加资产信息", Module = "internalfinance", Description = "添加资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.dai", PermissionName = "删除资产信息", Module = "internalfinance", Description = "删除资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.saia", PermissionName = "查询资产信息", Module = "internalfinance", Description = "查询资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.uai", PermissionName = "更新资产信息", Module = "internalfinance", Description = "更新资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 菜单管理 - new Permission { PermissionNumber = "menumanagement.bma", PermissionName = "构建菜单树", Module = "menumanagement", Description = "构建菜单树", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.deletemenu", PermissionName = "删除菜单", Module = "menumanagement", Description = "删除菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.insertmenu", PermissionName = "插入菜单", Module = "menumanagement", Description = "插入菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.sma", PermissionName = "查询所有菜单信息", Module = "menumanagement", Description = "查询所有菜单信息", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.updatemenu", PermissionName = "更新菜单", Module = "menumanagement", Description = "更新菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + // Nav Bar (导航栏管理) // 导航控件管理 - new Permission { PermissionNumber = "navbar.addnavbar", PermissionName = "添加导航控件", Module = "navbar", Description = "添加导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.dn", PermissionName = "删除导航控件", Module = "navbar", Description = "删除导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.navbarlist", PermissionName = "导航控件列表", Module = "navbar", Description = "导航控件列表", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.un", PermissionName = "更新导航控件", Module = "navbar", Description = "更新导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.addnavbar", PermissionName = "添加导航控件", Module = "client", Description = "添加导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.dn", PermissionName = "删除导航控件", Module = "client", Description = "删除导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.navbarlist", PermissionName = "导航控件列表", Module = "client", Description = "导航控件列表", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.un", PermissionName = "更新导航控件", Module = "client", Description = "更新导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 公告类型 - new Permission { PermissionNumber = "noticetype.create", PermissionName = "添加公告类型", Module = "noticetype", Description = "添加公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.delete", PermissionName = "删除公告类型", Module = "noticetype", Description = "删除公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.update", PermissionName = "更新公告类型", Module = "noticetype", Description = "更新公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.view", PermissionName = "查询所有公告类型", Module = "noticetype", Description = "查询所有公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 操作日志 - new Permission { PermissionNumber = "operationlog.delete", PermissionName = "删除时间范围的操作日志", Module = "operationlog", Description = "删除时间范围的操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "operationlog.view", PermissionName = "查询所有操作日志", Module = "operationlog", Description = "查询所有操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // Hydroelectricity (水电信息管理) + // 水电费信息管理 + new Permission { PermissionNumber = "hydroelectricinformation.demi", PermissionName = "删除水电费信息", Module = "hydroelectricity", Description = "删除水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.iemi", PermissionName = "添加水电费信息", Module = "hydroelectricity", Description = "添加水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.semi", PermissionName = "查询水电费信息", Module = "hydroelectricity", Description = "查询水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.uemi", PermissionName = "修改水电费信息", Module = "hydroelectricity", Description = "修改水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 宣传联动内容 - new Permission { PermissionNumber = "promotioncontent.apc", PermissionName = "添加宣传联动内容", Module = "promotioncontent", Description = "添加宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.dpc", PermissionName = "删除宣传联动内容", Module = "promotioncontent", Description = "删除宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.spca", PermissionName = "查询所有宣传联动内容", Module = "promotioncontent", Description = "查询所有宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.spcs", PermissionName = "查询所有宣传联动内容(跑马灯)", Module = "promotioncontent", Description = "查询所有宣传联动内容(跑马灯)", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.upc", PermissionName = "更新宣传联动内容", Module = "promotioncontent", Description = "更新宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 请求日志 - new Permission { PermissionNumber = "requestlog.delete", PermissionName = "删除时间范围的请求日志", Module = "requestlog", Description = "删除时间范围的请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "requestlog.view", PermissionName = "查询所有请求日志", Module = "requestlog", Description = "查询所有请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // Supervision (监管统计管理) + // 监管统计信息管理 + new Permission { PermissionNumber = "supervisioninfo.dss", PermissionName = "删除监管统计信息", Module = "supervision", Description = "删除监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.iss", PermissionName = "插入监管统计信息", Module = "supervision", Description = "插入监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.sssa", PermissionName = "查询所有监管统计信息", Module = "supervision", Description = "查询所有监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.uss", PermissionName = "更新监管统计信息", Module = "supervision", Description = "更新监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // Room information (客房信息管理) + // 房间管理 + new Permission { PermissionNumber = "roommap.view", PermissionName = "房态图-查看", Module = "room", Description = "房态图一览-查看", MenuKey = "roommap", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.crbr", PermissionName = "根据预约信息办理入住", Module = "room", Description = "根据预约信息办理入住", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.cr", PermissionName = "退房操作", Module = "room", Description = "退房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.dbrn", PermissionName = "根据房间编号查询截止到今天住了多少天", Module = "room", Description = "根据房间编号查询截止到今天住了多少天", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.deleteroom", PermissionName = "删除房间", Module = "room", Description = "删除房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.insertroom", PermissionName = "添加房间", Module = "room", Description = "添加房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.scura", PermissionName = "根据房间状态来查询可使用的房间", Module = "room", Description = "根据房间状态来查询可使用的房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.scurabrs", PermissionName = "查询可入住房间数量", Module = "room", Description = "查询可入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sfrabrs", PermissionName = "查询维修房数量", Module = "room", Description = "查询维修房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sncrabrs", PermissionName = "查询脏房数量", Module = "room", Description = "查询脏房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.snurabrs", PermissionName = "查询已入住房间数量", Module = "room", Description = "查询已入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srrabrs", PermissionName = "查询预约房数量", Module = "room", Description = "查询预约房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sra", PermissionName = "获取所有房间信息", Module = "room", Description = "获取所有房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrn", PermissionName = "根据房间编号查询房间信息", Module = "room", Description = "根据房间编号查询房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrp", PermissionName = "根据房间编号查询房间价格", Module = "room", Description = "根据房间编号查询房间价格", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrs", PermissionName = "根据房间状态获取相应状态的房间信息", Module = "room", Description = "根据房间状态获取相应状态的房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbtn", PermissionName = "获取房间分区的信息", Module = "room", Description = "获取房间分区的信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.tr", PermissionName = "转房操作", Module = "room", Description = "转房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.updateroom", PermissionName = "更新房间", Module = "room", Description = "更新房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.uri", PermissionName = "根据房间编号修改房间信息(入住)", Module = "room", Description = "根据房间编号修改房间信息(入住)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.uriwr", PermissionName = "根据房间编号修改房间信息(预约)", Module = "room", Description = "根据房间编号修改房间信息(预约)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.ursbrn", PermissionName = "根据房间编号更改房间状态", Module = "room", Description = "根据房间编号更改房间状态", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 房间配置管理 + new Permission { PermissionNumber = "roomconfig.drt", PermissionName = "删除房间配置", Module = "room", Description = "删除房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.irt", PermissionName = "添加房间配置", Module = "room", Description = "添加房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.srtbrn", PermissionName = "根据房间编号查询房间类型名称", Module = "room", Description = "根据房间编号查询房间类型名称", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.srta", PermissionName = "获取所有房间类型", Module = "room", Description = "获取所有房间类型", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.urt", PermissionName = "更新房间配置", Module = "room", Description = "更新房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 预约信息管理 - new Permission { PermissionNumber = "resermanagement.dri", PermissionName = "删除预约信息", Module = "resermanagement", Description = "删除预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.iri", PermissionName = "添加预约信息", Module = "resermanagement", Description = "添加预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.sra", PermissionName = "获取所有预约信息", Module = "resermanagement", Description = "获取所有预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.sribrn", PermissionName = "根据房间编号获取预约信息", Module = "resermanagement", Description = "根据房间编号获取预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.srta", PermissionName = "查询所有预约类型", Module = "resermanagement", Description = "查询所有预约类型", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.uri", PermissionName = "更新预约信息", Module = "resermanagement", Description = "更新预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.dri", PermissionName = "删除预约信息", Module = "room", Description = "删除预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.iri", PermissionName = "添加预约信息", Module = "room", Description = "添加预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.sra", PermissionName = "获取所有预约信息", Module = "room", Description = "获取所有预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.sribrn", PermissionName = "根据房间编号获取预约信息", Module = "room", Description = "根据房间编号获取预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.srta", PermissionName = "查询所有预约类型", Module = "room", Description = "查询所有预约类型", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.uri", PermissionName = "更新预约信息", Module = "room", Description = "更新预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 房间配置管理 - new Permission { PermissionNumber = "roomconfig.drt", PermissionName = "删除房间配置", Module = "roomconfig", Description = "删除房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.irt", PermissionName = "添加房间配置", Module = "roomconfig", Description = "添加房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.srtbrn", PermissionName = "根据房间编号查询房间类型名称", Module = "roomconfig", Description = "根据房间编号查询房间类型名称", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.srta", PermissionName = "获取所有房间类型", Module = "roomconfig", Description = "获取所有房间类型", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.urt", PermissionName = "更新房间配置", Module = "roomconfig", Description = "更新房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 房间管理 - new Permission { PermissionNumber = "roommanagement.crbr", PermissionName = "根据预约信息办理入住", Module = "roommanagement", Description = "根据预约信息办理入住", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.cr", PermissionName = "退房操作", Module = "roommanagement", Description = "退房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.dbrn", PermissionName = "根据房间编号查询截止到今天住了多少天", Module = "roommanagement", Description = "根据房间编号查询截止到今天住了多少天", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.deleteroom", PermissionName = "删除房间", Module = "roommanagement", Description = "删除房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.insertroom", PermissionName = "添加房间", Module = "roommanagement", Description = "添加房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.scura", PermissionName = "根据房间状态来查询可使用的房间", Module = "roommanagement", Description = "根据房间状态来查询可使用的房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.scurabrs", PermissionName = "查询可入住房间数量", Module = "roommanagement", Description = "查询可入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sfrabrs", PermissionName = "查询维修房数量", Module = "roommanagement", Description = "查询维修房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sncrabrs", PermissionName = "查询脏房数量", Module = "roommanagement", Description = "查询脏房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.snurabrs", PermissionName = "查询已入住房间数量", Module = "roommanagement", Description = "查询已入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srrabrs", PermissionName = "查询预约房数量", Module = "roommanagement", Description = "查询预约房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sra", PermissionName = "获取所有房间信息", Module = "roommanagement", Description = "获取所有房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrn", PermissionName = "根据房间编号查询房间信息", Module = "roommanagement", Description = "根据房间编号查询房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrp", PermissionName = "根据房间编号查询房间价格", Module = "roommanagement", Description = "根据房间编号查询房间价格", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrs", PermissionName = "根据房间状态获取相应状态的房间信息", Module = "roommanagement", Description = "根据房间状态获取相应状态的房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbtn", PermissionName = "获取房间分区的信息", Module = "roommanagement", Description = "获取房间分区的信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.tr", PermissionName = "转房操作", Module = "roommanagement", Description = "转房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.updateroom", PermissionName = "更新房间", Module = "roommanagement", Description = "更新房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.uri", PermissionName = "根据房间编号修改房间信息(入住)", Module = "roommanagement", Description = "根据房间编号修改房间信息(入住)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.uriwr", PermissionName = "根据房间编号修改房间信息(预约)", Module = "roommanagement", Description = "根据房间编号修改房间信息(预约)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.ursbrn", PermissionName = "根据房间编号更改房间状态", Module = "roommanagement", Description = "根据房间编号更改房间状态", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // Customer management (客户管理) + // 会员等级规则管理 + new Permission { PermissionNumber = "viplevel.addviprule", PermissionName = "添加会员等级规则", Module = "customer", Description = "添加会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.delviprule", PermissionName = "删除会员等级规则", Module = "customer", Description = "删除会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.svr", PermissionName = "查询会员等级规则", Module = "customer", Description = "查询会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.svrlist", PermissionName = "查询会员等级规则列表", Module = "customer", Description = "查询会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.updviprule", PermissionName = "更新会员等级规则", Module = "customer", Description = "更新会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 客户信息 + new Permission { PermissionNumber = "customer.dci", PermissionName = "删除客户信息", Module = "customer", Description = "删除客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.ici", PermissionName = "添加客户信息", Module = "customer", Description = "添加客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.scbi", PermissionName = "查询指定客户信息", Module = "customer", Description = "查询指定客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.scs", PermissionName = "查询所有客户信息", Module = "customer", Description = "查询所有客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.uci", PermissionName = "更新客户信息", Module = "customer", Description = "更新客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.uctbcn", PermissionName = "更新会员等级", Module = "customer", Description = "更新会员等级", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 客户消费信息 + new Permission { PermissionNumber = "customerspend.acs", PermissionName = "添加客户消费信息", Module = "customer", Description = "添加客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ssbrn", PermissionName = "查询房间消费信息", Module = "customer", Description = "查询房间消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ssia", PermissionName = "查询所有消费信息", Module = "customer", Description = "查询所有消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.shsia", PermissionName = "查询客户历史消费信息", Module = "customer", Description = "查询客户历史消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.sca", PermissionName = "查询消费总金额", Module = "customer", Description = "查询消费总金额", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ucs", PermissionName = "撤回客户消费信息", Module = "customer", Description = "撤回客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.usi", PermissionName = "更新消费信息", Module = "customer", Description = "更新消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 客户类型 + new Permission { PermissionNumber = "customertype.create", PermissionName = "新增客户类型", Module = "customer", Description = "基础信息-客户类型-新增", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.delete", PermissionName = "删除客户类型", Module = "customer", Description = "基础信息-客户类型-删除", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.update", PermissionName = "更新客户类型", Module = "customer", Description = "基础信息-客户类型-更新", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.view", PermissionName = "查询客户类型列表", Module = "customer", Description = "基础信息-客户类型-查询列表", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // Human resource (酒店人事管理) // 员工管理 - new Permission { PermissionNumber = "staffmanagement.ae", PermissionName = "添加员工信息", Module = "staffmanagement", Description = "添加员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.mea", PermissionName = "员工账号禁/启用", Module = "staffmanagement", Description = "员工账号禁/启用", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.reap", PermissionName = "重置员工账号密码", Module = "staffmanagement", Description = "重置员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.sea", PermissionName = "获取所有工作人员信息", Module = "staffmanagement", Description = "获取所有工作人员信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.seibei", PermissionName = "根据登录名称查询员工信息", Module = "staffmanagement", Description = "根据登录名称查询员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ue", PermissionName = "修改员工信息", Module = "staffmanagement", Description = "修改员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + new Permission { PermissionNumber = "staffmanagement.ae", PermissionName = "添加员工信息", Module = "humanresource", Description = "添加员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.mea", PermissionName = "员工账号禁/启用", Module = "humanresource", Description = "员工账号禁/启用", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.reap", PermissionName = "重置员工账号密码", Module = "humanresource", Description = "重置员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.sea", PermissionName = "获取所有工作人员信息", Module = "humanresource", Description = "获取所有工作人员信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.seibei", PermissionName = "根据登录名称查询员工信息", Module = "humanresource", Description = "根据登录名称查询员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ue", PermissionName = "修改员工信息", Module = "humanresource", Description = "修改员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工履历管理 - new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "staffmanagement", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "staffmanagement", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "humanresource", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "humanresource", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工打卡管理 - new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "staffmanagement", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "staffmanagement", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.acfo", PermissionName = "添加员工打卡数据", Module = "staffmanagement", Description = "添加员工打卡数据", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.scfobei", PermissionName = "根据员工编号查询其所有的打卡记录", Module = "staffmanagement", Description = "根据员工编号查询其所有的打卡记录", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "humanresource", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "humanresource", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.acfo", PermissionName = "添加员工打卡数据", Module = "humanresource", Description = "添加员工打卡数据", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.scfobei", PermissionName = "根据员工编号查询其所有的打卡记录", Module = "humanresource", Description = "根据员工编号查询其所有的打卡记录", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工照片管理 - new Permission { PermissionNumber = "staffmanagement.ueap", PermissionName = "修改员工账号密码", Module = "staffmanagement", Description = "修改员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.uwp", PermissionName = "更新员工照片", Module = "staffmanagement", Description = "更新员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.dwp", PermissionName = "删除员工照片", Module = "staffmanagement", Description = "删除员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.iwp", PermissionName = "添加员工照片", Module = "staffmanagement", Description = "添加员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ep", PermissionName = "查询员工照片", Module = "staffmanagement", Description = "查询员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - + new Permission { PermissionNumber = "staffmanagement.ueap", PermissionName = "修改员工账号密码", Module = "humanresource", Description = "修改员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.uwp", PermissionName = "更新员工照片", Module = "humanresource", Description = "更新员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.dwp", PermissionName = "删除员工照片", Module = "humanresource", Description = "删除员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.iwp", PermissionName = "添加员工照片", Module = "humanresource", Description = "添加员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ep", PermissionName = "查询员工照片", Module = "humanresource", Description = "查询员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工两步验证管理 - new Permission { PermissionNumber = "staffmanagement.dtf", PermissionName = "关闭当前员工账号 2FA", Module = "staffmanagement", Description = "关闭当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.etf", PermissionName = "启用当前员工账号 2FA", Module = "staffmanagement", Description = "启用当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.gtfs", PermissionName = "生成当前员工账号的 2FA 绑定信息", Module = "staffmanagement", Description = "生成当前员工账号的 2FA 绑定信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.gtfse", PermissionName = "获取当前员工账号的 2FA 状态", Module = "staffmanagement", Description = "获取当前员工账号的 2FA 状态", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.rtfrc", PermissionName = "重置当前员工账号恢复备用码", Module = "staffmanagement", Description = "重置当前员工账号恢复备用码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.dtf", PermissionName = "关闭当前员工账号 2FA", Module = "humanresource", Description = "关闭当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.etf", PermissionName = "启用当前员工账号 2FA", Module = "humanresource", Description = "启用当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.gtfs", PermissionName = "生成当前员工账号的 2FA 绑定信息", Module = "humanresource", Description = "生成当前员工账号的 2FA 绑定信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.gtfse", PermissionName = "获取当前员工账号的 2FA 状态", Module = "humanresource", Description = "获取当前员工账号的 2FA 状态", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.rtfrc", PermissionName = "重置当前员工账号恢复备用码", Module = "humanresource", Description = "重置当前员工账号恢复备用码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 监管统计信息管理 - new Permission { PermissionNumber = "supervisioninfo.dss", PermissionName = "删除监管统计信息", Module = "supervisioninfo", Description = "删除监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.iss", PermissionName = "插入监管统计信息", Module = "supervisioninfo", Description = "插入监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.sssa", PermissionName = "查询所有监管统计信息", Module = "supervisioninfo", Description = "查询所有监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.uss", PermissionName = "更新监管统计信息", Module = "supervisioninfo", Description = "更新监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // Material management (酒店物资管理) + // 商品管理 + new Permission { PermissionNumber = "goodsmanagement.dst", PermissionName = "删除商品信息", Module = "material", Description = "删除商品信息", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ist", PermissionName = "添加商品", Module = "material", Description = "添加商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ssta", PermissionName = "查询所有商品", Module = "material", Description = "查询所有商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.sstbnap", PermissionName = "根据商品名称和价格查询商品编号", Module = "material", Description = "根据商品名称和价格查询商品编号", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ust", PermissionName = "修改商品", Module = "material", Description = "修改商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // Operation management (行为操作管理) + // 操作日志 + new Permission { PermissionNumber = "operationlog.delete", PermissionName = "删除时间范围的操作日志", Module = "operation", Description = "删除时间范围的操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "operationlog.view", PermissionName = "查询所有操作日志", Module = "operation", Description = "查询所有操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 请求日志 + new Permission { PermissionNumber = "requestlog.delete", PermissionName = "删除时间范围的请求日志", Module = "operation", Description = "删除时间范围的请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "requestlog.view", PermissionName = "查询所有请求日志", Module = "operation", Description = "查询所有请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + + // System management (系统管理) // 管理员管理 new Permission { PermissionNumber = "system:admin:addadmin", PermissionName = "添加管理员", Module = "system", Description = "添加管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:deladmin", PermissionName = "删除管理员", Module = "system", Description = "删除管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:gaal", PermissionName = "获取所有管理员列表", Module = "system", Description = "获取所有管理员列表", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:updadmin", PermissionName = "更新管理员", Module = "system", Description = "更新管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 管理员类型管理 new Permission { PermissionNumber = "system:admintype:aat", PermissionName = "添加管理员类型", Module = "system", Description = "添加管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:dat", PermissionName = "删除管理员类型", Module = "system", Description = "删除管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:gaat", PermissionName = "获取所有管理员类型", Module = "system", Description = "获取所有管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:uat", PermissionName = "更新管理员类型", Module = "system", Description = "更新管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 管理员两步验证管理 new Permission { PermissionNumber = "system:admin:gtfs", PermissionName = "获取当前管理员账号的 2FA 状态", Module = "system", Description = "获取当前管理员账号的 2FA 状态", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:dtf", PermissionName = "关闭当前管理员账号 2FA", Module = "system", Description = "关闭当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:etf", PermissionName = "启用当前管理员账号 2FA", Module = "system", Description = "启用当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:gtfsu", PermissionName = "生成当前管理员账号的 2FA 绑定信息", Module = "system", Description = "生成当前管理员账号的 2FA 绑定信息", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:rtfrc", PermissionName = "重置当前管理员账号恢复备用码", Module = "system", Description = "重置当前管理员账号恢复备用码", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 角色管理 new Permission { PermissionNumber = "system:role:aru", PermissionName = "为角色分配管理员(全量覆盖)", Module = "system", Description = "为角色分配管理员(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:deleterole", PermissionName = "删除角色", Module = "system", Description = "删除角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:grp", PermissionName = "为角色授予权限(全量覆盖)", Module = "system", Description = "为角色授予权限(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:insertrole", PermissionName = "添加角色", Module = "system", Description = "添加角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:rrp", PermissionName = "读取指定角色已授予的权限编码集合", Module = "system", Description = "读取指定角色已授予的权限编码集合", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:rrg", PermissionName = "读取指定角色菜单和权限授权(菜单与权限独立)", Module = "system", Description = "读取指定角色菜单和权限授权(菜单与权限独立)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:rru", PermissionName = "读取隶属于指定角色的管理员用户编码集合", Module = "system", Description = "读取隶属于指定角色的管理员用户编码集合", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:srl", PermissionName = "查询角色列表", Module = "system", Description = "查询角色列表", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:updaterole", PermissionName = "更新角色", Module = "system", Description = "更新角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + // 菜单管理 + new Permission { PermissionNumber = "menumanagement.bma", PermissionName = "构建菜单树", Module = "system", Description = "构建菜单树", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.deletemenu", PermissionName = "删除菜单", Module = "system", Description = "删除菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.insertmenu", PermissionName = "插入菜单", Module = "system", Description = "插入菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.sma", PermissionName = "查询所有菜单信息", Module = "system", Description = "查询所有菜单信息", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.updatemenu", PermissionName = "更新菜单", Module = "system", Description = "更新菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + // 主页 + // 仪表盘 + new Permission { PermissionNumber = "dashboard.view", PermissionName = "仪表盘-查看", Module = "home", Description = "仪表盘-查看", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "home.view", PermissionName = "首页-查看", Module = "home", Description = "首页-查看", MenuKey = "home", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.bs", PermissionName = "获取业务统计信息", Module = "dashboard", Description = "获取业务统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.hrs", PermissionName = "获取人事统计信息", Module = "dashboard", Description = "获取人事统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.ls", PermissionName = "获取后勤统计信息", Module = "dashboard", Description = "获取后勤统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.rs", PermissionName = "获取房间统计信息", Module = "dashboard", Description = "获取房间统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + + + // 权限分配 // 管理员-角色权限管理(网页端) new Permission { PermissionNumber = "system:user:admin.rudp", PermissionName = "读取指定用户的“直接权限”", Module = "system", Description = "读取指定用户的“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:admin.rurp", PermissionName = "读取指定用户的“角色-权限”明细", Module = "system", Description = "读取指定用户的“角色-权限”明细", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -897,14 +910,12 @@ namespace EOM.TSHotelManagement.Migration new Permission { PermissionNumber = "system:user:admin:aup", PermissionName = "为指定用户分配“直接权限”", Module = "system", Description = "为指定用户分配“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:admin:aur", PermissionName = "为用户分配角色(全量覆盖)", Module = "system", Description = "为用户分配角色(全量覆盖)", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:assign.spl", PermissionName = "查询权限列表(支持条件过滤与分页/忽略分页)", Module = "system", Description = "查询权限列表(支持条件过滤与分页/忽略分页)", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 客户-角色权限管理(网页端) new Permission { PermissionNumber = "system:user:customer.rudp", PermissionName = "读取客户“直接权限”权限编码集合", Module = "system", Description = "读取客户“直接权限”权限编码集合", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:customer.rurp", PermissionName = "读取客户“角色-权限”明细", Module = "system", Description = "读取客户“角色-权限”明细", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:customer.rur", PermissionName = "读取客户已分配的角色编码集合", Module = "system", Description = "读取客户已分配的角色编码集合", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:customer:aup", PermissionName = "为客户分配“直接权限”", Module = "system", Description = "为客户分配“直接权限”", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:customer:aur", PermissionName = "为客户分配角色(全量覆盖)", Module = "system", Description = "为客户分配角色(全量覆盖)", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - // 员工-角色权限管理(网页端) new Permission { PermissionNumber = "system:user:employee.rudp", PermissionName = "读取员工“直接权限”权限编码集合", Module = "system", Description = "读取员工“直接权限”权限编码集合", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:user:employee.rurp", PermissionName = "读取员工“角色-权限”明细", Module = "system", Description = "读取员工“角色-权限”明细", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, diff --git a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs index 02fa017..fb0678e 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs @@ -19,6 +19,7 @@ namespace EOM.TSHotelManagement.Service private readonly GenericRepository userRoleRepository; private readonly GenericRepository rolePermissionRepository; private readonly GenericRepository permissionRepository; + private readonly GenericRepository menuRepository; private readonly GenericRepository roleRepository; public CustomerPermissionService( @@ -26,12 +27,14 @@ namespace EOM.TSHotelManagement.Service GenericRepository userRoleRepository, GenericRepository rolePermissionRepository, GenericRepository permissionRepository, + GenericRepository menuRepository, GenericRepository roleRepository) { this.customerRepository = customerRepository; this.userRoleRepository = userRoleRepository; this.rolePermissionRepository = rolePermissionRepository; this.permissionRepository = permissionRepository; + this.menuRepository = menuRepository; this.roleRepository = roleRepository; } @@ -183,8 +186,11 @@ namespace EOM.TSHotelManagement.Service // 2) 角色 -> 权限编码(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) - .Select(rp => new { rp.RoleNumber, rp.PermissionNumber }) + .Where(rp => rp.IsDelete != 1 + && roleNumbers.Contains(rp.RoleNumber) + && rp.PermissionNumber != null + && rp.PermissionNumber != "") + .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) .ToList(); var permNumbers = rolePermList @@ -194,30 +200,61 @@ namespace EOM.TSHotelManagement.Service .ToList(); // 3) 权限详情(Permission) - var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); + var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) - .Select(p => new { p.PermissionNumber, p.PermissionName, p.MenuKey }) + .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); foreach (var p in info) { - permInfo[p.PermissionNumber] = (p.PermissionName, p.MenuKey ?? string.Empty); + permInfo[p.PermissionNumber] = p.PermissionName; } } // 4) 组装输出 + var menuIds = rolePermList + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0) + .Select(x => x.MenuId!.Value) + .Distinct() + .ToList(); + + var menuInfo = new Dictionary(); + if (menuIds.Count > 0) + { + var menus = menuRepository.AsQueryable() + .Where(m => m.IsDelete != 1 && menuIds.Contains(m.Id)) + .Select(m => new { m.Id, m.Key, m.Title }) + .ToList(); + + foreach (var m in menus) + { + menuInfo[m.Id] = (m.Key ?? string.Empty, m.Title ?? string.Empty); + } + } + var resultItems = rolePermList.Select(x => { - permInfo.TryGetValue(x.PermissionNumber, out var meta); + permInfo.TryGetValue(x.PermissionNumber!, out var permName); + var menuId = x.MenuId; + var menuKey = string.Empty; + var menuName = string.Empty; + if (menuId.HasValue && menuInfo.TryGetValue(menuId.Value, out var menuMeta)) + { + menuKey = menuMeta.Key; + menuName = menuMeta.Name; + } + return new UserRolePermissionOutputDto { RoleNumber = x.RoleNumber, - PermissionNumber = x.PermissionNumber, - PermissionName = meta.Name, - MenuKey = meta.MenuKey + PermissionNumber = x.PermissionNumber!, + PermissionName = permName, + MenuId = menuId, + MenuKey = menuKey, + MenuName = menuName }; }).ToList(); @@ -284,12 +321,10 @@ namespace EOM.TSHotelManagement.Service // 软删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) - .Select(x => new RolePermission { RoleNumber = x.RoleNumber, PermissionNumber = x.PermissionNumber, IsDelete = 1 }) .ToList(); - - foreach (var rp in existing) + if (existing.Count > 0) { - rolePermissionRepository.SoftDelete(rp); + rolePermissionRepository.SoftDeleteRange(existing); } // 过滤、去重、忽略空白 @@ -381,4 +416,4 @@ namespace EOM.TSHotelManagement.Service } } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs index c59a2a8..9217e1b 100644 --- a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs +++ b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs @@ -19,6 +19,7 @@ namespace EOM.TSHotelManagement.Service private readonly GenericRepository userRoleRepository; private readonly GenericRepository rolePermissionRepository; private readonly GenericRepository permissionRepository; + private readonly GenericRepository menuRepository; private readonly GenericRepository roleRepository; public EmployeePermissionService( @@ -26,12 +27,14 @@ namespace EOM.TSHotelManagement.Service GenericRepository userRoleRepository, GenericRepository rolePermissionRepository, GenericRepository permissionRepository, + GenericRepository menuRepository, GenericRepository roleRepository) { this.employeeRepository = employeeRepository; this.userRoleRepository = userRoleRepository; this.rolePermissionRepository = rolePermissionRepository; this.permissionRepository = permissionRepository; + this.menuRepository = menuRepository; this.roleRepository = roleRepository; } @@ -183,8 +186,11 @@ namespace EOM.TSHotelManagement.Service // 2) 角色 -> 权限编码(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) - .Select(rp => new { rp.RoleNumber, rp.PermissionNumber }) + .Where(rp => rp.IsDelete != 1 + && roleNumbers.Contains(rp.RoleNumber) + && rp.PermissionNumber != null + && rp.PermissionNumber != "") + .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) .ToList(); var permNumbers = rolePermList @@ -194,30 +200,61 @@ namespace EOM.TSHotelManagement.Service .ToList(); // 3) 权限详情(Permission) - var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); + var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) - .Select(p => new { p.PermissionNumber, p.PermissionName, p.MenuKey }) + .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); foreach (var p in info) { - permInfo[p.PermissionNumber] = (p.PermissionName, p.MenuKey ?? string.Empty); + permInfo[p.PermissionNumber] = p.PermissionName; } } // 4) 组装输出 + var menuIds = rolePermList + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0) + .Select(x => x.MenuId!.Value) + .Distinct() + .ToList(); + + var menuInfo = new Dictionary(); + if (menuIds.Count > 0) + { + var menus = menuRepository.AsQueryable() + .Where(m => m.IsDelete != 1 && menuIds.Contains(m.Id)) + .Select(m => new { m.Id, m.Key, m.Title }) + .ToList(); + + foreach (var m in menus) + { + menuInfo[m.Id] = (m.Key ?? string.Empty, m.Title ?? string.Empty); + } + } + var resultItems = rolePermList.Select(x => { - permInfo.TryGetValue(x.PermissionNumber, out var meta); + permInfo.TryGetValue(x.PermissionNumber!, out var permName); + var menuId = x.MenuId; + var menuKey = string.Empty; + var menuName = string.Empty; + if (menuId.HasValue && menuInfo.TryGetValue(menuId.Value, out var menuMeta)) + { + menuKey = menuMeta.Key; + menuName = menuMeta.Name; + } + return new UserRolePermissionOutputDto { RoleNumber = x.RoleNumber, - PermissionNumber = x.PermissionNumber, - PermissionName = meta.Name, - MenuKey = meta.MenuKey + PermissionNumber = x.PermissionNumber!, + PermissionName = permName, + MenuId = menuId, + MenuKey = menuKey, + MenuName = menuName }; }).ToList(); @@ -284,12 +321,10 @@ namespace EOM.TSHotelManagement.Service // 软删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) - .Select(x => new RolePermission { RoleNumber = x.RoleNumber, PermissionNumber = x.PermissionNumber, IsDelete = 1 }) .ToList(); - - foreach (var rp in existing) + if (existing.Count > 0) { - rolePermissionRepository.SoftDelete(rp); + rolePermissionRepository.SoftDeleteRange(existing); } // 过滤、去重、忽略空白 @@ -381,4 +416,4 @@ namespace EOM.TSHotelManagement.Service } } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs index 6ad6476..00f69fc 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs @@ -63,6 +63,11 @@ namespace EOM.TSHotelManagement.Service /// private readonly GenericRepository permissionRepository; + /// + /// 菜单 + /// + private readonly GenericRepository menuRepository; + /// /// 角色 /// @@ -90,13 +95,14 @@ namespace EOM.TSHotelManagement.Service private readonly ILogger logger; - public AdminService(GenericRepository adminRepository, GenericRepository adminTypeRepository, GenericRepository userRoleRepository, GenericRepository rolePermissionRepository, GenericRepository permissionRepository, GenericRepository roleRepository, DataProtectionHelper dataProtector, JWTHelper jWTHelper, ITwoFactorAuthService twoFactorAuthService, MailHelper mailHelper, ILogger logger) + public AdminService(GenericRepository adminRepository, GenericRepository adminTypeRepository, GenericRepository userRoleRepository, GenericRepository rolePermissionRepository, GenericRepository permissionRepository, GenericRepository menuRepository, GenericRepository roleRepository, DataProtectionHelper dataProtector, JWTHelper jWTHelper, ITwoFactorAuthService twoFactorAuthService, MailHelper mailHelper, ILogger logger) { this.adminRepository = adminRepository; this.adminTypeRepository = adminTypeRepository; this.userRoleRepository = userRoleRepository; this.rolePermissionRepository = rolePermissionRepository; this.permissionRepository = permissionRepository; + this.menuRepository = menuRepository; this.roleRepository = roleRepository; this.dataProtector = dataProtector; this.jWTHelper = jWTHelper; @@ -816,10 +822,13 @@ namespace EOM.TSHotelManagement.Service }; } - // 2) 角色 -> 权限编码(RolePermission) + // 2) 角色 -> 权限映射(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) - .Select(rp => new { rp.RoleNumber, rp.PermissionNumber }) + .Where(rp => rp.IsDelete != 1 + && roleNumbers.Contains(rp.RoleNumber) + && rp.PermissionNumber != null + && rp.PermissionNumber != "") + .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) .ToList(); var permNumbers = rolePermList @@ -829,30 +838,61 @@ namespace EOM.TSHotelManagement.Service .ToList(); // 3) 权限详情(Permission) - var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); + var permInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) - .Select(p => new { p.PermissionNumber, p.PermissionName, p.MenuKey }) + .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); foreach (var p in info) { - permInfo[p.PermissionNumber] = (p.PermissionName, p.MenuKey ?? string.Empty); + permInfo[p.PermissionNumber] = p.PermissionName; } } // 4) 组装输出 + var menuIds = rolePermList + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0) + .Select(x => x.MenuId!.Value) + .Distinct() + .ToList(); + + var menuInfo = new Dictionary(); + if (menuIds.Count > 0) + { + var menus = menuRepository.AsQueryable() + .Where(m => m.IsDelete != 1 && menuIds.Contains(m.Id)) + .Select(m => new { m.Id, m.Key, m.Title }) + .ToList(); + + foreach (var m in menus) + { + menuInfo[m.Id] = (m.Key ?? string.Empty, m.Title ?? string.Empty); + } + } + var resultItems = rolePermList.Select(x => { - permInfo.TryGetValue(x.PermissionNumber, out var meta); + permInfo.TryGetValue(x.PermissionNumber!, out var permName); + var menuId = x.MenuId; + var menuKey = string.Empty; + var menuName = string.Empty; + if (menuId.HasValue && menuInfo.TryGetValue(menuId.Value, out var menuMeta)) + { + menuKey = menuMeta.Key; + menuName = menuMeta.Name; + } + return new UserRolePermissionOutputDto { RoleNumber = x.RoleNumber, - PermissionNumber = x.PermissionNumber, - PermissionName = meta.Name, - MenuKey = meta.MenuKey + PermissionNumber = x.PermissionNumber!, + PermissionName = permName, + MenuId = menuId, + MenuKey = menuKey, + MenuName = menuName }; }).ToList(); @@ -921,12 +961,10 @@ namespace EOM.TSHotelManagement.Service // 软删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) - .Select(x => new RolePermission { RoleNumber = x.RoleNumber, PermissionNumber = x.PermissionNumber, IsDelete = 1 }) .ToList(); - - foreach (var rp in existing) + if (existing.Count > 0) { - rolePermissionRepository.SoftDelete(rp); + rolePermissionRepository.SoftDeleteRange(existing); } // 过滤、去重、忽略空白 diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs index e774e30..bc4b427 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs @@ -68,13 +68,12 @@ namespace EOM.TSHotelManagement.Service /// public ListOutputDto BuildMenuAll(BaseInputDto baseInputDto) { - // 1) 读取所有未删除的菜单 + // 1) 读取所有未删除菜单 List allMenus = menuRepository.GetList(a => a.IsDelete != 1).OrderBy(a => a.Id).ToList(); - // 默认:空用户/无权限 -> 返回空树 + // 默认:无权限返回空树 List filteredMenus = new(); - // 前端按钮权限:按菜单Key聚合的“用户拥有的权限编码”集合 - Dictionary> menuPermMap = null; + Dictionary> menuPermMap = new(); try { @@ -89,12 +88,10 @@ namespace EOM.TSHotelManagement.Service } catch { - // token 无效则按无权限处理 userNumber = string.Empty; } } - // 超级管理员放行所有菜单 var isSuperAdmin = false; if (!string.IsNullOrWhiteSpace(userNumber)) { @@ -105,112 +102,140 @@ namespace EOM.TSHotelManagement.Service if (isSuperAdmin) { filteredMenus = allMenus; - - // 超管:加载所有与菜单绑定的权限编码 - var allPermPairs = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && p.MenuKey != null) - .Select(p => new { p.MenuKey, p.PermissionNumber }) + var allPermNumbers = permissionRepository.AsQueryable() + .Where(p => p.IsDelete != 1) + .Select(p => p.PermissionNumber) + .ToList() + .Where(p => !p.IsNullOrEmpty()) + .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - menuPermMap = allPermPairs - .GroupBy(x => x.MenuKey!) - .ToDictionary(g => g.Key!, g => g.Select(x => x.PermissionNumber).Distinct().ToList()); + menuPermMap = BuildDefaultMenuPermissionMap(filteredMenus, allPermNumbers); + return BuildMenuTree(filteredMenus, menuPermMap); } - else if (!string.IsNullOrWhiteSpace(userNumber)) + + if (string.IsNullOrWhiteSpace(userNumber)) { - // 2) 用户 -> 角色 - var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) - .Select(ur => ur.RoleNumber) - .ToList(); + return BuildMenuTree(filteredMenus, menuPermMap); + } - if (roleNumbers != null && roleNumbers.Count > 0) - { - // 3) 角色 -> 权限 - var permNumbers = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) - .Select(rp => rp.PermissionNumber) - .ToList(); - - if (permNumbers != null && permNumbers.Count > 0) - { - // 4) 权限 -> 绑定的菜单Key(Permission.MenuKey) - var permQuery = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && p.MenuKey != null && permNumbers.Contains(p.PermissionNumber)); - - var allowedKeys = new HashSet( - permQuery - .Select(p => p.MenuKey) - .ToList() - .Where(k => !string.IsNullOrWhiteSpace(k))! - ); - - // 同时按菜单Key聚合当前用户拥有的权限编码,供前端按钮级控制 - var userPermPairs = permQuery - .Select(p => new { p.MenuKey, p.PermissionNumber }) - .ToList(); - - menuPermMap = userPermPairs - .GroupBy(x => x.MenuKey!) - .ToDictionary(g => g.Key!, g => g.Select(x => x.PermissionNumber).Distinct().ToList()); - - // 5) 仅保留有权限的菜单,并补齐其父级(保证树连通) - var menuById = allMenus.ToDictionary(m => m.Id); - var menuByKey = allMenus.Where(m => !string.IsNullOrWhiteSpace(m.Key)) - .ToDictionary(m => m.Key!); - var allowedMenuIds = new HashSet(); - - foreach (var key in allowedKeys) - { - if (menuByKey.TryGetValue(key, out var menu)) - { - var current = menu; - while (current != null && !allowedMenuIds.Contains(current.Id)) - { - allowedMenuIds.Add(current.Id); - if (current.Parent.HasValue && menuById.TryGetValue(current.Parent.Value, out var parentMenu)) - { - current = parentMenu; - } - else - { - current = null; - } - } - } - } - - filteredMenus = allMenus.Where(m => allowedMenuIds.Contains(m.Id)).ToList(); - } - else - { - filteredMenus = new List(); - } - } - else - { - filteredMenus = new List(); - } + // 2) 用户 -> 角色 + var roleNumbers = userRoleRepository.AsQueryable() + .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Select(ur => ur.RoleNumber) + .ToList(); + + if (roleNumbers == null || roleNumbers.Count == 0) + { + return BuildMenuTree(filteredMenus, menuPermMap); + } + + // 3) 角色 -> 授权(菜单与权限独立) + var roleGrants = rolePermissionRepository.AsQueryable() + .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) + .Select(rp => new { rp.MenuId, rp.PermissionNumber }) + .ToList(); + + var grantedPermNumbers = roleGrants + .Where(x => !x.PermissionNumber.IsNullOrEmpty()) + .Select(x => x.PermissionNumber!) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + var directMenuIds = roleGrants + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0) + .Select(x => x.MenuId!.Value) + .Distinct() + .ToHashSet(); + + if (directMenuIds.Count == 0) + { + return BuildMenuTree(filteredMenus, menuPermMap); + } + + // 4) 保留已授权菜单并补齐其父级,保证树连通 + var menuById = allMenus.ToDictionary(m => m.Id); + var allowedMenuIds = BuildAllowedMenuIdsWithAncestors(menuById, directMenuIds); + filteredMenus = allMenus.Where(m => allowedMenuIds.Contains(m.Id)).ToList(); + + // 5) 构建按菜单聚合的权限映射 + var menuSpecificPerms = roleGrants + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0 && !x.PermissionNumber.IsNullOrEmpty()) + .GroupBy(x => x.MenuId!.Value) + .ToDictionary( + g => g.Key, + g => g.Select(x => x.PermissionNumber!) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList()); + + if (menuSpecificPerms.Count > 0) + { + menuPermMap = filteredMenus + .Where(m => !string.IsNullOrWhiteSpace(m.Key)) + .ToDictionary( + m => m.Key!, + m => menuSpecificPerms.TryGetValue(m.Id, out var perms) + ? perms + : new List()); } else { - filteredMenus = new List(); + // 独立授权模式:将已授权权限作为可见菜单的全局权限集 + menuPermMap = BuildDefaultMenuPermissionMap(filteredMenus, grantedPermNumbers); } } catch { - // 异常情况下,回退为空树,避免泄露菜单 filteredMenus = new List(); + menuPermMap = new Dictionary>(); } - // 6) 构建(过滤后的)菜单树(附带每个菜单Key下的用户权限编码集合) return BuildMenuTree(filteredMenus, menuPermMap); } - /// - /// 查询所有菜单信息 - /// - /// + private static HashSet BuildAllowedMenuIdsWithAncestors( + Dictionary menuById, + HashSet directMenuIds) + { + var allowedMenuIds = new HashSet(); + + foreach (var menuId in directMenuIds) + { + if (!menuById.TryGetValue(menuId, out var current)) + { + continue; + } + + while (current != null && allowedMenuIds.Add(current.Id)) + { + if (current.Parent.HasValue && menuById.TryGetValue(current.Parent.Value, out var parentMenu)) + { + current = parentMenu; + } + else + { + current = null; + } + } + } + + return allowedMenuIds; + } + + private static Dictionary> BuildDefaultMenuPermissionMap( + List menus, + List permissionNumbers) + { + var normalizedPerms = (permissionNumbers ?? new List()) + .Where(p => !p.IsNullOrEmpty()) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + return menus + .Where(m => !string.IsNullOrWhiteSpace(m.Key)) + .ToDictionary(m => m.Key!, _ => normalizedPerms.ToList()); + } + public ListOutputDto SelectMenuAll(ReadMenuInputDto readMenuInputDto) { var where = SqlFilterBuilder.BuildExpression(readMenuInputDto ?? new ReadMenuInputDto()); @@ -411,4 +436,3 @@ namespace EOM.TSHotelManagement.Service } } } - diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Role/IRoleAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Role/IRoleAppService.cs index cc5218d..49eb25b 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Role/IRoleAppService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Role/IRoleAppService.cs @@ -47,6 +47,13 @@ namespace EOM.TSHotelManagement.Service /// 权限编码集合 ListOutputDto ReadRolePermissions(string roleNumber); + /// + /// 读取指定角色已授予的菜单与权限(菜单和权限独立) + /// + /// 角色编码 + /// 角色授权明细 + SingleOutputDto ReadRoleGrants(string roleNumber); + /// /// 读取隶属于指定角色的管理员用户编码集合 /// diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs index 390b67c..7ceea3d 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs @@ -30,13 +30,31 @@ namespace EOM.TSHotelManagement.Service /// private readonly GenericRepository userRoleRepository; + /// + /// 权限 仓储 + /// + private readonly GenericRepository permissionRepository; + + /// + /// 菜单 仓储 + /// + private readonly GenericRepository menuRepository; + private readonly ILogger logger; - public RoleAppService(GenericRepository roleRepository, GenericRepository rolePermissionRepository, GenericRepository userRoleRepository, ILogger logger) + public RoleAppService( + GenericRepository roleRepository, + GenericRepository rolePermissionRepository, + GenericRepository userRoleRepository, + GenericRepository permissionRepository, + GenericRepository menuRepository, + ILogger logger) { this.roleRepository = roleRepository; this.rolePermissionRepository = rolePermissionRepository; this.userRoleRepository = userRoleRepository; + this.permissionRepository = permissionRepository; + this.menuRepository = menuRepository; this.logger = logger; } @@ -215,15 +233,13 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Role not found", "角色不存在")); } - // 软删除该角色现有有效的权限映射 + // 软删除该角色现有有效授权映射(菜单 + 权限) var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == input.RoleNumber && x.IsDelete != 1) - .Select(x => new RolePermission { RoleNumber = x.RoleNumber, PermissionNumber = x.PermissionNumber, IsDelete = 1 }) .ToList(); - - foreach (var rp in existing) + if (existing.Count > 0) { - rolePermissionRepository.SoftDelete(rp); + rolePermissionRepository.SoftDeleteRange(existing); } // 过滤去重并忽略空白权限码 @@ -233,13 +249,53 @@ namespace EOM.TSHotelManagement.Service .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - // 插入新的权限映射 - foreach (var perm in distinctPerms) + // 过滤去重并忽略非法菜单主键 + var distinctMenuIds = (input.MenuIds ?? new List()) + .Where(id => id > 0) + .Distinct() + .ToList(); + + // 仅保留系统中真实存在的权限编码和菜单主键 + var validPerms = distinctPerms.Count == 0 + ? new List() + : permissionRepository.AsQueryable() + .Where(p => p.IsDelete != 1 && distinctPerms.Contains(p.PermissionNumber)) + .Select(p => p.PermissionNumber) + .ToList() + .Where(p => !p.IsNullOrEmpty()) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + var validMenuIds = distinctMenuIds.Count == 0 + ? new List() + : menuRepository.AsQueryable() + .Where(m => m.IsDelete != 1 && distinctMenuIds.Contains(m.Id)) + .Select(m => m.Id) + .ToList() + .Distinct() + .ToList(); + + // 写入角色-权限映射 + foreach (var perm in validPerms) { var entity = new RolePermission { RoleNumber = input.RoleNumber, PermissionNumber = perm, + MenuId = null, + IsDelete = 0 + }; + rolePermissionRepository.Insert(entity); + } + + // 写入角色-菜单映射 + foreach (var menuId in validMenuIds) + { + var entity = new RolePermission + { + RoleNumber = input.RoleNumber, + MenuId = menuId, + PermissionNumber = null, IsDelete = 0 }; rolePermissionRepository.Insert(entity); @@ -272,7 +328,10 @@ namespace EOM.TSHotelManagement.Service try { var list = rolePermissionRepository.AsQueryable() - .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == roleNumber + && rp.IsDelete != 1 + && rp.PermissionNumber != null + && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) .ToList() ?? new List(); @@ -299,6 +358,74 @@ namespace EOM.TSHotelManagement.Service } } + /// + /// 读取指定角色已授予的菜单与权限(菜单与权限独立) + /// + public SingleOutputDto ReadRoleGrants(string roleNumber) + { + if (roleNumber.IsNullOrEmpty()) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("RoleNumber is required", "缺少角色编码"), + Data = new ReadRoleGrantOutputDto + { + RoleNumber = string.Empty, + PermissionNumbers = new List(), + MenuIds = new List() + } + }; + } + + try + { + var grants = rolePermissionRepository.AsQueryable() + .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Select(rp => new { rp.PermissionNumber, rp.MenuId }) + .ToList(); + + var permissionNumbers = grants + .Where(x => !x.PermissionNumber.IsNullOrEmpty()) + .Select(x => x.PermissionNumber!) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + var menuIds = grants + .Where(x => x.MenuId.HasValue && x.MenuId.Value > 0) + .Select(x => x.MenuId!.Value) + .Distinct() + .ToList(); + + return new SingleOutputDto + { + Code = BusinessStatusCode.Success, + Message = LocalizationHelper.GetLocalizedString("Query success", "查询成功"), + Data = new ReadRoleGrantOutputDto + { + RoleNumber = roleNumber, + PermissionNumbers = permissionNumbers, + MenuIds = menuIds + } + }; + } + catch (Exception ex) + { + logger.LogError(ex, "Error reading grants for role {RoleNumber}: {Message}", roleNumber, ex.Message); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString($"Query failed: {ex.Message}", $"查询失败:{ex.Message}"), + Data = new ReadRoleGrantOutputDto + { + RoleNumber = roleNumber, + PermissionNumbers = new List(), + MenuIds = new List() + } + }; + } + } + /// /// 读取隶属于指定角色的管理员用户编码集合 /// -- Gitee From c137967654db04a50af9b94b9e1657a348858440 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Fri, 20 Feb 2026 16:07:38 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E5=B0=86=E6=9D=83=E9=99=90=E5=88=86?= =?UTF-8?q?=E9=85=8D=E7=9A=84=E6=95=B0=E6=8D=AE=EF=BC=8C=E4=BB=8E=E8=BD=AF?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=94=B9=E4=B8=BA=E7=A1=AC=E5=88=A0=E9=99=A4?= =?UTF-8?q?=EF=BC=8C=E8=8A=82=E7=9C=81=E8=A1=A8=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Business/Customer/Permission/CustomerPermissionService.cs | 4 ++-- .../Employee/Permission/EmployeePermissionService.cs | 4 ++-- .../SystemManagement/Administrator/AdminService.cs | 4 ++-- .../SystemManagement/Role/RoleAppService.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs index fb0678e..e2f02c1 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs @@ -318,13 +318,13 @@ namespace EOM.TSHotelManagement.Service roleRepository.Insert(role); } - // 软删除当前专属角色下所有有效的角色-权限绑定 + // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) .ToList(); if (existing.Count > 0) { - rolePermissionRepository.SoftDeleteRange(existing); + rolePermissionRepository.Delete(existing); } // 过滤、去重、忽略空白 diff --git a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs index 9217e1b..ae63dff 100644 --- a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs +++ b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs @@ -318,13 +318,13 @@ namespace EOM.TSHotelManagement.Service roleRepository.Insert(role); } - // 软删除当前专属角色下所有有效的角色-权限绑定 + // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) .ToList(); if (existing.Count > 0) { - rolePermissionRepository.SoftDeleteRange(existing); + rolePermissionRepository.Delete(existing); } // 过滤、去重、忽略空白 diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs index 00f69fc..159974d 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs @@ -958,13 +958,13 @@ namespace EOM.TSHotelManagement.Service roleRepository.Insert(role); } - // 软删除当前专属角色下所有有效的角色-权限绑定 + // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) .ToList(); if (existing.Count > 0) { - rolePermissionRepository.SoftDeleteRange(existing); + rolePermissionRepository.Delete(existing); } // 过滤、去重、忽略空白 diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs index 7ceea3d..8d5f708 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs @@ -233,13 +233,13 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Role not found", "角色不存在")); } - // 软删除该角色现有有效授权映射(菜单 + 权限) + // 硬删除该角色现有有效授权映射(菜单 + 权限) var existing = rolePermissionRepository.AsQueryable() .Where(x => x.RoleNumber == input.RoleNumber && x.IsDelete != 1) .ToList(); if (existing.Count > 0) { - rolePermissionRepository.SoftDeleteRange(existing); + rolePermissionRepository.Delete(existing); } // 过滤去重并忽略空白权限码 -- Gitee From 2379efb1f76e0b7a919ac782b61358a89df7c10d Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Fri, 20 Feb 2026 16:50:29 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=A1=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Authorization/PermissionsAuthorization.cs | 5 +- .../Extensions/PermissionSyncExtensions.cs | 4 - .../DatabaseInitializer.cs | 17 +- .../Repository/GenericRepository.cs | 16 +- .../Application/NavBar/NavBar.cs | 4 +- EOM.TSHotelManagement.Domain/BaseEntity.cs | 43 -- .../Business/Asset/Asset.cs | 4 +- .../Business/Customer/CustoSpend.cs | 42 -- .../Business/Customer/CustoType.cs | 4 +- .../Business/Customer/Customer.cs | 4 +- .../Business/Customer/CustomerAccount.cs | 2 +- .../Business/Customer/PassPortType.cs | 4 +- .../EnergyManagement/EnergyManagement.cs | 4 +- .../Business/News/News.cs | 4 +- .../PromotionContent/PromotionContent.cs | 4 +- .../Business/Reser/Reser.cs | 4 +- .../Business/Room/Room.cs | 4 +- .../Business/Room/RoomType.cs | 4 +- .../Business/Sellthing/SellThing.cs | 4 +- .../Business/Spend/Spend.cs | 4 +- .../Common/AuditEntity.cs | 29 ++ .../Common/BaseEntity.cs | 18 + .../Common/SoftDeleteEntity.cs | 14 + .../Employee/Employee.cs | 4 +- .../Employee/EmployeeCheck.cs | 4 +- .../Employee/EmployeeHistory.cs | 4 +- .../Employee/EmployeePhoto.cs | 4 +- .../Employee/EmployeeRewardPunishment.cs | 4 +- .../Employee/RewardPunishmentType.cs | 6 +- .../SystemManagement/Administrator.cs | 4 +- .../SystemManagement/AdministratorType.cs | 4 +- .../SystemManagement/AppointmentNotice.cs | 4 +- .../SystemManagement/AppointmentNoticeType.cs | 4 +- .../SystemManagement/Department.cs | 4 +- .../SystemManagement/Education.cs | 4 +- .../SystemManagement/Menu.cs | 6 +- .../SystemManagement/Nation.cs | 4 +- .../SystemManagement/Permission.cs | 4 +- .../SystemManagement/Position.cs | 4 +- .../SystemManagement/Role.cs | 6 +- .../SystemManagement/RolePermission.cs | 4 +- .../SystemManagement/SupervisionStatistics.cs | 4 +- .../SystemManagement/SystemInformation.cs | 53 --- .../SystemManagement/TwoFactorAuth.cs | 2 +- .../SystemManagement/TwoFactorRecoveryCode.cs | 2 +- .../SystemManagement/UserRole.cs | 6 +- .../SystemManagement/VipLevelRule.cs | 4 +- .../Util/OperationLog.cs | 4 +- .../Util/RequestLog.cs | 4 +- .../EntityBuilder.cs | 366 +++++++++--------- .../Account/CustomerAccountService.cs | 5 +- .../Business/Customer/CustomerService.cs | 3 +- .../Permission/CustomerPermissionService.cs | 34 +- .../Business/Spend/SpendService.cs | 3 +- .../Permission/EmployeePermissionService.cs | 30 +- .../Administrator/AdminService.cs | 44 +-- .../SystemManagement/Base/BaseService.cs | 8 +- .../SystemManagement/Menu/MenuService.cs | 5 +- .../SystemManagement/Role/RoleAppService.cs | 26 +- 59 files changed, 400 insertions(+), 523 deletions(-) delete mode 100644 EOM.TSHotelManagement.Domain/BaseEntity.cs delete mode 100644 EOM.TSHotelManagement.Domain/Business/Customer/CustoSpend.cs create mode 100644 EOM.TSHotelManagement.Domain/Common/AuditEntity.cs create mode 100644 EOM.TSHotelManagement.Domain/Common/BaseEntity.cs create mode 100644 EOM.TSHotelManagement.Domain/Common/SoftDeleteEntity.cs delete mode 100644 EOM.TSHotelManagement.Domain/SystemManagement/SystemInformation.cs diff --git a/EOM.TSHotelManagement.API/Authorization/PermissionsAuthorization.cs b/EOM.TSHotelManagement.API/Authorization/PermissionsAuthorization.cs index e37fa55..b2884f6 100644 --- a/EOM.TSHotelManagement.API/Authorization/PermissionsAuthorization.cs +++ b/EOM.TSHotelManagement.API/Authorization/PermissionsAuthorization.cs @@ -135,7 +135,7 @@ namespace EOM.TSHotelManagement.WebApi.Authorization // 获取用户绑定的有效角色 var roleNumbers = await _db.Queryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToListAsync(); @@ -147,8 +147,7 @@ namespace EOM.TSHotelManagement.WebApi.Authorization // 判断角色是否拥有该权限 var hasPermission = await _db.Queryable() - .Where(rp => rp.IsDelete != 1 - && roleNumbers.Contains(rp.RoleNumber) + .Where(rp => roleNumbers.Contains(rp.RoleNumber) && rp.PermissionNumber == requirement.Code) .AnyAsync(); diff --git a/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs b/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs index fc19b52..52efbb6 100644 --- a/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs @@ -67,7 +67,6 @@ namespace EOM.TSHotelManagement.WebApi // 查询已有权限 var existing = db.Queryable() - .Where(p => p.IsDelete != 1) .Select(p => p.PermissionNumber) .ToList(); @@ -88,7 +87,6 @@ namespace EOM.TSHotelManagement.WebApi Description = "Auto-synced from [RequirePermission] on API action", MenuKey = null, ParentNumber = null, - IsDelete = 0, DataInsUsr = "System", DataInsDate = now }).ToList(); @@ -105,7 +103,6 @@ namespace EOM.TSHotelManagement.WebApi // 如角色不存在,DatabaseInitializer 已负责创建;此处仅做映射补齐 var existingRolePerms = db.Queryable() .Where(rp => rp.RoleNumber == AdminRoleNumber - && rp.IsDelete != 1 && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) @@ -124,7 +121,6 @@ namespace EOM.TSHotelManagement.WebApi { RoleNumber = AdminRoleNumber, PermissionNumber = p, - IsDelete = 0, DataInsUsr = "System", DataInsDate = now }).ToList(); diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index c5e00af..49c8dd0 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -462,10 +462,9 @@ WHERE rp.`menu_id` IS NULL PassportType _ => 6, Menu _ => 7, NavBar _ => 8, - SystemInformation _ => 9, - PromotionContent _ => 10, - Administrator _ => 11, - Employee _ => 12, + PromotionContent _ => 9, + Administrator _ => 10, + Employee _ => 11, _ => 99 }) .ToList(); @@ -502,10 +501,6 @@ WHERE rp.`menu_id` IS NULL alreadyExists = db.Queryable().Any(a => a.PromotionContentMessage == promoContent.PromotionContentMessage); break; - case SystemInformation sysInfo: - alreadyExists = db.Queryable().Any(a => a.UrlAddress == sysInfo.UrlAddress); - break; - case Nation nation: alreadyExists = db.Queryable().Any(a => a.NationName == nation.NationName); break; @@ -640,7 +635,7 @@ WHERE rp.`menu_id` IS NULL if (adminUser != null) { var hasBind = db.Queryable() - .Any(ur => ur.UserNumber == adminUser.Number && ur.RoleNumber == adminRoleNumber && ur.IsDelete != 1); + .Any(ur => ur.UserNumber == adminUser.Number && ur.RoleNumber == adminRoleNumber); if (!hasBind) { @@ -648,7 +643,6 @@ WHERE rp.`menu_id` IS NULL { UserNumber = adminUser.Number, RoleNumber = adminRoleNumber, - IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }).ExecuteCommand(); @@ -662,13 +656,11 @@ WHERE rp.`menu_id` IS NULL // 3) Grant ALL permissions to admin role var allPermNumbers = db.Queryable() - .Where(p => p.IsDelete != 1) .Select(p => p.PermissionNumber) .ToList(); var existingRolePerms = db.Queryable() .Where(rp => rp.RoleNumber == adminRoleNumber - && rp.IsDelete != 1 && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) @@ -686,7 +678,6 @@ WHERE rp.`menu_id` IS NULL { RoleNumber = adminRoleNumber, PermissionNumber = p!, - IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }).ToList(); diff --git a/EOM.TSHotelManagement.Data/Repository/GenericRepository.cs b/EOM.TSHotelManagement.Data/Repository/GenericRepository.cs index 415449c..36992f4 100644 --- a/EOM.TSHotelManagement.Data/Repository/GenericRepository.cs +++ b/EOM.TSHotelManagement.Data/Repository/GenericRepository.cs @@ -45,7 +45,7 @@ namespace EOM.TSHotelManagement.Data public override bool Insert(T entity) { - if (entity is BaseEntity baseEntity) + if (entity is AuditEntity baseEntity) { var currentUser = GetCurrentUser(); if (!baseEntity.DataInsDate.HasValue) @@ -62,7 +62,7 @@ namespace EOM.TSHotelManagement.Data { Expression>? rowVersionWhere = null; - if (entity is BaseEntity baseEntity) + if (entity is AuditEntity baseEntity) { var currentUser = GetCurrentUser(); if (!baseEntity.DataChgDate.HasValue) @@ -110,7 +110,7 @@ namespace EOM.TSHotelManagement.Data foreach (var entity in updateObjs) { - if (entity is BaseEntity baseEntity) + if (entity is AuditEntity baseEntity) { var currentUser = GetCurrentUser(); if (!baseEntity.DataChgDate.HasValue) @@ -146,7 +146,7 @@ namespace EOM.TSHotelManagement.Data public bool SoftDelete(T entity) { - if (entity is BaseEntity baseEntity) + if (entity is SoftDeleteEntity baseEntity) { var currentUser = GetCurrentUser(); if (!baseEntity.DataChgDate.HasValue) @@ -220,7 +220,7 @@ namespace EOM.TSHotelManagement.Data // 更新内存中的实体状态 foreach (var entity in entities) { - if (entity is BaseEntity baseEntity) + if (entity is SoftDeleteEntity baseEntity) { hasBaseEntity = true; baseEntity.IsDelete = 1; @@ -242,9 +242,9 @@ namespace EOM.TSHotelManagement.Data totalAffected += base.Context.Updateable(batch) .UpdateColumns(new[] { - nameof(BaseEntity.IsDelete), - nameof(BaseEntity.DataChgUsr), - nameof(BaseEntity.DataChgDate) + nameof(SoftDeleteEntity.IsDelete), + nameof(AuditEntity.DataChgUsr), + nameof(AuditEntity.DataChgDate) }) .ExecuteCommand(); } diff --git a/EOM.TSHotelManagement.Domain/Application/NavBar/NavBar.cs b/EOM.TSHotelManagement.Domain/Application/NavBar/NavBar.cs index b264880..d38eda2 100644 --- a/EOM.TSHotelManagement.Domain/Application/NavBar/NavBar.cs +++ b/EOM.TSHotelManagement.Domain/Application/NavBar/NavBar.cs @@ -1,4 +1,4 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { @@ -6,7 +6,7 @@ namespace EOM.TSHotelManagement.Domain /// 导航栏配置表 (Navigation Bar Configuration) /// [SugarTable("nav_bar", "导航栏配置表 (Navigation Bar Configuration)", true)] - public class NavBar : BaseEntity + public class NavBar : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/BaseEntity.cs b/EOM.TSHotelManagement.Domain/BaseEntity.cs deleted file mode 100644 index 68954f7..0000000 --- a/EOM.TSHotelManagement.Domain/BaseEntity.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; - -namespace EOM.TSHotelManagement.Domain -{ - public class BaseEntity - { - /// - /// 删除标识 - /// - [SqlSugar.SugarColumn(ColumnName = "delete_mk", Length = 11, IsNullable = false, DefaultValue = "0")] - public int? IsDelete { get; set; } = 0; - /// - /// 资料创建人 - /// - [SqlSugar.SugarColumn(ColumnName = "datains_usr", Length = 128, IsOnlyIgnoreUpdate = true, IsNullable = true)] - public string? DataInsUsr { get; set; } - /// - /// 资料创建时间 - /// - [SqlSugar.SugarColumn(ColumnName = "datains_date", IsOnlyIgnoreUpdate = true, IsNullable = true)] - public DateTime? DataInsDate { get; set; } - /// - /// 资料更新人 - /// - [SqlSugar.SugarColumn(ColumnName = "datachg_usr", Length = 128, IsOnlyIgnoreInsert = true, IsNullable = true)] - public string? DataChgUsr { get; set; } - /// - /// 资料更新时间 - /// - [SqlSugar.SugarColumn(ColumnName = "datachg_date", IsOnlyIgnoreInsert = true, IsNullable = true)] - public DateTime? DataChgDate { get; set; } - /// - /// 行版本(乐观锁) - /// - [SqlSugar.SugarColumn(ColumnName = "row_version", IsNullable = false, DefaultValue = "1")] - public long RowVersion { get; set; } = 1; - /// - /// Token - /// - [SqlSugar.SugarColumn(IsIgnore = true)] - public string? UserToken { get; set; } - } -} diff --git a/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs b/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs index 7f79ea6..dae0369 100644 --- a/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs +++ b/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 资产管理 /// [SqlSugar.SugarTable("asset")] - public class Asset : BaseEntity + public class Asset : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/CustoSpend.cs b/EOM.TSHotelManagement.Domain/Business/Customer/CustoSpend.cs deleted file mode 100644 index b189e5b..0000000 --- a/EOM.TSHotelManagement.Domain/Business/Customer/CustoSpend.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - *模块说明:酒店盈利情况类 - */ -namespace EOM.TSHotelManagement.Domain -{ - /// - /// 酒店盈利情况 - /// - public class CustoSpend - { - /// - /// 年 - /// - public string Years { get; set; } - /// - /// 总金额 - /// - public decimal Money { get; set; } - - } -} diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/CustoType.cs b/EOM.TSHotelManagement.Domain/Business/Customer/CustoType.cs index 311987e..0f3f379 100644 --- a/EOM.TSHotelManagement.Domain/Business/Customer/CustoType.cs +++ b/EOM.TSHotelManagement.Domain/Business/Customer/CustoType.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 客户类型 /// [SqlSugar.SugarTable("custo_type")] - public class CustoType : BaseEntity + public class CustoType : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs b/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs index ec58653..6620b8d 100644 --- a/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs +++ b/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 客户信息 /// [SqlSugar.SugarTable("customer")] - public class Customer : BaseEntity + public class Customer : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/CustomerAccount.cs b/EOM.TSHotelManagement.Domain/Business/Customer/CustomerAccount.cs index 957fe62..79046f0 100644 --- a/EOM.TSHotelManagement.Domain/Business/Customer/CustomerAccount.cs +++ b/EOM.TSHotelManagement.Domain/Business/Customer/CustomerAccount.cs @@ -3,7 +3,7 @@ using System; namespace EOM.TSHotelManagement.Domain { [SqlSugar.SugarTable("customer_account", "客户账号表")] - public class CustomerAccount : BaseEntity + public class CustomerAccount : SoftDeleteEntity { /// /// ID (索引ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/PassPortType.cs b/EOM.TSHotelManagement.Domain/Business/Customer/PassPortType.cs index 66a0717..79dccab 100644 --- a/EOM.TSHotelManagement.Domain/Business/Customer/PassPortType.cs +++ b/EOM.TSHotelManagement.Domain/Business/Customer/PassPortType.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 证件类型 /// [SqlSugar.SugarTable("passport_type")] - public class PassportType : BaseEntity + public class PassportType : SoftDeleteEntity { [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "编号 (ID)")] public int Id { get; set; } diff --git a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs index 84bbe06..d12bc48 100644 --- a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs +++ b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 水电信息 /// [SqlSugar.SugarTable("energy_management", "水电信息")] - public class EnergyManagement : BaseEntity + public class EnergyManagement : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/News/News.cs b/EOM.TSHotelManagement.Domain/Business/News/News.cs index fe1706e..57c66bb 100644 --- a/EOM.TSHotelManagement.Domain/Business/News/News.cs +++ b/EOM.TSHotelManagement.Domain/Business/News/News.cs @@ -1,9 +1,9 @@ -using System; +using System; namespace EOM.TSHotelManagement.Domain { [SqlSugar.SugarTable("news", "新闻动态")] - public class News : BaseEntity + public class News : SoftDeleteEntity { [SqlSugar.SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "索引ID")] public int Id { get; set; } diff --git a/EOM.TSHotelManagement.Domain/Business/PromotionContent/PromotionContent.cs b/EOM.TSHotelManagement.Domain/Business/PromotionContent/PromotionContent.cs index d6eec3e..211ff73 100644 --- a/EOM.TSHotelManagement.Domain/Business/PromotionContent/PromotionContent.cs +++ b/EOM.TSHotelManagement.Domain/Business/PromotionContent/PromotionContent.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// APP横幅配置表 (APP Banner Configuration) /// [SugarTable("app_banner", "APP横幅配置表 (APP Banner Configuration)")] - public class PromotionContent : BaseEntity + public class PromotionContent : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs b/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs index cf497f2..8e27af8 100644 --- a/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs +++ b/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 预约信息表 (Reservation Information) /// [SugarTable("reser", "预约信息表 (Reservation Information)")] - public class Reser : BaseEntity + public class Reser : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs index b161cef..7be37c6 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -32,7 +32,7 @@ namespace EOM.TSHotelManagement.Domain /// 酒店房间信息表 (Hotel Room Information) /// [SugarTable("room", "酒店房间信息表 (Hotel Room Information)")] - public class Room : BaseEntity + public class Room : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs b/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs index 783f7c2..95c2f32 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 房间类型配置表 (Room Type Configuration) /// [SugarTable("room_type", "房间类型配置表 (Room Type Configuration)")] - public class RoomType : BaseEntity + public class RoomType : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Sellthing/SellThing.cs b/EOM.TSHotelManagement.Domain/Business/Sellthing/SellThing.cs index 8039a86..80ebc57 100644 --- a/EOM.TSHotelManagement.Domain/Business/Sellthing/SellThing.cs +++ b/EOM.TSHotelManagement.Domain/Business/Sellthing/SellThing.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -32,7 +32,7 @@ namespace EOM.TSHotelManagement.Domain /// 商品信息表 (Product Information) /// [SugarTable("sellthing", "商品信息表 (Product Information)")] - public class SellThing : BaseEntity + public class SellThing : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs b/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs index 514641f..c1ecda6 100644 --- a/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs +++ b/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 消费信息 (Consumption Information) /// [SugarTable("customer_spend")] - public class Spend : BaseEntity + public class Spend : SoftDeleteEntity { [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "编号 (ID)")] public int Id { get; set; } diff --git a/EOM.TSHotelManagement.Domain/Common/AuditEntity.cs b/EOM.TSHotelManagement.Domain/Common/AuditEntity.cs new file mode 100644 index 0000000..b2e854e --- /dev/null +++ b/EOM.TSHotelManagement.Domain/Common/AuditEntity.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Domain; + +public class AuditEntity: BaseEntity +{ + /// + /// 资料创建人 + /// + [SqlSugar.SugarColumn(ColumnName = "datains_usr", Length = 128, IsOnlyIgnoreUpdate = true, IsNullable = true)] + public string? DataInsUsr { get; set; } + /// + /// 资料创建时间 + /// + [SqlSugar.SugarColumn(ColumnName = "datains_date", IsOnlyIgnoreUpdate = true, IsNullable = true)] + public DateTime? DataInsDate { get; set; } + /// + /// 资料更新人 + /// + [SqlSugar.SugarColumn(ColumnName = "datachg_usr", Length = 128, IsOnlyIgnoreInsert = true, IsNullable = true)] + public string? DataChgUsr { get; set; } + /// + /// 资料更新时间 + /// + [SqlSugar.SugarColumn(ColumnName = "datachg_date", IsOnlyIgnoreInsert = true, IsNullable = true)] + public DateTime? DataChgDate { get; set; } +} diff --git a/EOM.TSHotelManagement.Domain/Common/BaseEntity.cs b/EOM.TSHotelManagement.Domain/Common/BaseEntity.cs new file mode 100644 index 0000000..7a0b7af --- /dev/null +++ b/EOM.TSHotelManagement.Domain/Common/BaseEntity.cs @@ -0,0 +1,18 @@ +using System; + +namespace EOM.TSHotelManagement.Domain +{ + public class BaseEntity + { + /// + /// 行版本(乐观锁) + /// + [SqlSugar.SugarColumn(ColumnName = "row_version", IsNullable = false, DefaultValue = "1")] + public long RowVersion { get; set; } = 1; + /// + /// Token + /// + [SqlSugar.SugarColumn(IsIgnore = true)] + public string? UserToken { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Domain/Common/SoftDeleteEntity.cs b/EOM.TSHotelManagement.Domain/Common/SoftDeleteEntity.cs new file mode 100644 index 0000000..e8a8663 --- /dev/null +++ b/EOM.TSHotelManagement.Domain/Common/SoftDeleteEntity.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Domain; + +public class SoftDeleteEntity : AuditEntity +{ + /// + /// 删除标识 + /// + [SqlSugar.SugarColumn(ColumnName = "delete_mk", Length = 11, IsNullable = false, DefaultValue = "0")] + public int? IsDelete { get; set; } = 0; +} diff --git a/EOM.TSHotelManagement.Domain/Employee/Employee.cs b/EOM.TSHotelManagement.Domain/Employee/Employee.cs index 77db185..d5ec972 100644 --- a/EOM.TSHotelManagement.Domain/Employee/Employee.cs +++ b/EOM.TSHotelManagement.Domain/Employee/Employee.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工信息 (Employee Information) /// [SugarTable("employee")] - public class Employee : BaseEntity + public class Employee : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs b/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs index 92e40db..89e567b 100644 --- a/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs +++ b/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工打卡考勤 (Employee Check-in/Check-out Record) /// [SugarTable("employee_check", "员工打卡考勤 (Employee Check-in/Check-out Record)")] - public class EmployeeCheck : BaseEntity + public class EmployeeCheck : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Employee/EmployeeHistory.cs b/EOM.TSHotelManagement.Domain/Employee/EmployeeHistory.cs index b1a93b0..56ccbbc 100644 --- a/EOM.TSHotelManagement.Domain/Employee/EmployeeHistory.cs +++ b/EOM.TSHotelManagement.Domain/Employee/EmployeeHistory.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工履历 (Employee History) /// [SugarTable("employee_history")] - public class EmployeeHistory : BaseEntity + public class EmployeeHistory : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Employee/EmployeePhoto.cs b/EOM.TSHotelManagement.Domain/Employee/EmployeePhoto.cs index 2a86f21..b216028 100644 --- a/EOM.TSHotelManagement.Domain/Employee/EmployeePhoto.cs +++ b/EOM.TSHotelManagement.Domain/Employee/EmployeePhoto.cs @@ -1,4 +1,4 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { @@ -6,7 +6,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工照片 (Employee Photo) /// [SugarTable("employee_pic", "员工照片 (Employee Photo)")] - public class EmployeePhoto : BaseEntity + public class EmployeePhoto : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Employee/EmployeeRewardPunishment.cs b/EOM.TSHotelManagement.Domain/Employee/EmployeeRewardPunishment.cs index e88ee2e..38d311a 100644 --- a/EOM.TSHotelManagement.Domain/Employee/EmployeeRewardPunishment.cs +++ b/EOM.TSHotelManagement.Domain/Employee/EmployeeRewardPunishment.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工奖惩 (Employee Rewards/Punishments) /// [SugarTable("reward_punishment", "员工奖惩 (Employee Rewards/Punishments)")] - public class EmployeeRewardPunishment : BaseEntity + public class EmployeeRewardPunishment : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Employee/RewardPunishmentType.cs b/EOM.TSHotelManagement.Domain/Employee/RewardPunishmentType.cs index 028cbaa..2e97cd3 100644 --- a/EOM.TSHotelManagement.Domain/Employee/RewardPunishmentType.cs +++ b/EOM.TSHotelManagement.Domain/Employee/RewardPunishmentType.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 奖惩类型配置表 (Reward/Punishment Type Configuration) /// [SugarTable("reward_punishment_type", "奖惩类型配置表 (Reward/Punishment Type Configuration)")] - public class RewardPunishmentType : BaseEntity + public class RewardPunishmentType : SoftDeleteEntity { /// /// 编号 (ID) @@ -62,4 +62,4 @@ namespace EOM.TSHotelManagement.Domain )] public string RewardPunishmentTypeName { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs index fb52e73..6764f27 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 管理员实体类 (Administrator Entity) /// [SugarTable("administrator", "管理员实体类 (Administrator Entity)", true)] - public class Administrator : BaseEntity + public class Administrator : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorType.cs b/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorType.cs index d8d04c5..b461216 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorType.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorType.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 管理员类型 (Administrator Type) /// [SugarTable("administrator_type", "管理员类型 (Administrator Type)", true)] - public class AdministratorType : BaseEntity + public class AdministratorType : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNotice.cs b/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNotice.cs index d9acdd4..f639ed7 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNotice.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNotice.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 任命公告 (Appointment AppointmentNotice) /// [SugarTable("appointment_notice", "任命公告 (Appointment AppointmentNotice)")] - public class AppointmentNotice : BaseEntity + public class AppointmentNotice : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNoticeType.cs b/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNoticeType.cs index 1afdeec..4bd65db 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNoticeType.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/AppointmentNoticeType.cs @@ -1,9 +1,9 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { [SugarTable("appointment_notice_type", "任命公告类型 (Appointment AppointmentNotice Type)")] - public class AppointmentNoticeType : BaseEntity + public class AppointmentNoticeType : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Department.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Department.cs index 00e5a5e..98721a7 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Department.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Department.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 部门表 (Department Table) /// [SugarTable("department")] - public class Department : BaseEntity + public class Department : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Education.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Education.cs index e96f210..6a7d087 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Education.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Education.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 学历 (Education) /// [SugarTable("qualification", "学历 (Education)")] - public class Education : BaseEntity + public class Education : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Menu.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Menu.cs index ad8152c..c0468ce 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Menu.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Menu.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -29,7 +29,7 @@ namespace EOM.TSHotelManagement.Domain /// 菜单表 (Menu Table) /// [SugarTable("menu", "菜单表 (Menu Table)", true)] - public class Menu : BaseEntity + public class Menu : SoftDeleteEntity { /// /// 编号 (ID) @@ -72,4 +72,4 @@ namespace EOM.TSHotelManagement.Domain public string Icon { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Nation.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Nation.cs index 3f3ce96..168efa1 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Nation.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Nation.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 民族 (Nation) /// [SugarTable("nation", "民族信息表 (Nation Information)")] - public class Nation : BaseEntity + public class Nation : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Permission.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Permission.cs index 9f96ad8..8bc0bad 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Permission.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Permission.cs @@ -6,7 +6,7 @@ namespace EOM.TSHotelManagement.Domain /// 系统权限定义表 (Permission Definition) /// [SugarTable("permission", "系统权限定义表 (Permission Definition)")] - public class Permission : BaseEntity + public class Permission : AuditEntity { /// /// 编号 (ID) @@ -81,4 +81,4 @@ namespace EOM.TSHotelManagement.Domain )] public string? ParentNumber { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Position.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Position.cs index de74ca0..2f1f310 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Position.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Position.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 职位信息表 (Position Information) /// [SugarTable("position", "职位信息表 (Position Information)")] - public class Position : BaseEntity + public class Position : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Role.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Role.cs index faf2414..5dceac4 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Role.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Role.cs @@ -1,11 +1,11 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { /// /// 系统角色配置表 (System Role Configuration) /// [SugarTable("role", "系统角色配置表 (System Role Configuration)")] - public class Role : BaseEntity + public class Role : SoftDeleteEntity { /// /// 编号 (ID) @@ -48,4 +48,4 @@ namespace EOM.TSHotelManagement.Domain public string? RoleDescription { get; set; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs b/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs index 3c0b45c..38a7378 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/RolePermission.cs @@ -1,11 +1,11 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { /// /// 角色权限关联表 (Role-Permission Mapping) /// [SugarTable("role_permission", "角色权限关联表 (Role-Permission Mapping)")] - public class RolePermission : BaseEntity + public class RolePermission : AuditEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/SupervisionStatistics.cs b/EOM.TSHotelManagement.Domain/SystemManagement/SupervisionStatistics.cs index 6359409..3bd6c0e 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/SupervisionStatistics.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/SupervisionStatistics.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 监管统计信息表 (Supervision Statistics) /// [SugarTable("supervision_statistics", "监管统计信息表 (Supervision Statistics)")] - public class SupervisionStatistics : BaseEntity + public class SupervisionStatistics : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/SystemInformation.cs b/EOM.TSHotelManagement.Domain/SystemManagement/SystemInformation.cs deleted file mode 100644 index ec4876b..0000000 --- a/EOM.TSHotelManagement.Domain/SystemManagement/SystemInformation.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - *模块说明:系统信息静态类 - */ -using SqlSugar; - -namespace EOM.TSHotelManagement.Domain -{ - /// - /// 系统信息 (System Information) - /// - [SugarTable("app_config_base", "系统信息 (System Information)", true)] - public class SystemInformation - { - /// - /// 编号 (ID) - /// - [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "编号 (ID)")] - public int Id { get; set; } - - /// - /// 地址编号 (URL Number) - /// - [SugarColumn(ColumnName = "url_no", IsPrimaryKey = true, ColumnDescription = "地址编号 (URL Number)")] - public int UrlNumber { get; set; } - - /// - /// 地址 (URL Address) - /// - [SugarColumn(ColumnName = "url_addr", Length = 256, ColumnDescription = "地址 (URL Address)")] - public string UrlAddress { get; set; } - } -} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorAuth.cs b/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorAuth.cs index a87512d..db92253 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorAuth.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorAuth.cs @@ -6,7 +6,7 @@ namespace EOM.TSHotelManagement.Domain [SugarIndex("ux_2fa_employee_pk", nameof(EmployeePk), OrderByType.Asc, true)] [SugarIndex("ux_2fa_administrator_pk", nameof(AdministratorPk), OrderByType.Asc, true)] [SugarIndex("ux_2fa_customer_account_pk", nameof(CustomerAccountPk), OrderByType.Asc, true)] - public class TwoFactorAuth : BaseEntity + public class TwoFactorAuth : SoftDeleteEntity { [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "索引ID")] public int Id { get; set; } diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorRecoveryCode.cs b/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorRecoveryCode.cs index 108125a..5ddc562 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorRecoveryCode.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/TwoFactorRecoveryCode.cs @@ -5,7 +5,7 @@ namespace EOM.TSHotelManagement.Domain [SugarTable("two_factor_recovery_code", "2FA recovery codes")] [SugarIndex("idx_2fa_recovery_auth", nameof(TwoFactorAuthPk), OrderByType.Asc)] [SugarIndex("idx_2fa_recovery_used", nameof(IsUsed), OrderByType.Asc)] - public class TwoFactorRecoveryCode : BaseEntity + public class TwoFactorRecoveryCode : SoftDeleteEntity { [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "Primary key")] public int Id { get; set; } diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/UserRole.cs b/EOM.TSHotelManagement.Domain/SystemManagement/UserRole.cs index 11e2f36..df93d59 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/UserRole.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/UserRole.cs @@ -1,11 +1,11 @@ -using SqlSugar; +using SqlSugar; namespace EOM.TSHotelManagement.Domain { // /// 用户角色关联表 (User-Role Mapping) /// [SugarTable("user_role", "用户角色关联表 (User-Role Mapping)")] - public class UserRole : BaseEntity + public class UserRole : AuditEntity { /// /// 编号 (ID) @@ -40,4 +40,4 @@ namespace EOM.TSHotelManagement.Domain public string UserNumber { get; set; } = null!; } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/VipLevelRule.cs b/EOM.TSHotelManagement.Domain/SystemManagement/VipLevelRule.cs index 31b9546..87d5c61 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/VipLevelRule.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/VipLevelRule.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -30,7 +30,7 @@ namespace EOM.TSHotelManagement.Domain /// 会员等级规则表 (VIP Level Rules) /// [SugarTable("vip_rule", "会员等级规则配置表 (VIP Level Rule Configuration)")] - public class VipLevelRule : BaseEntity + public class VipLevelRule : SoftDeleteEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Util/OperationLog.cs b/EOM.TSHotelManagement.Domain/Util/OperationLog.cs index 995bfba..01be2b3 100644 --- a/EOM.TSHotelManagement.Domain/Util/OperationLog.cs +++ b/EOM.TSHotelManagement.Domain/Util/OperationLog.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 操作日志表 (Operation Log) /// [SugarTable("operation_log", "操作日志表 (Operation Log)")] - public class OperationLog : BaseEntity + public class OperationLog : AuditEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Domain/Util/RequestLog.cs b/EOM.TSHotelManagement.Domain/Util/RequestLog.cs index c253165..03c2ad8 100644 --- a/EOM.TSHotelManagement.Domain/Util/RequestLog.cs +++ b/EOM.TSHotelManagement.Domain/Util/RequestLog.cs @@ -1,10 +1,10 @@ -using SqlSugar; +using SqlSugar; using System; namespace EOM.TSHotelManagement.Domain { [SugarTable("request_log", "请求日志表 (Request Log)")] - public class RequestLog : BaseEntity + public class RequestLog : AuditEntity { /// /// 编号 (ID) diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 3ef761a..088d409 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -65,7 +65,6 @@ namespace EOM.TSHotelManagement.Migration typeof(SellThing), typeof(Spend), typeof(SupervisionStatistics), - typeof(SystemInformation), typeof(UserRole), typeof(VipLevelRule), typeof(RequestLog), @@ -625,11 +624,6 @@ namespace EOM.TSHotelManagement.Migration DataInsUsr = "System", DataInsDate = DateTime.Now }, - new SystemInformation - { - UrlNumber = 1, - UrlAddress = "https://gitee.com/java-and-net/TopskyHotelManagerSystem/releases", - }, new PromotionContent { PromotionContentNumber = "PC-000001", @@ -668,260 +662,260 @@ namespace EOM.TSHotelManagement.Migration // Basic (基础信息管理) // 部门 - new Permission { PermissionNumber = "department.create", PermissionName = "新增部门", Module = "basic", Description = "基础信息-部门-新增", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.delete", PermissionName = "删除部门", Module = "basic", Description = "基础信息-部门-删除", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.update", PermissionName = "更新部门", Module = "basic", Description = "基础信息-部门-更新", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "department.view", PermissionName = "查询部门列表", Module = "basic", Description = "基础信息-部门-查询列表", MenuKey = "department", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.create", PermissionName = "新增部门", Module = "basic", Description = "基础信息-部门-新增", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.delete", PermissionName = "删除部门", Module = "basic", Description = "基础信息-部门-删除", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.update", PermissionName = "更新部门", Module = "basic", Description = "基础信息-部门-更新", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.view", PermissionName = "查询部门列表", Module = "basic", Description = "基础信息-部门-查询列表", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 民族 - new Permission { PermissionNumber = "nation.create", PermissionName = "新增民族", Module = "basic", Description = "基础信息-民族-新增", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.delete", PermissionName = "删除民族", Module = "basic", Description = "基础信息-民族-删除", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.update", PermissionName = "更新民族", Module = "basic", Description = "基础信息-民族-更新", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "nation.view", PermissionName = "查询民族列表", Module = "basic", Description = "基础信息-民族-查询列表", MenuKey = "nation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.create", PermissionName = "新增民族", Module = "basic", Description = "基础信息-民族-新增", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.delete", PermissionName = "删除民族", Module = "basic", Description = "基础信息-民族-删除", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.update", PermissionName = "更新民族", Module = "basic", Description = "基础信息-民族-更新", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.view", PermissionName = "查询民族列表", Module = "basic", Description = "基础信息-民族-查询列表", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 证件类型 - new Permission { PermissionNumber = "passport.create", PermissionName = "新增证件类型", Module = "basic", Description = "基础信息-证件类型-新增", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.delete", PermissionName = "删除证件类型", Module = "basic", Description = "基础信息-证件类型-删除", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.update", PermissionName = "更新证件类型", Module = "basic", Description = "基础信息-证件类型-更新", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "passport.view", PermissionName = "查询证件类型列表", Module = "basic", Description = "基础信息-证件类型-查询列表", MenuKey = "passport", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.create", PermissionName = "新增证件类型", Module = "basic", Description = "基础信息-证件类型-新增", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.delete", PermissionName = "删除证件类型", Module = "basic", Description = "基础信息-证件类型-删除", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.update", PermissionName = "更新证件类型", Module = "basic", Description = "基础信息-证件类型-更新", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.view", PermissionName = "查询证件类型列表", Module = "basic", Description = "基础信息-证件类型-查询列表", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 职位 - new Permission { PermissionNumber = "position.create", PermissionName = "新增职位", Module = "basic", Description = "基础信息-职位-新增", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.delete", PermissionName = "删除职位", Module = "basic", Description = "基础信息-职位-删除", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.update", PermissionName = "更新职位", Module = "basic", Description = "基础信息-职位-更新", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "position.view", PermissionName = "查询职位列表", Module = "basic", Description = "基础信息-职位-查询列表", MenuKey = "position", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.create", PermissionName = "新增职位", Module = "basic", Description = "基础信息-职位-新增", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.delete", PermissionName = "删除职位", Module = "basic", Description = "基础信息-职位-删除", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.update", PermissionName = "更新职位", Module = "basic", Description = "基础信息-职位-更新", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.view", PermissionName = "查询职位列表", Module = "basic", Description = "基础信息-职位-查询列表", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 学历 - new Permission { PermissionNumber = "qualification.create", PermissionName = "新增学历", Module = "basic", Description = "基础信息-学历-新增", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.delete", PermissionName = "删除学历", Module = "basic", Description = "基础信息-学历-删除", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.update", PermissionName = "更新学历", Module = "basic", Description = "基础信息-学历-更新", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "qualification.view", PermissionName = "查询学历列表", Module = "basic", Description = "基础信息-学历-查询列表", MenuKey = "qualification", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.create", PermissionName = "新增学历", Module = "basic", Description = "基础信息-学历-新增", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.delete", PermissionName = "删除学历", Module = "basic", Description = "基础信息-学历-删除", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.update", PermissionName = "更新学历", Module = "basic", Description = "基础信息-学历-更新", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.view", PermissionName = "查询学历列表", Module = "basic", Description = "基础信息-学历-查询列表", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 公告类型 - new Permission { PermissionNumber = "noticetype.create", PermissionName = "添加公告类型", Module = "basic", Description = "添加公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.delete", PermissionName = "删除公告类型", Module = "basic", Description = "删除公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.update", PermissionName = "更新公告类型", Module = "basic", Description = "更新公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "noticetype.view", PermissionName = "查询所有公告类型", Module = "basic", Description = "查询所有公告类型", MenuKey = "noticetype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.create", PermissionName = "添加公告类型", Module = "basic", Description = "添加公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.delete", PermissionName = "删除公告类型", Module = "basic", Description = "删除公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.update", PermissionName = "更新公告类型", Module = "basic", Description = "更新公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.view", PermissionName = "查询所有公告类型", Module = "basic", Description = "查询所有公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 宣传联动内容 - new Permission { PermissionNumber = "promotioncontent.apc", PermissionName = "添加宣传联动内容", Module = "basic", Description = "添加宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.dpc", PermissionName = "删除宣传联动内容", Module = "basic", Description = "删除宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.spca", PermissionName = "查询所有宣传联动内容", Module = "basic", Description = "查询所有宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.spcs", PermissionName = "查询所有宣传联动内容(跑马灯)", Module = "basic", Description = "查询所有宣传联动内容(跑马灯)", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "promotioncontent.upc", PermissionName = "更新宣传联动内容", Module = "basic", Description = "更新宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.apc", PermissionName = "添加宣传联动内容", Module = "basic", Description = "添加宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.dpc", PermissionName = "删除宣传联动内容", Module = "basic", Description = "删除宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.spca", PermissionName = "查询所有宣传联动内容", Module = "basic", Description = "查询所有宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.spcs", PermissionName = "查询所有宣传联动内容(跑马灯)", Module = "basic", Description = "查询所有宣传联动内容(跑马灯)", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.upc", PermissionName = "更新宣传联动内容", Module = "basic", Description = "更新宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Finance (财务信息管理) // 资产信息管理 - new Permission { PermissionNumber = "internalfinance.aai", PermissionName = "添加资产信息", Module = "internalfinance", Description = "添加资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "internalfinance.dai", PermissionName = "删除资产信息", Module = "internalfinance", Description = "删除资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "internalfinance.saia", PermissionName = "查询资产信息", Module = "internalfinance", Description = "查询资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "internalfinance.uai", PermissionName = "更新资产信息", Module = "internalfinance", Description = "更新资产信息", MenuKey = "internalfinance", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "internalfinance.aai", PermissionName = "添加资产信息", Module = "internalfinance", Description = "添加资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "internalfinance.dai", PermissionName = "删除资产信息", Module = "internalfinance", Description = "删除资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "internalfinance.saia", PermissionName = "查询资产信息", Module = "internalfinance", Description = "查询资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "internalfinance.uai", PermissionName = "更新资产信息", Module = "internalfinance", Description = "更新资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Nav Bar (导航栏管理) // 导航控件管理 - new Permission { PermissionNumber = "navbar.addnavbar", PermissionName = "添加导航控件", Module = "client", Description = "添加导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.dn", PermissionName = "删除导航控件", Module = "client", Description = "删除导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.navbarlist", PermissionName = "导航控件列表", Module = "client", Description = "导航控件列表", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "navbar.un", PermissionName = "更新导航控件", Module = "client", Description = "更新导航控件", MenuKey = "navbar", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.addnavbar", PermissionName = "添加导航控件", Module = "client", Description = "添加导航控件", MenuKey = "navbar", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.dn", PermissionName = "删除导航控件", Module = "client", Description = "删除导航控件", MenuKey = "navbar", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.navbarlist", PermissionName = "导航控件列表", Module = "client", Description = "导航控件列表", MenuKey = "navbar", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "navbar.un", PermissionName = "更新导航控件", Module = "client", Description = "更新导航控件", MenuKey = "navbar", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Hydroelectricity (水电信息管理) // 水电费信息管理 - new Permission { PermissionNumber = "hydroelectricinformation.demi", PermissionName = "删除水电费信息", Module = "hydroelectricity", Description = "删除水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.iemi", PermissionName = "添加水电费信息", Module = "hydroelectricity", Description = "添加水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.semi", PermissionName = "查询水电费信息", Module = "hydroelectricity", Description = "查询水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "hydroelectricinformation.uemi", PermissionName = "修改水电费信息", Module = "hydroelectricity", Description = "修改水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.demi", PermissionName = "删除水电费信息", Module = "hydroelectricity", Description = "删除水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.iemi", PermissionName = "添加水电费信息", Module = "hydroelectricity", Description = "添加水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.semi", PermissionName = "查询水电费信息", Module = "hydroelectricity", Description = "查询水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.uemi", PermissionName = "修改水电费信息", Module = "hydroelectricity", Description = "修改水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Supervision (监管统计管理) // 监管统计信息管理 - new Permission { PermissionNumber = "supervisioninfo.dss", PermissionName = "删除监管统计信息", Module = "supervision", Description = "删除监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.iss", PermissionName = "插入监管统计信息", Module = "supervision", Description = "插入监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.sssa", PermissionName = "查询所有监管统计信息", Module = "supervision", Description = "查询所有监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "supervisioninfo.uss", PermissionName = "更新监管统计信息", Module = "supervision", Description = "更新监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.dss", PermissionName = "删除监管统计信息", Module = "supervision", Description = "删除监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.iss", PermissionName = "插入监管统计信息", Module = "supervision", Description = "插入监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.sssa", PermissionName = "查询所有监管统计信息", Module = "supervision", Description = "查询所有监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.uss", PermissionName = "更新监管统计信息", Module = "supervision", Description = "更新监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Room information (客房信息管理) // 房间管理 - new Permission { PermissionNumber = "roommap.view", PermissionName = "房态图-查看", Module = "room", Description = "房态图一览-查看", MenuKey = "roommap", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.crbr", PermissionName = "根据预约信息办理入住", Module = "room", Description = "根据预约信息办理入住", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.cr", PermissionName = "退房操作", Module = "room", Description = "退房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.dbrn", PermissionName = "根据房间编号查询截止到今天住了多少天", Module = "room", Description = "根据房间编号查询截止到今天住了多少天", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.deleteroom", PermissionName = "删除房间", Module = "room", Description = "删除房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.insertroom", PermissionName = "添加房间", Module = "room", Description = "添加房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.scura", PermissionName = "根据房间状态来查询可使用的房间", Module = "room", Description = "根据房间状态来查询可使用的房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.scurabrs", PermissionName = "查询可入住房间数量", Module = "room", Description = "查询可入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sfrabrs", PermissionName = "查询维修房数量", Module = "room", Description = "查询维修房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sncrabrs", PermissionName = "查询脏房数量", Module = "room", Description = "查询脏房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.snurabrs", PermissionName = "查询已入住房间数量", Module = "room", Description = "查询已入住房间数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srrabrs", PermissionName = "查询预约房数量", Module = "room", Description = "查询预约房数量", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.sra", PermissionName = "获取所有房间信息", Module = "room", Description = "获取所有房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrn", PermissionName = "根据房间编号查询房间信息", Module = "room", Description = "根据房间编号查询房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrp", PermissionName = "根据房间编号查询房间价格", Module = "room", Description = "根据房间编号查询房间价格", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbrs", PermissionName = "根据房间状态获取相应状态的房间信息", Module = "room", Description = "根据房间状态获取相应状态的房间信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.srbtn", PermissionName = "获取房间分区的信息", Module = "room", Description = "获取房间分区的信息", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.tr", PermissionName = "转房操作", Module = "room", Description = "转房操作", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.updateroom", PermissionName = "更新房间", Module = "room", Description = "更新房间", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.uri", PermissionName = "根据房间编号修改房间信息(入住)", Module = "room", Description = "根据房间编号修改房间信息(入住)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.uriwr", PermissionName = "根据房间编号修改房间信息(预约)", Module = "room", Description = "根据房间编号修改房间信息(预约)", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roommanagement.ursbrn", PermissionName = "根据房间编号更改房间状态", Module = "room", Description = "根据房间编号更改房间状态", MenuKey = "roommanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommap.view", PermissionName = "房态图-查看", Module = "room", Description = "房态图一览-查看", MenuKey = "roommap", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.crbr", PermissionName = "根据预约信息办理入住", Module = "room", Description = "根据预约信息办理入住", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.cr", PermissionName = "退房操作", Module = "room", Description = "退房操作", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.dbrn", PermissionName = "根据房间编号查询截止到今天住了多少天", Module = "room", Description = "根据房间编号查询截止到今天住了多少天", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.deleteroom", PermissionName = "删除房间", Module = "room", Description = "删除房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.insertroom", PermissionName = "添加房间", Module = "room", Description = "添加房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.scura", PermissionName = "根据房间状态来查询可使用的房间", Module = "room", Description = "根据房间状态来查询可使用的房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.scurabrs", PermissionName = "查询可入住房间数量", Module = "room", Description = "查询可入住房间数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sfrabrs", PermissionName = "查询维修房数量", Module = "room", Description = "查询维修房数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sncrabrs", PermissionName = "查询脏房数量", Module = "room", Description = "查询脏房数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.snurabrs", PermissionName = "查询已入住房间数量", Module = "room", Description = "查询已入住房间数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srrabrs", PermissionName = "查询预约房数量", Module = "room", Description = "查询预约房数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.sra", PermissionName = "获取所有房间信息", Module = "room", Description = "获取所有房间信息", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrn", PermissionName = "根据房间编号查询房间信息", Module = "room", Description = "根据房间编号查询房间信息", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrp", PermissionName = "根据房间编号查询房间价格", Module = "room", Description = "根据房间编号查询房间价格", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbrs", PermissionName = "根据房间状态获取相应状态的房间信息", Module = "room", Description = "根据房间状态获取相应状态的房间信息", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.srbtn", PermissionName = "获取房间分区的信息", Module = "room", Description = "获取房间分区的信息", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.tr", PermissionName = "转房操作", Module = "room", Description = "转房操作", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.updateroom", PermissionName = "更新房间", Module = "room", Description = "更新房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.uri", PermissionName = "根据房间编号修改房间信息(入住)", Module = "room", Description = "根据房间编号修改房间信息(入住)", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.uriwr", PermissionName = "根据房间编号修改房间信息(预约)", Module = "room", Description = "根据房间编号修改房间信息(预约)", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.ursbrn", PermissionName = "根据房间编号更改房间状态", Module = "room", Description = "根据房间编号更改房间状态", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 房间配置管理 - new Permission { PermissionNumber = "roomconfig.drt", PermissionName = "删除房间配置", Module = "room", Description = "删除房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.irt", PermissionName = "添加房间配置", Module = "room", Description = "添加房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.srtbrn", PermissionName = "根据房间编号查询房间类型名称", Module = "room", Description = "根据房间编号查询房间类型名称", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.srta", PermissionName = "获取所有房间类型", Module = "room", Description = "获取所有房间类型", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "roomconfig.urt", PermissionName = "更新房间配置", Module = "room", Description = "更新房间配置", MenuKey = "roomconfig", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.drt", PermissionName = "删除房间配置", Module = "room", Description = "删除房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.irt", PermissionName = "添加房间配置", Module = "room", Description = "添加房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.srtbrn", PermissionName = "根据房间编号查询房间类型名称", Module = "room", Description = "根据房间编号查询房间类型名称", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.srta", PermissionName = "获取所有房间类型", Module = "room", Description = "获取所有房间类型", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.urt", PermissionName = "更新房间配置", Module = "room", Description = "更新房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 预约信息管理 - new Permission { PermissionNumber = "resermanagement.dri", PermissionName = "删除预约信息", Module = "room", Description = "删除预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.iri", PermissionName = "添加预约信息", Module = "room", Description = "添加预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.sra", PermissionName = "获取所有预约信息", Module = "room", Description = "获取所有预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.sribrn", PermissionName = "根据房间编号获取预约信息", Module = "room", Description = "根据房间编号获取预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.srta", PermissionName = "查询所有预约类型", Module = "room", Description = "查询所有预约类型", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "resermanagement.uri", PermissionName = "更新预约信息", Module = "room", Description = "更新预约信息", MenuKey = "resermanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.dri", PermissionName = "删除预约信息", Module = "room", Description = "删除预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.iri", PermissionName = "添加预约信息", Module = "room", Description = "添加预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.sra", PermissionName = "获取所有预约信息", Module = "room", Description = "获取所有预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.sribrn", PermissionName = "根据房间编号获取预约信息", Module = "room", Description = "根据房间编号获取预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.srta", PermissionName = "查询所有预约类型", Module = "room", Description = "查询所有预约类型", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.uri", PermissionName = "更新预约信息", Module = "room", Description = "更新预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Customer management (客户管理) // 会员等级规则管理 - new Permission { PermissionNumber = "viplevel.addviprule", PermissionName = "添加会员等级规则", Module = "customer", Description = "添加会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.delviprule", PermissionName = "删除会员等级规则", Module = "customer", Description = "删除会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.svr", PermissionName = "查询会员等级规则", Module = "customer", Description = "查询会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.svrlist", PermissionName = "查询会员等级规则列表", Module = "customer", Description = "查询会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "viplevel.updviprule", PermissionName = "更新会员等级规则", Module = "customer", Description = "更新会员等级规则", MenuKey = "viplevel", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.addviprule", PermissionName = "添加会员等级规则", Module = "customer", Description = "添加会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.delviprule", PermissionName = "删除会员等级规则", Module = "customer", Description = "删除会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.svr", PermissionName = "查询会员等级规则", Module = "customer", Description = "查询会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.svrlist", PermissionName = "查询会员等级规则列表", Module = "customer", Description = "查询会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.updviprule", PermissionName = "更新会员等级规则", Module = "customer", Description = "更新会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户信息 - new Permission { PermissionNumber = "customer.dci", PermissionName = "删除客户信息", Module = "customer", Description = "删除客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.ici", PermissionName = "添加客户信息", Module = "customer", Description = "添加客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.scbi", PermissionName = "查询指定客户信息", Module = "customer", Description = "查询指定客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.scs", PermissionName = "查询所有客户信息", Module = "customer", Description = "查询所有客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.uci", PermissionName = "更新客户信息", Module = "customer", Description = "更新客户信息", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customer.uctbcn", PermissionName = "更新会员等级", Module = "customer", Description = "更新会员等级", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.dci", PermissionName = "删除客户信息", Module = "customer", Description = "删除客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.ici", PermissionName = "添加客户信息", Module = "customer", Description = "添加客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.scbi", PermissionName = "查询指定客户信息", Module = "customer", Description = "查询指定客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.scs", PermissionName = "查询所有客户信息", Module = "customer", Description = "查询所有客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.uci", PermissionName = "更新客户信息", Module = "customer", Description = "更新客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.uctbcn", PermissionName = "更新会员等级", Module = "customer", Description = "更新会员等级", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户消费信息 - new Permission { PermissionNumber = "customerspend.acs", PermissionName = "添加客户消费信息", Module = "customer", Description = "添加客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ssbrn", PermissionName = "查询房间消费信息", Module = "customer", Description = "查询房间消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ssia", PermissionName = "查询所有消费信息", Module = "customer", Description = "查询所有消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.shsia", PermissionName = "查询客户历史消费信息", Module = "customer", Description = "查询客户历史消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.sca", PermissionName = "查询消费总金额", Module = "customer", Description = "查询消费总金额", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.ucs", PermissionName = "撤回客户消费信息", Module = "customer", Description = "撤回客户消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customerspend.usi", PermissionName = "更新消费信息", Module = "customer", Description = "更新消费信息", MenuKey = "customerspend", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.acs", PermissionName = "添加客户消费信息", Module = "customer", Description = "添加客户消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ssbrn", PermissionName = "查询房间消费信息", Module = "customer", Description = "查询房间消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ssia", PermissionName = "查询所有消费信息", Module = "customer", Description = "查询所有消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.shsia", PermissionName = "查询客户历史消费信息", Module = "customer", Description = "查询客户历史消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.sca", PermissionName = "查询消费总金额", Module = "customer", Description = "查询消费总金额", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.ucs", PermissionName = "撤回客户消费信息", Module = "customer", Description = "撤回客户消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.usi", PermissionName = "更新消费信息", Module = "customer", Description = "更新消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户类型 - new Permission { PermissionNumber = "customertype.create", PermissionName = "新增客户类型", Module = "customer", Description = "基础信息-客户类型-新增", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.delete", PermissionName = "删除客户类型", Module = "customer", Description = "基础信息-客户类型-删除", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.update", PermissionName = "更新客户类型", Module = "customer", Description = "基础信息-客户类型-更新", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "customertype.view", PermissionName = "查询客户类型列表", Module = "customer", Description = "基础信息-客户类型-查询列表", MenuKey = "customertype", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.create", PermissionName = "新增客户类型", Module = "customer", Description = "基础信息-客户类型-新增", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.delete", PermissionName = "删除客户类型", Module = "customer", Description = "基础信息-客户类型-删除", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.update", PermissionName = "更新客户类型", Module = "customer", Description = "基础信息-客户类型-更新", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.view", PermissionName = "查询客户类型列表", Module = "customer", Description = "基础信息-客户类型-查询列表", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Human resource (酒店人事管理) // 员工管理 - new Permission { PermissionNumber = "staffmanagement.ae", PermissionName = "添加员工信息", Module = "humanresource", Description = "添加员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.mea", PermissionName = "员工账号禁/启用", Module = "humanresource", Description = "员工账号禁/启用", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.reap", PermissionName = "重置员工账号密码", Module = "humanresource", Description = "重置员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.sea", PermissionName = "获取所有工作人员信息", Module = "humanresource", Description = "获取所有工作人员信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.seibei", PermissionName = "根据登录名称查询员工信息", Module = "humanresource", Description = "根据登录名称查询员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ue", PermissionName = "修改员工信息", Module = "humanresource", Description = "修改员工信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ae", PermissionName = "添加员工信息", Module = "humanresource", Description = "添加员工信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.mea", PermissionName = "员工账号禁/启用", Module = "humanresource", Description = "员工账号禁/启用", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.reap", PermissionName = "重置员工账号密码", Module = "humanresource", Description = "重置员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.sea", PermissionName = "获取所有工作人员信息", Module = "humanresource", Description = "获取所有工作人员信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.seibei", PermissionName = "根据登录名称查询员工信息", Module = "humanresource", Description = "根据登录名称查询员工信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ue", PermissionName = "修改员工信息", Module = "humanresource", Description = "修改员工信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工履历管理 - new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "humanresource", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "humanresource", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "humanresource", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "humanresource", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工打卡管理 - new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "humanresource", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "humanresource", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.acfo", PermissionName = "添加员工打卡数据", Module = "humanresource", Description = "添加员工打卡数据", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.scfobei", PermissionName = "根据员工编号查询其所有的打卡记录", Module = "humanresource", Description = "根据员工编号查询其所有的打卡记录", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "humanresource", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "humanresource", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.acfo", PermissionName = "添加员工打卡数据", Module = "humanresource", Description = "添加员工打卡数据", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.scfobei", PermissionName = "根据员工编号查询其所有的打卡记录", Module = "humanresource", Description = "根据员工编号查询其所有的打卡记录", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工照片管理 - new Permission { PermissionNumber = "staffmanagement.ueap", PermissionName = "修改员工账号密码", Module = "humanresource", Description = "修改员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.uwp", PermissionName = "更新员工照片", Module = "humanresource", Description = "更新员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.dwp", PermissionName = "删除员工照片", Module = "humanresource", Description = "删除员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.iwp", PermissionName = "添加员工照片", Module = "humanresource", Description = "添加员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.ep", PermissionName = "查询员工照片", Module = "humanresource", Description = "查询员工照片", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ueap", PermissionName = "修改员工账号密码", Module = "humanresource", Description = "修改员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.uwp", PermissionName = "更新员工照片", Module = "humanresource", Description = "更新员工照片", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.dwp", PermissionName = "删除员工照片", Module = "humanresource", Description = "删除员工照片", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.iwp", PermissionName = "添加员工照片", Module = "humanresource", Description = "添加员工照片", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.ep", PermissionName = "查询员工照片", Module = "humanresource", Description = "查询员工照片", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工两步验证管理 - new Permission { PermissionNumber = "staffmanagement.dtf", PermissionName = "关闭当前员工账号 2FA", Module = "humanresource", Description = "关闭当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.etf", PermissionName = "启用当前员工账号 2FA", Module = "humanresource", Description = "启用当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.gtfs", PermissionName = "生成当前员工账号的 2FA 绑定信息", Module = "humanresource", Description = "生成当前员工账号的 2FA 绑定信息", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.gtfse", PermissionName = "获取当前员工账号的 2FA 状态", Module = "humanresource", Description = "获取当前员工账号的 2FA 状态", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.rtfrc", PermissionName = "重置当前员工账号恢复备用码", Module = "humanresource", Description = "重置当前员工账号恢复备用码", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.dtf", PermissionName = "关闭当前员工账号 2FA", Module = "humanresource", Description = "关闭当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.etf", PermissionName = "启用当前员工账号 2FA", Module = "humanresource", Description = "启用当前员工账号 2FA", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.gtfs", PermissionName = "生成当前员工账号的 2FA 绑定信息", Module = "humanresource", Description = "生成当前员工账号的 2FA 绑定信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.gtfse", PermissionName = "获取当前员工账号的 2FA 状态", Module = "humanresource", Description = "获取当前员工账号的 2FA 状态", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.rtfrc", PermissionName = "重置当前员工账号恢复备用码", Module = "humanresource", Description = "重置当前员工账号恢复备用码", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Material management (酒店物资管理) // 商品管理 - new Permission { PermissionNumber = "goodsmanagement.dst", PermissionName = "删除商品信息", Module = "material", Description = "删除商品信息", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ist", PermissionName = "添加商品", Module = "material", Description = "添加商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ssta", PermissionName = "查询所有商品", Module = "material", Description = "查询所有商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.sstbnap", PermissionName = "根据商品名称和价格查询商品编号", Module = "material", Description = "根据商品名称和价格查询商品编号", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "goodsmanagement.ust", PermissionName = "修改商品", Module = "material", Description = "修改商品", MenuKey = "goodsmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.dst", PermissionName = "删除商品信息", Module = "material", Description = "删除商品信息", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ist", PermissionName = "添加商品", Module = "material", Description = "添加商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ssta", PermissionName = "查询所有商品", Module = "material", Description = "查询所有商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.sstbnap", PermissionName = "根据商品名称和价格查询商品编号", Module = "material", Description = "根据商品名称和价格查询商品编号", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.ust", PermissionName = "修改商品", Module = "material", Description = "修改商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // Operation management (行为操作管理) // 操作日志 - new Permission { PermissionNumber = "operationlog.delete", PermissionName = "删除时间范围的操作日志", Module = "operation", Description = "删除时间范围的操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "operationlog.view", PermissionName = "查询所有操作日志", Module = "operation", Description = "查询所有操作日志", MenuKey = "operationlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "operationlog.delete", PermissionName = "删除时间范围的操作日志", Module = "operation", Description = "删除时间范围的操作日志", MenuKey = "operationlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "operationlog.view", PermissionName = "查询所有操作日志", Module = "operation", Description = "查询所有操作日志", MenuKey = "operationlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 请求日志 - new Permission { PermissionNumber = "requestlog.delete", PermissionName = "删除时间范围的请求日志", Module = "operation", Description = "删除时间范围的请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "requestlog.view", PermissionName = "查询所有请求日志", Module = "operation", Description = "查询所有请求日志", MenuKey = "requestlog", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "requestlog.delete", PermissionName = "删除时间范围的请求日志", Module = "operation", Description = "删除时间范围的请求日志", MenuKey = "requestlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "requestlog.view", PermissionName = "查询所有请求日志", Module = "operation", Description = "查询所有请求日志", MenuKey = "requestlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // System management (系统管理) // 管理员管理 - new Permission { PermissionNumber = "system:admin:addadmin", PermissionName = "添加管理员", Module = "system", Description = "添加管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:deladmin", PermissionName = "删除管理员", Module = "system", Description = "删除管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:gaal", PermissionName = "获取所有管理员列表", Module = "system", Description = "获取所有管理员列表", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:updadmin", PermissionName = "更新管理员", Module = "system", Description = "更新管理员", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:addadmin", PermissionName = "添加管理员", Module = "system", Description = "添加管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:deladmin", PermissionName = "删除管理员", Module = "system", Description = "删除管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:gaal", PermissionName = "获取所有管理员列表", Module = "system", Description = "获取所有管理员列表", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:updadmin", PermissionName = "更新管理员", Module = "system", Description = "更新管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 管理员类型管理 - new Permission { PermissionNumber = "system:admintype:aat", PermissionName = "添加管理员类型", Module = "system", Description = "添加管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admintype:dat", PermissionName = "删除管理员类型", Module = "system", Description = "删除管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admintype:gaat", PermissionName = "获取所有管理员类型", Module = "system", Description = "获取所有管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admintype:uat", PermissionName = "更新管理员类型", Module = "system", Description = "更新管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admintype:aat", PermissionName = "添加管理员类型", Module = "system", Description = "添加管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admintype:dat", PermissionName = "删除管理员类型", Module = "system", Description = "删除管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admintype:gaat", PermissionName = "获取所有管理员类型", Module = "system", Description = "获取所有管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admintype:uat", PermissionName = "更新管理员类型", Module = "system", Description = "更新管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 管理员两步验证管理 - new Permission { PermissionNumber = "system:admin:gtfs", PermissionName = "获取当前管理员账号的 2FA 状态", Module = "system", Description = "获取当前管理员账号的 2FA 状态", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:dtf", PermissionName = "关闭当前管理员账号 2FA", Module = "system", Description = "关闭当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:etf", PermissionName = "启用当前管理员账号 2FA", Module = "system", Description = "启用当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:gtfsu", PermissionName = "生成当前管理员账号的 2FA 绑定信息", Module = "system", Description = "生成当前管理员账号的 2FA 绑定信息", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:admin:rtfrc", PermissionName = "重置当前管理员账号恢复备用码", Module = "system", Description = "重置当前管理员账号恢复备用码", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:gtfs", PermissionName = "获取当前管理员账号的 2FA 状态", Module = "system", Description = "获取当前管理员账号的 2FA 状态", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:dtf", PermissionName = "关闭当前管理员账号 2FA", Module = "system", Description = "关闭当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:etf", PermissionName = "启用当前管理员账号 2FA", Module = "system", Description = "启用当前管理员账号 2FA", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:gtfsu", PermissionName = "生成当前管理员账号的 2FA 绑定信息", Module = "system", Description = "生成当前管理员账号的 2FA 绑定信息", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:rtfrc", PermissionName = "重置当前管理员账号恢复备用码", Module = "system", Description = "重置当前管理员账号恢复备用码", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 角色管理 - new Permission { PermissionNumber = "system:role:aru", PermissionName = "为角色分配管理员(全量覆盖)", Module = "system", Description = "为角色分配管理员(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:deleterole", PermissionName = "删除角色", Module = "system", Description = "删除角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:grp", PermissionName = "为角色授予权限(全量覆盖)", Module = "system", Description = "为角色授予权限(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:insertrole", PermissionName = "添加角色", Module = "system", Description = "添加角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:rrp", PermissionName = "读取指定角色已授予的权限编码集合", Module = "system", Description = "读取指定角色已授予的权限编码集合", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:rrg", PermissionName = "读取指定角色菜单和权限授权(菜单与权限独立)", Module = "system", Description = "读取指定角色菜单和权限授权(菜单与权限独立)", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:rru", PermissionName = "读取隶属于指定角色的管理员用户编码集合", Module = "system", Description = "读取隶属于指定角色的管理员用户编码集合", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:srl", PermissionName = "查询角色列表", Module = "system", Description = "查询角色列表", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:role:updaterole", PermissionName = "更新角色", Module = "system", Description = "更新角色", MenuKey = "rolemanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:aru", PermissionName = "为角色分配管理员(全量覆盖)", Module = "system", Description = "为角色分配管理员(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:deleterole", PermissionName = "删除角色", Module = "system", Description = "删除角色", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:grp", PermissionName = "为角色授予权限(全量覆盖)", Module = "system", Description = "为角色授予权限(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:insertrole", PermissionName = "添加角色", Module = "system", Description = "添加角色", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:rrp", PermissionName = "读取指定角色已授予的权限编码集合", Module = "system", Description = "读取指定角色已授予的权限编码集合", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:rrg", PermissionName = "读取指定角色菜单和权限授权(菜单与权限独立)", Module = "system", Description = "读取指定角色菜单和权限授权(菜单与权限独立)", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:rru", PermissionName = "读取隶属于指定角色的管理员用户编码集合", Module = "system", Description = "读取隶属于指定角色的管理员用户编码集合", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:srl", PermissionName = "查询角色列表", Module = "system", Description = "查询角色列表", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:updaterole", PermissionName = "更新角色", Module = "system", Description = "更新角色", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 菜单管理 - new Permission { PermissionNumber = "menumanagement.bma", PermissionName = "构建菜单树", Module = "system", Description = "构建菜单树", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.deletemenu", PermissionName = "删除菜单", Module = "system", Description = "删除菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.insertmenu", PermissionName = "插入菜单", Module = "system", Description = "插入菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.sma", PermissionName = "查询所有菜单信息", Module = "system", Description = "查询所有菜单信息", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "menumanagement.updatemenu", PermissionName = "更新菜单", Module = "system", Description = "更新菜单", MenuKey = "menumanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.bma", PermissionName = "构建菜单树", Module = "system", Description = "构建菜单树", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.deletemenu", PermissionName = "删除菜单", Module = "system", Description = "删除菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.insertmenu", PermissionName = "插入菜单", Module = "system", Description = "插入菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.sma", PermissionName = "查询所有菜单信息", Module = "system", Description = "查询所有菜单信息", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.updatemenu", PermissionName = "更新菜单", Module = "system", Description = "更新菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 主页 // 仪表盘 - new Permission { PermissionNumber = "dashboard.view", PermissionName = "仪表盘-查看", Module = "home", Description = "仪表盘-查看", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "home.view", PermissionName = "首页-查看", Module = "home", Description = "首页-查看", MenuKey = "home", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.bs", PermissionName = "获取业务统计信息", Module = "dashboard", Description = "获取业务统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.hrs", PermissionName = "获取人事统计信息", Module = "dashboard", Description = "获取人事统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.ls", PermissionName = "获取后勤统计信息", Module = "dashboard", Description = "获取后勤统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "dashboard.rs", PermissionName = "获取房间统计信息", Module = "dashboard", Description = "获取房间统计信息", MenuKey = "dashboard", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.view", PermissionName = "仪表盘-查看", Module = "home", Description = "仪表盘-查看", MenuKey = "dashboard", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "home.view", PermissionName = "首页-查看", Module = "home", Description = "首页-查看", MenuKey = "home", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.bs", PermissionName = "获取业务统计信息", Module = "dashboard", Description = "获取业务统计信息", MenuKey = "dashboard", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.hrs", PermissionName = "获取人事统计信息", Module = "dashboard", Description = "获取人事统计信息", MenuKey = "dashboard", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.ls", PermissionName = "获取后勤统计信息", Module = "dashboard", Description = "获取后勤统计信息", MenuKey = "dashboard", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "dashboard.rs", PermissionName = "获取房间统计信息", Module = "dashboard", Description = "获取房间统计信息", MenuKey = "dashboard", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 权限分配 // 管理员-角色权限管理(网页端) - new Permission { PermissionNumber = "system:user:admin.rudp", PermissionName = "读取指定用户的“直接权限”", Module = "system", Description = "读取指定用户的“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:admin.rurp", PermissionName = "读取指定用户的“角色-权限”明细", Module = "system", Description = "读取指定用户的“角色-权限”明细", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:admin.rur", PermissionName = "读取指定用户已分配的角色编码集合", Module = "system", Description = "读取指定用户已分配的角色编码集合", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:admin:aup", PermissionName = "为指定用户分配“直接权限”", Module = "system", Description = "为指定用户分配“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:admin:aur", PermissionName = "为用户分配角色(全量覆盖)", Module = "system", Description = "为用户分配角色(全量覆盖)", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:assign.spl", PermissionName = "查询权限列表(支持条件过滤与分页/忽略分页)", Module = "system", Description = "查询权限列表(支持条件过滤与分页/忽略分页)", MenuKey = "administratormanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:admin.rudp", PermissionName = "读取指定用户的“直接权限”", Module = "system", Description = "读取指定用户的“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:admin.rurp", PermissionName = "读取指定用户的“角色-权限”明细", Module = "system", Description = "读取指定用户的“角色-权限”明细", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:admin.rur", PermissionName = "读取指定用户已分配的角色编码集合", Module = "system", Description = "读取指定用户已分配的角色编码集合", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:admin:aup", PermissionName = "为指定用户分配“直接权限”", Module = "system", Description = "为指定用户分配“直接权限”", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:admin:aur", PermissionName = "为用户分配角色(全量覆盖)", Module = "system", Description = "为用户分配角色(全量覆盖)", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:assign.spl", PermissionName = "查询权限列表(支持条件过滤与分页/忽略分页)", Module = "system", Description = "查询权限列表(支持条件过滤与分页/忽略分页)", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户-角色权限管理(网页端) - new Permission { PermissionNumber = "system:user:customer.rudp", PermissionName = "读取客户“直接权限”权限编码集合", Module = "system", Description = "读取客户“直接权限”权限编码集合", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:customer.rurp", PermissionName = "读取客户“角色-权限”明细", Module = "system", Description = "读取客户“角色-权限”明细", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:customer.rur", PermissionName = "读取客户已分配的角色编码集合", Module = "system", Description = "读取客户已分配的角色编码集合", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:customer:aup", PermissionName = "为客户分配“直接权限”", Module = "system", Description = "为客户分配“直接权限”", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:customer:aur", PermissionName = "为客户分配角色(全量覆盖)", Module = "system", Description = "为客户分配角色(全量覆盖)", MenuKey = "customer", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:customer.rudp", PermissionName = "读取客户“直接权限”权限编码集合", Module = "system", Description = "读取客户“直接权限”权限编码集合", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:customer.rurp", PermissionName = "读取客户“角色-权限”明细", Module = "system", Description = "读取客户“角色-权限”明细", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:customer.rur", PermissionName = "读取客户已分配的角色编码集合", Module = "system", Description = "读取客户已分配的角色编码集合", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:customer:aup", PermissionName = "为客户分配“直接权限”", Module = "system", Description = "为客户分配“直接权限”", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:customer:aur", PermissionName = "为客户分配角色(全量覆盖)", Module = "system", Description = "为客户分配角色(全量覆盖)", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工-角色权限管理(网页端) - new Permission { PermissionNumber = "system:user:employee.rudp", PermissionName = "读取员工“直接权限”权限编码集合", Module = "system", Description = "读取员工“直接权限”权限编码集合", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:employee.rurp", PermissionName = "读取员工“角色-权限”明细", Module = "system", Description = "读取员工“角色-权限”明细", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:employee.rur", PermissionName = "读取员工已分配的角色编码集合", Module = "system", Description = "读取员工已分配的角色编码集合", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:employee:aup", PermissionName = "为员工分配“直接权限”", Module = "system", Description = "为员工分配“直接权限”", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "system:user:employee:aur", PermissionName = "为员工分配角色(全量覆盖)", Module = "system", Description = "为员工分配角色(全量覆盖)", MenuKey = "staffmanagement", ParentNumber = null, IsDelete = 0, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:employee.rudp", PermissionName = "读取员工“直接权限”权限编码集合", Module = "system", Description = "读取员工“直接权限”权限编码集合", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:employee.rurp", PermissionName = "读取员工“角色-权限”明细", Module = "system", Description = "读取员工“角色-权限”明细", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:employee.rur", PermissionName = "读取员工已分配的角色编码集合", Module = "system", Description = "读取员工已分配的角色编码集合", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:employee:aup", PermissionName = "为员工分配“直接权限”", Module = "system", Description = "为员工分配“直接权限”", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:user:employee:aur", PermissionName = "为员工分配角色(全量覆盖)", Module = "system", Description = "为员工分配角色(全量覆盖)", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, }; diff --git a/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs b/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs index 80cb10a..dfeb165 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs @@ -1,4 +1,4 @@ -using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; @@ -319,13 +319,12 @@ namespace EOM.TSHotelManagement.Service } // 绑定客户到客户组角色 - if (!userRoleRepository.AsQueryable().Any(ur => ur.UserNumber == customerNumber && ur.RoleNumber == customerRoleNumber && ur.IsDelete != 1)) + if (!userRoleRepository.AsQueryable().Any(ur => ur.UserNumber == customerNumber && ur.RoleNumber == customerRoleNumber)) { userRoleRepository.Insert(new UserRole { UserNumber = customerNumber, RoleNumber = customerRoleNumber, - IsDelete = 0, DataInsUsr = readCustomerAccountInputDto.Account, DataInsDate = DateTime.Now }); diff --git a/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs b/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs index ef10f0c..d5681ce 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs @@ -145,13 +145,12 @@ namespace EOM.TSHotelManagement.Service } // 绑定客户到客户组角色 - if (!userRoleRepository.AsQueryable().Any(ur => ur.UserNumber == customer.CustomerNumber && ur.RoleNumber == customerRoleNumber && ur.IsDelete != 1)) + if (!userRoleRepository.AsQueryable().Any(ur => ur.UserNumber == customer.CustomerNumber && ur.RoleNumber == customerRoleNumber)) { userRoleRepository.Insert(new UserRole { UserNumber = customer.CustomerNumber, RoleNumber = customerRoleNumber, - IsDelete = 0, DataInsUsr = customer.DataInsUsr, DataInsDate = DateTime.Now }); diff --git a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs index e2f02c1..421b42a 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/Permission/CustomerPermissionService.cs @@ -56,15 +56,15 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("User not found", "用户不存在")); } - // 软删除当前用户下所有有效的角色绑定 + // 硬删除当前用户下所有有效的角色绑定 var existing = userRoleRepository.AsQueryable() - .Where(x => x.UserNumber == input.UserNumber && x.IsDelete != 1) - .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber, IsDelete = 1 }) + .Where(x => x.UserNumber == input.UserNumber) + .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber }) .ToList(); foreach (var ur in existing) { - userRoleRepository.SoftDelete(ur); + userRoleRepository.Delete(ur); } // 过滤、去重、忽略空白 @@ -80,8 +80,7 @@ namespace EOM.TSHotelManagement.Service var entity = new UserRole { UserNumber = input.UserNumber, - RoleNumber = role, - IsDelete = 0 + RoleNumber = role }; userRoleRepository.Insert(entity); } @@ -111,7 +110,7 @@ namespace EOM.TSHotelManagement.Service try { var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -161,7 +160,7 @@ namespace EOM.TSHotelManagement.Service { // 1) 用户 -> 角色 var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -186,8 +185,7 @@ namespace EOM.TSHotelManagement.Service // 2) 角色 -> 权限编码(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 - && roleNumbers.Contains(rp.RoleNumber) + .Where(rp => roleNumbers.Contains(rp.RoleNumber) && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) @@ -204,7 +202,7 @@ namespace EOM.TSHotelManagement.Service if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) + .Where(p => permNumbers.Contains(p.PermissionNumber)) .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); @@ -320,7 +318,7 @@ namespace EOM.TSHotelManagement.Service // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() - .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) + .Where(x => x.RoleNumber == userRoleNumber) .ToList(); if (existing.Count > 0) { @@ -338,7 +336,7 @@ namespace EOM.TSHotelManagement.Service { // 仅保留系统中存在的权限码 var validPerms = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && perms.Contains(p.PermissionNumber)) + .Where(p => perms.Contains(p.PermissionNumber)) .Select(p => p.PermissionNumber) .ToList(); @@ -347,22 +345,20 @@ namespace EOM.TSHotelManagement.Service var entity = new RolePermission { RoleNumber = userRoleNumber, - PermissionNumber = pnum, - IsDelete = 0 + PermissionNumber = pnum }; rolePermissionRepository.Insert(entity); } } // 确保用户与专属角色绑定存在 - var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber && ur.IsDelete != 1); + var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber); if (!hasBinding) { userRoleRepository.Insert(new UserRole { UserNumber = input.UserNumber, - RoleNumber = userRoleNumber, - IsDelete = 0 + RoleNumber = userRoleNumber }); } @@ -392,7 +388,7 @@ namespace EOM.TSHotelManagement.Service { var roleNumber = $"R-USER-{userNumber}"; var list = rolePermissionRepository.AsQueryable() - .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == roleNumber) .Select(rp => rp.PermissionNumber) .ToList(); diff --git a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs index 1fb1e46..bfebddc 100644 --- a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs +++ b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -405,7 +405,6 @@ namespace EOM.TSHotelManagement.Service OperationAccount = addCustomerSpendInputDto.WorkerNo, LogLevel = (int)Common.LogLevel.Warning, SoftwareVersion = addCustomerSpendInputDto.SoftwareVersion, - IsDelete = 0, DataInsUsr = addCustomerSpendInputDto.WorkerNo, DataInsDate = Convert.ToDateTime(DateTime.Now) }; diff --git a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs index ae63dff..3ca136e 100644 --- a/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs +++ b/EOM.TSHotelManagement.Service/Employee/Permission/EmployeePermissionService.cs @@ -58,8 +58,8 @@ namespace EOM.TSHotelManagement.Service // 软删除当前用户下所有有效的角色绑定 var existing = userRoleRepository.AsQueryable() - .Where(x => x.UserNumber == input.UserNumber && x.IsDelete != 1) - .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber, IsDelete = 1 }) + .Where(x => x.UserNumber == input.UserNumber) + .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber }) .ToList(); foreach (var ur in existing) @@ -80,8 +80,7 @@ namespace EOM.TSHotelManagement.Service var entity = new UserRole { UserNumber = input.UserNumber, - RoleNumber = role, - IsDelete = 0 + RoleNumber = role }; userRoleRepository.Insert(entity); } @@ -111,7 +110,7 @@ namespace EOM.TSHotelManagement.Service try { var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -161,7 +160,7 @@ namespace EOM.TSHotelManagement.Service { // 1) 用户 -> 角色 var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -186,8 +185,7 @@ namespace EOM.TSHotelManagement.Service // 2) 角色 -> 权限编码(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 - && roleNumbers.Contains(rp.RoleNumber) + .Where(rp => roleNumbers.Contains(rp.RoleNumber) && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) @@ -204,7 +202,7 @@ namespace EOM.TSHotelManagement.Service if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) + .Where(p => permNumbers.Contains(p.PermissionNumber)) .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); @@ -320,7 +318,7 @@ namespace EOM.TSHotelManagement.Service // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() - .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) + .Where(x => x.RoleNumber == userRoleNumber) .ToList(); if (existing.Count > 0) { @@ -338,7 +336,7 @@ namespace EOM.TSHotelManagement.Service { // 仅保留系统中存在的权限码 var validPerms = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && perms.Contains(p.PermissionNumber)) + .Where(p => perms.Contains(p.PermissionNumber)) .Select(p => p.PermissionNumber) .ToList(); @@ -347,22 +345,20 @@ namespace EOM.TSHotelManagement.Service var entity = new RolePermission { RoleNumber = userRoleNumber, - PermissionNumber = pnum, - IsDelete = 0 + PermissionNumber = pnum }; rolePermissionRepository.Insert(entity); } } // 确保用户与专属角色绑定存在 - var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber && ur.IsDelete != 1); + var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber); if (!hasBinding) { userRoleRepository.Insert(new UserRole { UserNumber = input.UserNumber, - RoleNumber = userRoleNumber, - IsDelete = 0 + RoleNumber = userRoleNumber }); } @@ -392,7 +388,7 @@ namespace EOM.TSHotelManagement.Service { var roleNumber = $"R-USER-{userNumber}"; var list = rolePermissionRepository.AsQueryable() - .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == roleNumber) .Select(rp => rp.PermissionNumber) .ToList(); diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs index 159974d..bce0291 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Administrator/AdminService.cs @@ -380,7 +380,7 @@ namespace EOM.TSHotelManagement.Service { if (createAdministratorInputDto.IsSuperAdmin == (int)AdminRole.SuperAdmin) { - var haveSuperAdmin = adminRepository.IsAny(a => a.IsSuperAdmin == 1 && a.IsDelete != 1); + var haveSuperAdmin = adminRepository.IsAny(a => a.IsSuperAdmin == 1); if (haveSuperAdmin) { return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Super Administrator already exists", "超级管理员已存在"), Code = BusinessStatusCode.InternalServerError }; @@ -645,7 +645,7 @@ namespace EOM.TSHotelManagement.Service } // cannot be delete if have administrators - var haveAdmin = adminRepository.IsAny(a => administratorTypes.Select(a => a.TypeId).Contains(a.Type) && a.IsDelete != 1); + var haveAdmin = adminRepository.IsAny(a => administratorTypes.Select(a => a.TypeId).Contains(a.Type)); if (haveAdmin) { return new BaseResponse @@ -681,21 +681,21 @@ namespace EOM.TSHotelManagement.Service try { // 校验用户是否存在且未删除 - var userExists = adminRepository.IsAny(a => a.Number == input.UserNumber && a.IsDelete != 1); + var userExists = adminRepository.IsAny(a => a.Number == input.UserNumber); if (!userExists) { return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("User not found", "用户不存在")); } - // 软删除当前用户下所有有效的角色绑定 + // 硬删除当前用户下所有有效的角色绑定 var existing = userRoleRepository.AsQueryable() - .Where(x => x.UserNumber == input.UserNumber && x.IsDelete != 1) - .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber, IsDelete = 1 }) + .Where(x => x.UserNumber == input.UserNumber) + .Select(x => new UserRole { UserNumber = x.UserNumber, RoleNumber = x.RoleNumber }) .ToList(); foreach (var ur in existing) { - userRoleRepository.SoftDelete(ur); + userRoleRepository.Delete(ur); } // 过滤、去重、忽略空白 @@ -711,8 +711,7 @@ namespace EOM.TSHotelManagement.Service var entity = new UserRole { UserNumber = input.UserNumber, - RoleNumber = role, - IsDelete = 0 + RoleNumber = role }; userRoleRepository.Insert(entity); } @@ -746,7 +745,7 @@ namespace EOM.TSHotelManagement.Service try { var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -799,7 +798,7 @@ namespace EOM.TSHotelManagement.Service { // 1) 用户 -> 角色 var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -824,8 +823,7 @@ namespace EOM.TSHotelManagement.Service // 2) 角色 -> 权限映射(RolePermission) var rolePermList = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 - && roleNumbers.Contains(rp.RoleNumber) + .Where(rp => roleNumbers.Contains(rp.RoleNumber) && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => new { rp.RoleNumber, rp.PermissionNumber, rp.MenuId }) @@ -842,7 +840,7 @@ namespace EOM.TSHotelManagement.Service if (permNumbers.Count > 0) { var info = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && permNumbers.Contains(p.PermissionNumber)) + .Where(p => permNumbers.Contains(p.PermissionNumber)) .Select(p => new { p.PermissionNumber, p.PermissionName }) .ToList(); @@ -936,7 +934,7 @@ namespace EOM.TSHotelManagement.Service try { // 校验用户是否存在且未删除 - var userExists = adminRepository.IsAny(a => a.Number == input.UserNumber && a.IsDelete != 1); + var userExists = adminRepository.IsAny(a => a.Number == input.UserNumber); if (!userExists) { return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("User not found", "用户不存在")); @@ -945,7 +943,7 @@ namespace EOM.TSHotelManagement.Service var userRoleNumber = $"R-USER-{input.UserNumber}"; // 确保专属角色存在 - var existsRole = roleRepository.IsAny(r => r.RoleNumber == userRoleNumber && r.IsDelete != 1); + var existsRole = roleRepository.IsAny(r => r.RoleNumber == userRoleNumber); if (!existsRole) { var role = new Role @@ -960,7 +958,7 @@ namespace EOM.TSHotelManagement.Service // 硬删除当前专属角色下所有有效的角色-权限绑定 var existing = rolePermissionRepository.AsQueryable() - .Where(x => x.RoleNumber == userRoleNumber && x.IsDelete != 1) + .Where(x => x.RoleNumber == userRoleNumber) .ToList(); if (existing.Count > 0) { @@ -978,7 +976,7 @@ namespace EOM.TSHotelManagement.Service { // 仅保留系统中存在的权限码 var validPerms = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && perms.Contains(p.PermissionNumber)) + .Where(p => perms.Contains(p.PermissionNumber)) .Select(p => p.PermissionNumber) .ToList(); @@ -987,22 +985,20 @@ namespace EOM.TSHotelManagement.Service var entity = new RolePermission { RoleNumber = userRoleNumber, - PermissionNumber = pnum, - IsDelete = 0 + PermissionNumber = pnum }; rolePermissionRepository.Insert(entity); } } // 确保用户与专属角色绑定存在 - var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber && ur.IsDelete != 1); + var hasBinding = userRoleRepository.IsAny(ur => ur.UserNumber == input.UserNumber && ur.RoleNumber == userRoleNumber); if (!hasBinding) { userRoleRepository.Insert(new UserRole { UserNumber = input.UserNumber, - RoleNumber = userRoleNumber, - IsDelete = 0 + RoleNumber = userRoleNumber }); } @@ -1034,7 +1030,7 @@ namespace EOM.TSHotelManagement.Service { var roleNumber = $"R-USER-{userNumber}"; var list = rolePermissionRepository.AsQueryable() - .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == roleNumber) .Select(rp => rp.PermissionNumber) .ToList(); diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs index 23dd1d2..a364c49 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs @@ -76,11 +76,6 @@ namespace EOM.TSHotelManagement.Service /// private readonly GenericRepository goodbadTypeRepository; - /// - /// 基础URL - /// - private readonly GenericRepository baseRepository; - /// /// 公告类型 /// @@ -94,7 +89,7 @@ namespace EOM.TSHotelManagement.Service private readonly ILogger logger; - public BaseService(GenericRepository workerRepository, GenericRepository educationRepository, GenericRepository nationRepository, GenericRepository deptRepository, GenericRepository positionRepository, GenericRepository passPortTypeRepository, GenericRepository custoTypeRepository, GenericRepository goodbadTypeRepository, GenericRepository baseRepository, GenericRepository appointmentNoticeTypeRepository, GenericRepository employeeRepository, GenericRepository customerRepository, GenericRepository appointmentNoticeRepository, ILogger logger) + public BaseService(GenericRepository workerRepository, GenericRepository educationRepository, GenericRepository nationRepository, GenericRepository deptRepository, GenericRepository positionRepository, GenericRepository passPortTypeRepository, GenericRepository custoTypeRepository, GenericRepository goodbadTypeRepository, GenericRepository appointmentNoticeTypeRepository, GenericRepository employeeRepository, GenericRepository customerRepository, GenericRepository appointmentNoticeRepository, ILogger logger) { this.workerRepository = workerRepository; this.educationRepository = educationRepository; @@ -104,7 +99,6 @@ namespace EOM.TSHotelManagement.Service this.passPortTypeRepository = passPortTypeRepository; this.custoTypeRepository = custoTypeRepository; this.goodbadTypeRepository = goodbadTypeRepository; - this.baseRepository = baseRepository; this.appointmentNoticeTypeRepository = appointmentNoticeTypeRepository; this.employeeRepository = employeeRepository; this.customerRepository = customerRepository; diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs index bc4b427..1c4b022 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Menu/MenuService.cs @@ -103,7 +103,6 @@ namespace EOM.TSHotelManagement.Service { filteredMenus = allMenus; var allPermNumbers = permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1) .Select(p => p.PermissionNumber) .ToList() .Where(p => !p.IsNullOrEmpty()) @@ -121,7 +120,7 @@ namespace EOM.TSHotelManagement.Service // 2) 用户 -> 角色 var roleNumbers = userRoleRepository.AsQueryable() - .Where(ur => ur.UserNumber == userNumber && ur.IsDelete != 1) + .Where(ur => ur.UserNumber == userNumber) .Select(ur => ur.RoleNumber) .ToList(); @@ -132,7 +131,7 @@ namespace EOM.TSHotelManagement.Service // 3) 角色 -> 授权(菜单与权限独立) var roleGrants = rolePermissionRepository.AsQueryable() - .Where(rp => rp.IsDelete != 1 && roleNumbers.Contains(rp.RoleNumber)) + .Where(rp => roleNumbers.Contains(rp.RoleNumber)) .Select(rp => new { rp.MenuId, rp.PermissionNumber }) .ToList(); diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs index 8d5f708..3863db7 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Role/RoleAppService.cs @@ -96,8 +96,8 @@ namespace EOM.TSHotelManagement.Service // 如果角色组存在关联的权限映射或用户绑定,则不允许删除 var roleNumbers = roles.Select(r => r.RoleNumber).ToList(); - var hasRolePermissions = rolePermissionRepository.IsAny(rp => roleNumbers.Contains(rp.RoleNumber) && rp.IsDelete != 1); - var hasUserRoles = userRoleRepository.IsAny(ur => roleNumbers.Contains(ur.RoleNumber) && ur.IsDelete != 1); + var hasRolePermissions = rolePermissionRepository.IsAny(rp => roleNumbers.Contains(rp.RoleNumber)); + var hasUserRoles = userRoleRepository.IsAny(ur => roleNumbers.Contains(ur.RoleNumber)); if (hasRolePermissions || hasUserRoles) { return new BaseResponse @@ -235,7 +235,7 @@ namespace EOM.TSHotelManagement.Service // 硬删除该角色现有有效授权映射(菜单 + 权限) var existing = rolePermissionRepository.AsQueryable() - .Where(x => x.RoleNumber == input.RoleNumber && x.IsDelete != 1) + .Where(x => x.RoleNumber == input.RoleNumber) .ToList(); if (existing.Count > 0) { @@ -259,7 +259,7 @@ namespace EOM.TSHotelManagement.Service var validPerms = distinctPerms.Count == 0 ? new List() : permissionRepository.AsQueryable() - .Where(p => p.IsDelete != 1 && distinctPerms.Contains(p.PermissionNumber)) + .Where(p => distinctPerms.Contains(p.PermissionNumber)) .Select(p => p.PermissionNumber) .ToList() .Where(p => !p.IsNullOrEmpty()) @@ -282,8 +282,7 @@ namespace EOM.TSHotelManagement.Service { RoleNumber = input.RoleNumber, PermissionNumber = perm, - MenuId = null, - IsDelete = 0 + MenuId = null }; rolePermissionRepository.Insert(entity); } @@ -295,8 +294,7 @@ namespace EOM.TSHotelManagement.Service { RoleNumber = input.RoleNumber, MenuId = menuId, - PermissionNumber = null, - IsDelete = 0 + PermissionNumber = null }; rolePermissionRepository.Insert(entity); } @@ -329,7 +327,6 @@ namespace EOM.TSHotelManagement.Service { var list = rolePermissionRepository.AsQueryable() .Where(rp => rp.RoleNumber == roleNumber - && rp.IsDelete != 1 && rp.PermissionNumber != null && rp.PermissionNumber != "") .Select(rp => rp.PermissionNumber) @@ -381,7 +378,7 @@ namespace EOM.TSHotelManagement.Service try { var grants = rolePermissionRepository.AsQueryable() - .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1) + .Where(rp => rp.RoleNumber == roleNumber) .Select(rp => new { rp.PermissionNumber, rp.MenuId }) .ToList(); @@ -444,7 +441,7 @@ namespace EOM.TSHotelManagement.Service try { var list = userRoleRepository.AsQueryable() - .Where(ur => ur.RoleNumber == roleNumber && ur.IsDelete != 1) + .Where(ur => ur.RoleNumber == roleNumber) .Select(ur => ur.UserNumber) .ToList() ?? new List(); @@ -492,8 +489,8 @@ namespace EOM.TSHotelManagement.Service // 软删除该角色当前所有有效的用户绑定 var existing = userRoleRepository.AsQueryable() - .Where(ur => ur.RoleNumber == input.RoleNumber && ur.IsDelete != 1) - .Select(ur => new UserRole { RoleNumber = ur.RoleNumber, UserNumber = ur.UserNumber, IsDelete = 1 }) + .Where(ur => ur.RoleNumber == input.RoleNumber) + .Select(ur => new UserRole { RoleNumber = ur.RoleNumber, UserNumber = ur.UserNumber }) .ToList(); foreach (var ur in existing) @@ -514,8 +511,7 @@ namespace EOM.TSHotelManagement.Service var entity = new UserRole { RoleNumber = input.RoleNumber, - UserNumber = u, - IsDelete = 0 + UserNumber = u }; userRoleRepository.Insert(entity); } -- Gitee From 2c87ae7546d6962b7db40a707a7b0d2786d41a08 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sun, 22 Feb 2026 18:38:44 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A2=84=E7=BA=A6?= =?UTF-8?q?=E6=88=BF=E9=97=B4=E4=B8=9A=E5=8A=A1=E6=B5=81=E7=A8=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuartzWorkspace/Job/ReservationExpirationCheckJob.cs | 7 +++++-- .../Business/Reser/Dto/CreateReserInputDto.cs | 1 + EOM.TSHotelManagement.Migration/EntityBuilder.cs | 2 +- .../Business/Reser/ReserService.cs | 2 +- EOM.TSHotelManagement.Service/Business/Room/RoomService.cs | 1 + .../Dashboard/DashboardService.cs | 4 ++-- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs index 6431906..04f1299 100644 --- a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs @@ -1,4 +1,4 @@ -using EOM.TSHotelManagement.Domain; +using EOM.TSHotelManagement.Domain; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -105,7 +105,10 @@ namespace EOM.TSHotelManagement.Common .SetColumns(r => new Room { RoomStateId = (int)RoomState.Vacant }) .Where(r => shouldReleaseRooms.Contains(r.RoomNumber)) .ExecuteCommand(); - db.Deleteable(r => shouldDeleteReservations.Contains(r.Id)); + db.Updateable() + .SetColumns(r => new Reser { ReservationStatus = 2 }) + .Where(r => shouldDeleteReservations.Contains(r.Id)) + .ExecuteCommand(); } _logger.LogInformation("已为 {ItemName} 发送过期提醒", item.ReservationId); diff --git a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs index 187e6fe..26d2e7f 100644 --- a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs @@ -24,6 +24,7 @@ namespace EOM.TSHotelManagement.Contract [Required(ErrorMessage = "预约结束日期为必填字段")] public DateTime ReservationEndDate { get; set; } + public int ReservationStatus { get; set; } = 0; } } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 088d409..b8d7fde 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -86,7 +86,7 @@ namespace EOM.TSHotelManagement.Migration }, new Administrator { - Number = "1263785187301658678", + Number = "AD-202005060001", Account = "admin", Password = string.Empty, Name = "Administrator", diff --git a/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs b/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs index 888c7e0..23f86b8 100644 --- a/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs +++ b/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs @@ -184,7 +184,7 @@ namespace EOM.TSHotelManagement.Service .ToList(); Reser res = null; - res = reserRepository.GetFirst(a => a.ReservationRoomNumber == readReserInputDt.ReservationRoomNumber && a.IsDelete != 1); + res = reserRepository.GetFirst(a => a.ReservationRoomNumber == readReserInputDt.ReservationRoomNumber && a.ReservationStatus == 0 && a.IsDelete != 1); //解密联系方式 var sourceTelStr = dataProtector.SafeDecryptReserData(res.ReservationPhoneNumber); res.ReservationPhoneNumber = sourceTelStr; diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index c32440a..d2996e5 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -901,6 +901,7 @@ namespace EOM.TSHotelManagement.Service } var reser = reserRepository.GetFirst(a => a.ReservationId == checkinRoomByReservationDto.ReservationId && a.IsDelete != 1); + reser.ReservationStatus = 1; reser.IsDelete = 1; var reserUpdateResult = reserRepository.Update(reser); diff --git a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs index 1517faa..4f36ea6 100644 --- a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs +++ b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs @@ -1,4 +1,4 @@ -using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; @@ -116,7 +116,7 @@ namespace EOM.TSHotelManagement.Service var roomTypes = roomTypeRepository.AsQueryable().Where(a => a.IsDelete != 1).ToList(); var resers = reserRepository.AsQueryable() - .Where(a => a.IsDelete != 1).ToList(); + .Where(a => a.ReservationStatus == 0).ToList(); var roomStateData = roomRepository.AsQueryable().Where(a => roomStates.Select(b => b.Id).ToList().Contains(a.RoomStateId)).ToList(); -- Gitee From 094023ecb32bd2be803bf85ecf2b7982302fc3c7 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 28 Feb 2026 20:40:19 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E5=A2=9E=E5=BC=BARedis=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8E=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BC=9A=E5=91=98=E7=AD=89=E7=BA=A7=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次更新包括: - 增强Redis连接与操作配置,支持多项超时与重试参数,提升健壮性与容错能力,JWT吊销检查支持Redis熔断降级。 - 定时任务(Quartz)支持自定义Cron表达式,任务注册逻辑优化,新增会员等级自动升级定时任务。 - 房间结账流程优化,自动插入住房消费记录,能源记录时间更准确。 - 消费类型常量修正,Product改为Goods。 - 数据库初始化代码精简,移除冗余MySQL结构修复逻辑。 - 配置工厂完善,支持新参数读取。 - 默认超级管理员名称调整为“超级管理员”。 - 文档与配置示例同步更新,便于理解和部署。 --- .env.example | 8 + .../Extensions/ServiceExtensions.cs | 82 +++----- .../appsettings.Application.json | 7 +- .../appsettings.Database.json | 10 +- .../Constant/SpendTypeConstant.cs | 4 +- .../Helper/JwtTokenRevocationService.cs | 114 +++++++++- .../Helper/RedisHelper.cs | 54 +++-- .../AutomaticallyUpgradeMembershipLevelJob.cs | 199 ++++++++++++++++++ .../ReservationExpirationCheckJob.cs | 0 .../DatabaseInitializer.cs | 182 ---------------- .../Config/MailConfig.cs | 3 +- .../Config/RedisConfig.cs | 8 + .../Factory/LskyConfigFactory.cs | 5 +- .../Factory/MailConfigFactory.cs | 5 +- .../Factory/RedisConfigFactory.cs | 11 +- .../EntityBuilder.cs | 2 +- .../Business/Room/RoomService.cs | 45 +++- README.en.md | 8 + README.md | 8 + 19 files changed, 483 insertions(+), 272 deletions(-) create mode 100644 EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/AutomaticallyUpgradeMembershipLevelJob.cs rename EOM.TSHotelManagement.Common/QuartzWorkspace/{Job => BusinessJob}/ReservationExpirationCheckJob.cs (100%) diff --git a/.env.example b/.env.example index 9920f34..ef2c401 100644 --- a/.env.example +++ b/.env.example @@ -52,6 +52,14 @@ Mail__DisplayName=TSHotel Redis__Enabled=false Redis__ConnectionString=${REDIS_CONNECTION_STRING} Redis__DefaultDatabase=0 +Redis__ConnectTimeoutMs=5000 +Redis__AsyncTimeoutMs=2000 +Redis__SyncTimeoutMs=2000 +Redis__KeepAliveSeconds=15 +Redis__ConnectRetry=3 +Redis__ReconnectRetryBaseDelayMs=3000 +Redis__OperationTimeoutMs=1200 +Redis__FailureCooldownSeconds=30 # Lsky (optional) Lsky__Enabled=false diff --git a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs index 14b066a..a708acd 100644 --- a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs @@ -20,6 +20,7 @@ using NSwag; using NSwag.Generation.Processors.Security; using Quartz; using System; +using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.IO; using System.Linq; @@ -59,57 +60,26 @@ namespace EOM.TSHotelManagement.WebApi services.AddQuartz(q => { var jobs = configuration.GetSection(SystemConstant.JobKeys.Code).Get() ?? Array.Empty(); - - foreach (var job in jobs) + var jobRegistrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { - var reservationJobKey = $"{job}-Reservation"; - var mailJobKey = $"{job}-Mail"; - var imageHostingJobKey = $"{job}-ImageHosting"; - var redisJobKey = $"{job}-Redis"; - - q.AddJob(opts => opts - .WithIdentity(reservationJobKey) - .StoreDurably() - .WithDescription($"{reservationJobKey} 定时作业")); - - q.AddTrigger(opts => opts - .ForJob(reservationJobKey) - .WithIdentity($"{reservationJobKey}-Trigger") - //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 - .WithCronSchedule("0 0 1 * * ?")); // 每天1:00 AM执行 - - q.AddJob(opts => opts - .WithIdentity(mailJobKey) - .StoreDurably() - .WithDescription($"{mailJobKey} 定时作业")); - - q.AddTrigger(opts => opts - .ForJob(mailJobKey) - .WithIdentity($"{mailJobKey}-Trigger") - //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 - .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 - - q.AddJob(opts => opts - .WithIdentity(imageHostingJobKey) - .StoreDurably() - .WithDescription($"{imageHostingJobKey} 定时作业")); - - q.AddTrigger(opts => opts - .ForJob(imageHostingJobKey) - .WithIdentity($"{imageHostingJobKey}-Trigger") - //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 - .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 - - q.AddJob(opts => opts - .WithIdentity(redisJobKey) - .StoreDurably() - .WithDescription($"{redisJobKey} 定时作业")); + [nameof(ReservationExpirationCheckJob)] = (configurator, name) => + RegisterJobAndTrigger(configurator, name, "0 0 1 * * ?"), // 每天凌晨1点执行 + [nameof(MailServiceCheckJob)] = (configurator, name) => + RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 + [nameof(ImageHostingServiceCheckJob)] = (configurator, name) => + RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 + [nameof(RedisServiceCheckJob)] = (configurator, name) => + RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 + [nameof(AutomaticallyUpgradeMembershipLevelJob)] = (configurator, name) => + RegisterJobAndTrigger(configurator, name, "0 30 1 * * ?") // 每天凌晨1点30分执行 + }; - q.AddTrigger(opts => opts - .ForJob(redisJobKey) - .WithIdentity($"{redisJobKey}-Trigger") - //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 - .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 + foreach (var job in jobs.Where(a => !string.IsNullOrWhiteSpace(a)).Distinct(StringComparer.OrdinalIgnoreCase)) + { + if (jobRegistrations.TryGetValue(job, out var register)) + { + register(q, job); + } } }); @@ -121,6 +91,20 @@ namespace EOM.TSHotelManagement.WebApi }); } + private static void RegisterJobAndTrigger(IServiceCollectionQuartzConfigurator quartz, string jobName, string cronExpression) + where TJob : IJob + { + quartz.AddJob(opts => opts + .WithIdentity(jobName) + .StoreDurably() + .WithDescription($"{jobName} 定时作业")); + + quartz.AddTrigger(opts => opts + .ForJob(jobName) + .WithIdentity($"{jobName}-Trigger") + .WithCronSchedule(cronExpression)); + } + public static void ConfigureXForward(this IServiceCollection services) { services.Configure(options => diff --git a/EOM.TSHotelManagement.API/appsettings.Application.json b/EOM.TSHotelManagement.API/appsettings.Application.json index b77796a..3dc7a0b 100644 --- a/EOM.TSHotelManagement.API/appsettings.Application.json +++ b/EOM.TSHotelManagement.API/appsettings.Application.json @@ -12,9 +12,10 @@ ], "AllowedHosts": "*", "JobKeys": [ - "ReservationExpirationCheckJob", - "MailServiceCheckJob", - "RedisServiceCheckJob" + "ReservationExpirationCheckJob:0 0 1 * * ?", + "MailServiceCheckJob:0 */5 * * * ?", + "RedisServiceCheckJob:0 */5 * * * ?", + "AutomaticallyUpgradeMembershipLevelJob:0 */5 * * * ?" ], "ExpirationSettings": { "NotifyDaysBefore": 3, diff --git a/EOM.TSHotelManagement.API/appsettings.Database.json b/EOM.TSHotelManagement.API/appsettings.Database.json index f4844c2..0c7186c 100644 --- a/EOM.TSHotelManagement.API/appsettings.Database.json +++ b/EOM.TSHotelManagement.API/appsettings.Database.json @@ -10,7 +10,15 @@ "Redis": { "Enabled": false, "ConnectionString": "host:port,password=your_redis_password", - "DefaultDatabase": 0 + "DefaultDatabase": 1, + "ConnectTimeoutMs": 5000, + "AsyncTimeoutMs": 2000, + "SyncTimeoutMs": 2000, + "KeepAliveSeconds": 15, + "ConnectRetry": 3, + "ReconnectRetryBaseDelayMs": 3000, + "OperationTimeoutMs": 1200, + "FailureCooldownSeconds": 30 }, "InitializeDatabase": false } diff --git a/EOM.TSHotelManagement.Common/Constant/SpendTypeConstant.cs b/EOM.TSHotelManagement.Common/Constant/SpendTypeConstant.cs index c03aee1..a1dca37 100644 --- a/EOM.TSHotelManagement.Common/Constant/SpendTypeConstant.cs +++ b/EOM.TSHotelManagement.Common/Constant/SpendTypeConstant.cs @@ -1,10 +1,10 @@ -using EOM.TSHotelManagement.Infrastructure; +using EOM.TSHotelManagement.Infrastructure; namespace EOM.TSHotelManagement.Common { public class SpendTypeConstant : CodeConstantBase { - public static readonly SpendTypeConstant Product = new SpendTypeConstant("Product", "商品"); + public static readonly SpendTypeConstant Product = new SpendTypeConstant("Goods", "商品"); public static readonly SpendTypeConstant Room = new SpendTypeConstant("Room", "房间"); public static readonly SpendTypeConstant Other = new SpendTypeConstant("Other", "其他"); diff --git a/EOM.TSHotelManagement.Common/Helper/JwtTokenRevocationService.cs b/EOM.TSHotelManagement.Common/Helper/JwtTokenRevocationService.cs index 500266b..ea69ddc 100644 --- a/EOM.TSHotelManagement.Common/Helper/JwtTokenRevocationService.cs +++ b/EOM.TSHotelManagement.Common/Helper/JwtTokenRevocationService.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using StackExchange.Redis; using System; using System.Collections.Concurrent; using System.IdentityModel.Tokens.Jwt; @@ -15,11 +16,14 @@ namespace EOM.TSHotelManagement.Common private const string RevokedTokenKeyPrefix = "auth:revoked:"; private readonly ConcurrentDictionary _memoryStore = new(); private long _memoryProbeCount; + private long _redisBypassUntilUtcTicks; private readonly RedisHelper _redisHelper; private readonly ILogger _logger; private readonly bool _useRedis; private readonly TimeSpan _fallbackTtl = TimeSpan.FromMinutes(30); + private readonly TimeSpan _redisOperationTimeout; + private readonly TimeSpan _redisFailureCooldown; public JwtTokenRevocationService( @@ -30,6 +34,13 @@ namespace EOM.TSHotelManagement.Common _redisHelper = redisHelper; _logger = logger; _useRedis = ResolveRedisEnabled(configuration); + + var redisSection = configuration.GetSection("Redis"); + var operationTimeoutMs = redisSection.GetValue("OperationTimeoutMs") ?? 1200; + var failureCooldownSeconds = redisSection.GetValue("FailureCooldownSeconds") ?? 30; + + _redisOperationTimeout = TimeSpan.FromMilliseconds(Math.Clamp(operationTimeoutMs, 200, 5000)); + _redisFailureCooldown = TimeSpan.FromSeconds(Math.Clamp(failureCooldownSeconds, 5, 300)); } public async Task RevokeTokenAsync(string token) @@ -43,14 +54,21 @@ namespace EOM.TSHotelManagement.Common var key = BuildRevokedTokenKey(normalizedToken); var ttl = CalculateRevokedTtl(normalizedToken); - if (_useRedis) + if (CanUseRedis()) { try { var db = _redisHelper.GetDatabase(); - await db.StringSetAsync(key, "1", ttl); + await ExecuteRedisWithTimeoutAsync( + () => db.StringSetAsync(key, "1", ttl), + "revoke-token"); + ClearRedisBypass(); return; } + catch (Exception ex) when (IsRedisUnavailableException(ex)) + { + MarkRedisUnavailable(ex, "revoke-token"); + } catch (Exception ex) { _logger.LogError(ex, "Redis token revoke failed, fallback to memory store."); @@ -71,12 +89,20 @@ namespace EOM.TSHotelManagement.Common var key = BuildRevokedTokenKey(normalizedToken); - if (_useRedis) + if (CanUseRedis()) { try { var db = _redisHelper.GetDatabase(); - return await db.KeyExistsAsync(key); + var isRevoked = await ExecuteRedisWithTimeoutAsync( + () => db.KeyExistsAsync(key), + "revoke-check"); + ClearRedisBypass(); + return isRevoked; + } + catch (Exception ex) when (IsRedisUnavailableException(ex)) + { + MarkRedisUnavailable(ex, "revoke-check"); } catch (Exception ex) { @@ -111,6 +137,81 @@ namespace EOM.TSHotelManagement.Common return !string.IsNullOrWhiteSpace(token); } + private bool CanUseRedis() + { + if (!_useRedis) + { + return false; + } + + var bypassUntilTicks = Interlocked.Read(ref _redisBypassUntilUtcTicks); + if (bypassUntilTicks <= 0) + { + return true; + } + + return DateTime.UtcNow.Ticks >= bypassUntilTicks; + } + + private void MarkRedisUnavailable(Exception ex, string operation) + { + var bypassUntil = DateTime.UtcNow.Add(_redisFailureCooldown).Ticks; + Interlocked.Exchange(ref _redisBypassUntilUtcTicks, bypassUntil); + + _logger.LogWarning( + ex, + "Redis {Operation} failed, bypass Redis for {CooldownSeconds}s and fallback to memory store.", + operation, + _redisFailureCooldown.TotalSeconds); + } + + private void ClearRedisBypass() + { + Interlocked.Exchange(ref _redisBypassUntilUtcTicks, 0); + } + + private static bool IsRedisUnavailableException(Exception ex) + { + return ex is TimeoutException || ex is RedisException; + } + + private async Task ExecuteRedisWithTimeoutAsync(Func redisOperation, string operation) + { + var redisTask = redisOperation(); + if (await Task.WhenAny(redisTask, Task.Delay(_redisOperationTimeout)) == redisTask) + { + await redisTask; + return; + } + + ObserveTaskFailure(redisTask); + throw new TimeoutException($"Redis operation '{operation}' timed out after {_redisOperationTimeout.TotalMilliseconds}ms."); + } + + private async Task ExecuteRedisWithTimeoutAsync(Func> redisOperation, string operation) + { + var redisTask = redisOperation(); + if (await Task.WhenAny(redisTask, Task.Delay(_redisOperationTimeout)) == redisTask) + { + return await redisTask; + } + + ObserveTaskFailure(redisTask); + throw new TimeoutException($"Redis operation '{operation}' timed out after {_redisOperationTimeout.TotalMilliseconds}ms."); + } + + private static void ObserveTaskFailure(Task task) + { + task.ContinueWith( + t => + { + var _ = t.Exception; + }, + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default); + } + private static string BuildRevokedTokenKey(string token) { var hash = SHA256.HashData(Encoding.UTF8.GetBytes(token)); @@ -188,7 +289,8 @@ namespace EOM.TSHotelManagement.Common private static bool ResolveRedisEnabled(IConfiguration configuration) { var redisSection = configuration.GetSection("Redis"); - var enable = redisSection.GetValue("Enabled"); + var enable = redisSection.GetValue("Enable") + ?? redisSection.GetValue("Enabled"); if (enable.HasValue) { return enable.Value; @@ -197,4 +299,4 @@ namespace EOM.TSHotelManagement.Common return redisSection.GetValue("Enabled"); } } -} +} \ No newline at end of file diff --git a/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs index 1238879..9c94132 100644 --- a/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs @@ -2,6 +2,7 @@ using EOM.TSHotelManagement.Infrastructure; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System; +using System.Threading.Tasks; namespace EOM.TSHotelManagement.Common { @@ -9,6 +10,7 @@ namespace EOM.TSHotelManagement.Common { private readonly object _lock = new object(); private IConnectionMultiplexer _connection; + private int _defaultDatabase = -1; private readonly ILogger logger; private readonly RedisConfigFactory configFactory; @@ -23,29 +25,44 @@ namespace EOM.TSHotelManagement.Common { lock (_lock) { - if (_connection != null) return; + if (_connection != null) + { + return; + } + try { var redisConfig = configFactory.GetRedisConfig(); - if (!redisConfig.Enable) { logger.LogInformation("Redis功能未启用,跳过初始化"); return; } - int defaultDatabase = redisConfig.DefaultDatabase ?? -1; - - if (string.IsNullOrWhiteSpace(redisConfig?.ConnectionString)) + if (string.IsNullOrWhiteSpace(redisConfig.ConnectionString)) + { throw new ArgumentException("Redis连接字符串不能为空"); + } - var options = ConfigurationOptions.Parse(redisConfig.ConnectionString); + _defaultDatabase = redisConfig.DefaultDatabase ?? -1; + + var options = ConfigurationOptions.Parse(redisConfig.ConnectionString, ignoreUnknown: true); options.AbortOnConnectFail = false; - options.ConnectTimeout = 5000; - options.ReconnectRetryPolicy = new ExponentialRetry(3000); + options.ConnectTimeout = Clamp(redisConfig.ConnectTimeoutMs, 1000, 30000, 5000); + options.SyncTimeout = Clamp(redisConfig.SyncTimeoutMs, 500, 30000, 2000); + options.AsyncTimeout = Clamp(redisConfig.AsyncTimeoutMs, 500, 30000, 2000); + options.KeepAlive = Clamp(redisConfig.KeepAliveSeconds, 5, 300, 15); + options.ConnectRetry = Clamp(redisConfig.ConnectRetry, 1, 10, 3); + options.ReconnectRetryPolicy = new ExponentialRetry( + Clamp(redisConfig.ReconnectRetryBaseDelayMs, 500, 30000, 3000)); + + if (_defaultDatabase >= 0) + { + options.DefaultDatabase = _defaultDatabase; + } _connection = ConnectionMultiplexer.Connect(options); - _connection.GetDatabase(defaultDatabase).Ping(); + _connection.GetDatabase(_defaultDatabase).Ping(); } catch (Exception ex) { @@ -58,9 +75,11 @@ namespace EOM.TSHotelManagement.Common public IDatabase GetDatabase() { if (_connection == null) - throw new System.Exception("RedisHelper not initialized. Call Initialize first."); + { + throw new Exception("RedisHelper not initialized. Call Initialize first."); + } - return _connection.GetDatabase(); + return _connection.GetDatabase(_defaultDatabase); } public async Task CheckServiceStatusAsync() @@ -86,12 +105,10 @@ namespace EOM.TSHotelManagement.Common var db = GetDatabase(); if (expiry.HasValue) { - return await db.StringSetAsync(key, value, new StackExchange.Redis.Expiration(expiry.Value)); - } - else - { - return await db.StringSetAsync(key, value); + return await db.StringSetAsync(key, value, expiry.Value); } + + return await db.StringSetAsync(key, value); } catch (Exception ex) { @@ -142,5 +159,10 @@ namespace EOM.TSHotelManagement.Common } } + private static int Clamp(int? value, int min, int max, int fallback) + { + return Math.Clamp(value ?? fallback, min, max); + } } } + diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/AutomaticallyUpgradeMembershipLevelJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/AutomaticallyUpgradeMembershipLevelJob.cs new file mode 100644 index 0000000..ffd37af --- /dev/null +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/AutomaticallyUpgradeMembershipLevelJob.cs @@ -0,0 +1,199 @@ +using EOM.TSHotelManagement.Domain; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Quartz; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace EOM.TSHotelManagement.Common +{ + [DisallowConcurrentExecution] + public class AutomaticallyUpgradeMembershipLevelJob : IJob + { + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + + public AutomaticallyUpgradeMembershipLevelJob( + ILogger logger, + IServiceProvider serviceProvider) + { + _logger = logger; + _serviceProvider = serviceProvider; + } + + public Task Execute(IJobExecutionContext context) + { + _logger.LogInformation("开始批量处理会员等级升级。"); + + try + { + var result = ValidateAndUpdateCustomerInfo(); + _logger.LogInformation( + "会员等级升级完成,扫描客户 {ScannedCount} 个,需升级 {NeedUpgradeCount} 个,实际更新 {UpdatedCount} 个。", + result.ScannedCount, + result.NeedUpgradeCount, + result.UpdatedCount); + } + catch (Exception ex) + { + _logger.LogError(ex, "处理会员等级升级时发生异常"); + } + + return Task.CompletedTask; + } + + private MembershipUpgradeResult ValidateAndUpdateCustomerInfo() + { + using var scope = _serviceProvider.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + + var listVipRules = db.Queryable() + .Where(v => v.IsDelete != 1) + .OrderByDescending(a => a.RuleValue) + .ToList(); + + if (listVipRules.Count == 0) + { + _logger.LogWarning("会员等级升级已跳过:未找到有效的会员规则。"); + return MembershipUpgradeResult.Empty; + } + + var enabledCustomerTypes = db.Queryable() + .Where(x => x.IsDelete != 1) + .Select(x => x.CustomerType) + .ToList() + .ToHashSet(); + + listVipRules = listVipRules + .Where(x => enabledCustomerTypes.Contains(x.VipLevelId)) + .ToList(); + + if (listVipRules.Count == 0) + { + _logger.LogWarning("会员等级升级已跳过:规则指向的会员等级不存在或已被删除。"); + return MembershipUpgradeResult.Empty; + } + + var customerSpends = db.Queryable() + .Where(s => s.IsDelete != 1 && s.CustomerNumber != null && s.CustomerNumber != string.Empty) + .GroupBy(s => s.CustomerNumber) + .Select((s) => new CustomerSpendAggregate + { + CustomerNumber = s.CustomerNumber, + TotalConsumptionAmount = SqlFunc.AggregateSum(s.ConsumptionAmount) + }) + .ToList(); + + if (customerSpends.Count == 0) + { + _logger.LogInformation("会员等级升级已跳过:未找到有效消费记录。"); + return MembershipUpgradeResult.Empty; + } + + var customerNumbers = customerSpends + .Select(x => x.CustomerNumber) + .Where(x => !string.IsNullOrWhiteSpace(x)) + .Distinct() + .ToList(); + + var customers = db.Queryable() + .Where(c => c.IsDelete != 1 && customerNumbers.Contains(c.CustomerNumber)) + .ToList(); + + var customerLookup = customers + .Where(c => !string.IsNullOrWhiteSpace(c.CustomerNumber)) + .GroupBy(c => c.CustomerNumber) + .ToDictionary(g => g.Key, g => g.First()); + + var updateTime = DateTime.Now; + var customerToUpdate = new List(); + + foreach (var customerSpend in customerSpends) + { + if (string.IsNullOrWhiteSpace(customerSpend.CustomerNumber)) + { + continue; + } + + if (!customerLookup.TryGetValue(customerSpend.CustomerNumber, out var customer)) + { + continue; + } + + var targetVipLevel = listVipRules + .FirstOrDefault(vipRule => customerSpend.TotalConsumptionAmount >= vipRule.RuleValue)? + .VipLevelId ?? 0; + + if (targetVipLevel <= 0 || targetVipLevel == customer.CustomerType) + { + continue; + } + + customer.CustomerType = targetVipLevel; + customer.DataChgDate = updateTime; + customer.DataChgUsr = "BatchJobSystem"; + customerToUpdate.Add(customer); + } + + if (customerToUpdate.Count == 0) + { + return new MembershipUpgradeResult + { + ScannedCount = customerSpends.Count, + NeedUpgradeCount = 0, + UpdatedCount = 0 + }; + } + + var updatedCount = 0; + + db.Ado.BeginTran(); + try + { + foreach (var batch in customerToUpdate.Chunk(200)) + { + var currentBatch = batch.ToList(); + updatedCount += db.Updateable(currentBatch) + .UpdateColumns( + nameof(Customer.CustomerType), + nameof(Customer.DataChgDate), + nameof(Customer.DataChgUsr)) + .ExecuteCommand(); + } + + db.Ado.CommitTran(); + } + catch + { + db.Ado.RollbackTran(); + throw; + } + + return new MembershipUpgradeResult + { + ScannedCount = customerSpends.Count, + NeedUpgradeCount = customerToUpdate.Count, + UpdatedCount = updatedCount + }; + } + + private sealed class CustomerSpendAggregate + { + public string CustomerNumber { get; set; } = string.Empty; + public decimal TotalConsumptionAmount { get; set; } + } + + private sealed class MembershipUpgradeResult + { + public static MembershipUpgradeResult Empty { get; } = new MembershipUpgradeResult(); + + public int ScannedCount { get; set; } + public int NeedUpgradeCount { get; set; } + public int UpdatedCount { get; set; } + } + } +} diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/ReservationExpirationCheckJob.cs similarity index 100% rename from EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs rename to EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/ReservationExpirationCheckJob.cs diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index 49c8dd0..0506d77 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -102,8 +102,6 @@ namespace EOM.TSHotelManagement.Data .ToArray(); db.CodeFirst.InitTables(needCreateTableTypes); - EnsureTwoFactorForeignKeys(db, dbSettings.DbType); - EnsureRolePermissionSchema(db, dbSettings.DbType); Console.WriteLine("Database schema initialized"); @@ -260,186 +258,6 @@ namespace EOM.TSHotelManagement.Data return configString; } - private void EnsureTwoFactorForeignKeys(ISqlSugarClient db, DbType dbType) - { - try - { - if (dbType is DbType.MySql or DbType.MySqlConnector) - { - EnsureMySqlForeignKey(db, "two_factor_auth", "fk_2fa_employee", "employee_pk", "employee", "id"); - EnsureMySqlForeignKey(db, "two_factor_auth", "fk_2fa_administrator", "administrator_pk", "administrator", "id"); - EnsureMySqlForeignKey(db, "two_factor_auth", "fk_2fa_customer_account", "customer_account_pk", "customer_account", "id"); - EnsureMySqlForeignKey(db, "two_factor_recovery_code", "fk_2fa_recovery_auth", "two_factor_auth_pk", "two_factor_auth", "id", "CASCADE"); - } - } - catch (Exception ex) - { - Console.WriteLine($"EnsureTwoFactorForeignKeys skipped: {ex.Message}"); - } - } - - private void EnsureRolePermissionSchema(ISqlSugarClient db, DbType dbType) - { - try - { - if (dbType is DbType.MySql or DbType.MySqlConnector) - { - EnsureMySqlRolePermissionColumnsAndKeys(db); - BackfillRolePermissionMenuIdsFromLegacyData(db); - } - } - catch (Exception ex) - { - Console.WriteLine($"EnsureRolePermissionSchema skipped: {ex.Message}"); - } - } - - private static void EnsureMySqlRolePermissionColumnsAndKeys(ISqlSugarClient db) - { - var tableExists = db.Ado.GetInt( - @"SELECT COUNT(1) - FROM information_schema.TABLES - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'role_permission'") > 0; - if (!tableExists) - { - return; - } - - var hasMenuId = db.Ado.GetInt( - @"SELECT COUNT(1) - FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'role_permission' - AND COLUMN_NAME = 'menu_id'") > 0; - if (!hasMenuId) - { - db.Ado.ExecuteCommand( - "ALTER TABLE `role_permission` ADD COLUMN `menu_id` int NULL COMMENT '关联菜单主键 (Linked Menu Id)'"); - } - - var permissionNullable = string.Equals( - db.Ado.GetString( - @"SELECT IS_NULLABLE - FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'role_permission' - AND COLUMN_NAME = 'permission_number' - LIMIT 1"), - "YES", - StringComparison.OrdinalIgnoreCase); - if (!permissionNullable) - { - db.Ado.ExecuteCommand( - "ALTER TABLE `role_permission` MODIFY COLUMN `permission_number` varchar(128) NULL COMMENT '关联权限编码 (Linked Permission Code)'"); - } - - var pkColumns = db.Ado.SqlQuery( - @"SELECT COLUMN_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'role_permission' - AND CONSTRAINT_NAME = 'PRIMARY' - ORDER BY ORDINAL_POSITION"); - - var needResetPrimaryKey = pkColumns.Count != 1 - || !string.Equals(pkColumns[0], "id", StringComparison.OrdinalIgnoreCase); - if (needResetPrimaryKey) - { - if (pkColumns.Count > 0) - { - db.Ado.ExecuteCommand("ALTER TABLE `role_permission` DROP PRIMARY KEY"); - } - db.Ado.ExecuteCommand("ALTER TABLE `role_permission` ADD PRIMARY KEY (`id`)"); - } - - EnsureMySqlIndex(db, "role_permission", "Index_role_permission_role_number", "`role_number`"); - EnsureMySqlIndex(db, "role_permission", "Index_role_permission_permission_number", "`permission_number`"); - EnsureMySqlIndex(db, "role_permission", "Index_role_permission_menu_id", "`menu_id`"); - } - - private static void BackfillRolePermissionMenuIdsFromLegacyData(ISqlSugarClient db) - { - var hasPermissionMenuKey = db.Ado.GetInt( - @"SELECT COUNT(1) - FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'permission' - AND COLUMN_NAME = 'menu_key'") > 0; - if (!hasPermissionMenuKey) - { - return; - } - - var sql = @" -UPDATE `role_permission` rp -INNER JOIN `permission` p ON p.`permission_number` = rp.`permission_number` AND IFNULL(p.`delete_mk`, 0) <> 1 -INNER JOIN `menu` m ON m.`key` = p.`menu_key` AND IFNULL(m.`delete_mk`, 0) <> 1 -SET rp.`menu_id` = m.`id` -WHERE rp.`menu_id` IS NULL - AND rp.`permission_number` IS NOT NULL - AND p.`menu_key` IS NOT NULL - AND p.`menu_key` <> '';"; - - db.Ado.ExecuteCommand(sql); - } - - private static void EnsureMySqlForeignKey( - ISqlSugarClient db, - string tableName, - string constraintName, - string columnName, - string referenceTable, - string referenceColumn, - string onDeleteAction = "SET NULL") - { - var existsSql = @"SELECT COUNT(1) - FROM information_schema.TABLE_CONSTRAINTS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = @tableName - AND CONSTRAINT_NAME = @constraintName"; - - var exists = db.Ado.GetInt( - existsSql, - new SugarParameter("@tableName", tableName), - new SugarParameter("@constraintName", constraintName)) > 0; - if (exists) - { - return; - } - - var addConstraintSql = $@"ALTER TABLE `{tableName}` - ADD CONSTRAINT `{constraintName}` - FOREIGN KEY (`{columnName}`) - REFERENCES `{referenceTable}`(`{referenceColumn}`) - ON UPDATE RESTRICT - ON DELETE {onDeleteAction};"; - - db.Ado.ExecuteCommand(addConstraintSql); - } - - private static void EnsureMySqlIndex( - ISqlSugarClient db, - string tableName, - string indexName, - string columnExpression) - { - var exists = db.Ado.GetInt( - @"SELECT COUNT(1) - FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = @tableName - AND INDEX_NAME = @indexName", - new SugarParameter("@tableName", tableName), - new SugarParameter("@indexName", indexName)) > 0; - if (exists) - { - return; - } - - db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` ADD INDEX `{indexName}` ({columnExpression})"); - } - private void SeedInitialData(ISqlSugarClient db) { Console.WriteLine("Initializing database data..."); diff --git a/EOM.TSHotelManagement.Infrastructure/Config/MailConfig.cs b/EOM.TSHotelManagement.Infrastructure/Config/MailConfig.cs index 078f1c0..ace9a51 100644 --- a/EOM.TSHotelManagement.Infrastructure/Config/MailConfig.cs +++ b/EOM.TSHotelManagement.Infrastructure/Config/MailConfig.cs @@ -1,4 +1,4 @@ -namespace EOM.TSHotelManagement.Infrastructure +namespace EOM.TSHotelManagement.Infrastructure { public class MailConfig { @@ -6,6 +6,7 @@ /// 是否启用邮件服务 /// public bool Enabled { get; set; } = false; + /// /// SMTP服务器地址 /// diff --git a/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs b/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs index 967ad81..c50896b 100644 --- a/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs +++ b/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs @@ -5,5 +5,13 @@ namespace EOM.TSHotelManagement.Infrastructure public string ConnectionString { get; set; } public bool Enable { get; set; } public int? DefaultDatabase { get; set; } + public int? ConnectTimeoutMs { get; set; } + public int? AsyncTimeoutMs { get; set; } + public int? SyncTimeoutMs { get; set; } + public int? KeepAliveSeconds { get; set; } + public int? ConnectRetry { get; set; } + public int? ReconnectRetryBaseDelayMs { get; set; } + public int? OperationTimeoutMs { get; set; } + public int? FailureCooldownSeconds { get; set; } } } diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs index f36a3d5..729e2e8 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; namespace EOM.TSHotelManagement.Infrastructure { @@ -16,6 +16,7 @@ namespace EOM.TSHotelManagement.Infrastructure var lskySection = _configuration.GetSection("Lsky"); var lskyConfig = new LskyConfig { + Enabled = lskySection.GetValue("Enabled") ?? false, BaseAddress = lskySection.GetValue("BaseAddress") ?? string.Empty, Email = lskySection.GetValue("Email") ?? string.Empty, Password = lskySection.GetValue("Password") ?? string.Empty, @@ -25,4 +26,4 @@ namespace EOM.TSHotelManagement.Infrastructure return lskyConfig; } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs index 63a8bef..b2939eb 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; namespace EOM.TSHotelManagement.Infrastructure { @@ -20,7 +20,8 @@ namespace EOM.TSHotelManagement.Infrastructure UserName = _configuration.GetSection("Mail").GetValue("UserName") ?? string.Empty, Password = _configuration.GetSection("Mail").GetValue("Password") ?? string.Empty, EnableSsl = _configuration.GetSection("Mail").GetValue("EnableSsl") ?? false, - DisplayName = _configuration.GetSection("Mail").GetValue("DisplayName") ?? string.Empty + DisplayName = _configuration.GetSection("Mail").GetValue("DisplayName") ?? string.Empty, + Enabled = _configuration.GetSection("Mail").GetValue("Enabled") ?? false, }; return mailConfig; } diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs index 981eeaf..056ae5b 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs @@ -24,7 +24,16 @@ namespace EOM.TSHotelManagement.Infrastructure var redisConfig = new RedisConfig { ConnectionString = redisSection.GetValue("ConnectionString"), - Enable = enable + Enable = enable, + DefaultDatabase = redisSection.GetValue("DefaultDatabase"), + ConnectTimeoutMs = redisSection.GetValue("ConnectTimeoutMs"), + AsyncTimeoutMs = redisSection.GetValue("AsyncTimeoutMs"), + SyncTimeoutMs = redisSection.GetValue("SyncTimeoutMs"), + KeepAliveSeconds = redisSection.GetValue("KeepAliveSeconds"), + ConnectRetry = redisSection.GetValue("ConnectRetry"), + ReconnectRetryBaseDelayMs = redisSection.GetValue("ReconnectRetryBaseDelayMs"), + OperationTimeoutMs = redisSection.GetValue("OperationTimeoutMs"), + FailureCooldownSeconds = redisSection.GetValue("FailureCooldownSeconds") }; return redisConfig; } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index b8d7fde..d9faced 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -89,7 +89,7 @@ namespace EOM.TSHotelManagement.Migration Number = "AD-202005060001", Account = "admin", Password = string.Empty, - Name = "Administrator", + Name = "超级管理员", Type = "Admin", IsSuperAdmin = 1, IsDelete = 0, diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index d2996e5..ff820ba 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -705,7 +705,7 @@ namespace EOM.TSHotelManagement.Service }, a => a.CustomerNumber == transferRoomDto.CustomerNumber); } - var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType); + var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType && a.IsDelete != 1); if (customerType.IsNullOrEmpty()) return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer type does not exist", "客户类型不存在"), Code = BusinessStatusCode.InternalServerError }; @@ -801,9 +801,14 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not exist", "客户不存在"), Code = BusinessStatusCode.InternalServerError }; var room = roomRepository.GetFirst(a => a.RoomNumber == checkoutRoomDto.RoomNumber); + + var checkinDate = room.LastCheckInTime; + var checkoutDate = room.LastCheckOutTime; + //更新房间状态 room.CustomerNumber = string.Empty; - room.LastCheckOutTime = DateOnly.FromDateTime(DateTime.Now); + room.LastCheckInTime = DateOnly.MinValue; + room.LastCheckOutTime = DateOnly.MinValue; room.RoomStateId = (int)RoomState.Dirty; var roomUpdateResult = roomRepository.Update(room); if (!roomUpdateResult) @@ -815,14 +820,14 @@ namespace EOM.TSHotelManagement.Service var energy = new EnergyManagement { InformationId = uniqueCode.GetNewId("EM-"), - StartDate = (DateOnly)room.LastCheckInTime, - EndDate = DateOnly.FromDateTime((DateTime)checkoutRoomDto.DataChgDate), + StartDate = checkinDate ?? DateOnly.MinValue, + EndDate = DateOnly.FromDateTime(DateTime.Today), WaterUsage = checkoutRoomDto.WaterUsage, PowerUsage = checkoutRoomDto.ElectricityUsage, - Recorder = checkoutRoomDto.DataChgUsr, + Recorder = "System", CustomerNumber = room.CustomerNumber, RoomNumber = checkoutRoomDto.RoomNumber, - IsDelete = 0 + IsDelete = 0, }; energyRepository.Insert(energy); @@ -846,6 +851,34 @@ namespace EOM.TSHotelManagement.Service } } + // 插入住房消费记录 + var staySpan = DateTime.Now - room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue); + var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + var customerType = custoTypeRepository.GetSingle(a => a.CustomerType == customer.First().CustomerType && a.IsDelete != 1); + if (customerType.IsNullOrEmpty()) + return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer type does not exist", "客户类型不存在"), Code = BusinessStatusCode.InternalServerError }; + + decimal discount = (customerType != null && customerType.Discount > 0 && customerType.Discount < 100) + ? customerType.Discount / 100M + : 1M; + decimal roomBill = room.RoomRent * stayDays * discount; + var bill = new Spend + { + SpendNumber = uniqueCode.GetNewId("SP-"), + ProductName = $"居住 {checkoutRoomDto.RoomNumber} 共 {stayDays} 天", + SettlementStatus = ConsumptionConstant.Settled.Code, + ConsumptionType = SpendTypeConstant.Room.Code, + ConsumptionQuantity = stayDays, + ConsumptionTime = checkinDate.Value.ToDateTime(TimeOnly.MinValue), + ProductNumber = room.RoomNumber, + ProductPrice = room.RoomRent, + ConsumptionAmount = roomBill, + CustomerNumber = room.CustomerNumber, + RoomNumber = checkoutRoomDto.RoomNumber, + IsDelete = 0, + }; + spendRepository.Insert(bill); + scope.Complete(); } } diff --git a/README.en.md b/README.en.md index 424be9c..69b9e6b 100644 --- a/README.en.md +++ b/README.en.md @@ -199,6 +199,14 @@ docker run -d \ |Redis__Enabled|Enable Redis|N|false|true/false| |Redis__ConnectionString|Redis ConnectString|N|N/A|N/A| |Redis__DefaultDatabase|Default Database of Redis|N|0|0| +|Redis__ConnectTimeoutMs|Redis connect timeout (ms)|N|5000|1000~30000| +|Redis__AsyncTimeoutMs|Redis async command timeout (ms)|N|2000|500~30000| +|Redis__SyncTimeoutMs|Redis sync command timeout (ms)|N|2000|500~30000| +|Redis__KeepAliveSeconds|Redis keepalive interval (seconds)|N|15|5~300| +|Redis__ConnectRetry|Redis connect retry count|N|3|1~10| +|Redis__ReconnectRetryBaseDelayMs|Redis reconnect exponential retry base delay (ms)|N|3000|500~30000| +|Redis__OperationTimeoutMs|JWT revocation check operation timeout (ms)|N|1200|200~5000| +|Redis__FailureCooldownSeconds|Fallback cooldown after Redis failure (seconds)|N|30|5~300| |Idempotency__Enabled|Enable Idempotency-Key middleware|N|true|true/false| |Idempotency__EnforceKey|Require Idempotency-Key for write requests|N|false|true/false| |Idempotency__MaxKeyLength|Maximum Idempotency-Key length|N|128|integer >= 16| diff --git a/README.md b/README.md index 79cae06..fb6e5fa 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,14 @@ docker run -d \ |Redis__Enabled|是否启用Redis服务|N|false|true/false| |Redis__ConnectionString|Redis连接字符串|N|N/A|N/A| |Redis__DefaultDatabase|默认数据库|N|0|0| +|Redis__ConnectTimeoutMs|Redis 建连超时(毫秒)|N|5000|1000~30000| +|Redis__AsyncTimeoutMs|Redis 异步命令超时(毫秒)|N|2000|500~30000| +|Redis__SyncTimeoutMs|Redis 同步命令超时(毫秒)|N|2000|500~30000| +|Redis__KeepAliveSeconds|Redis KeepAlive 间隔(秒)|N|15|5~300| +|Redis__ConnectRetry|Redis 连接重试次数|N|3|1~10| +|Redis__ReconnectRetryBaseDelayMs|Redis 重连指数退避基准延迟(毫秒)|N|3000|500~30000| +|Redis__OperationTimeoutMs|JWT 吊销检查操作超时(毫秒)|N|1200|200~5000| +|Redis__FailureCooldownSeconds|Redis 失败后熔断冷却时间(秒)|N|30|5~300| |Idempotency__Enabled|是否启用幂等键中间件|N|true|true/false| |Idempotency__EnforceKey|是否强制写请求必须携带 Idempotency-Key|N|false|true/false| |Idempotency__MaxKeyLength|Idempotency-Key 最大长度|N|128|>=16 的整数| -- Gitee From d4b06a3c9195df3e8479afb79a28775271860210 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sun, 1 Mar 2026 14:37:01 +0800 Subject: [PATCH 06/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=E3=80=82?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8C=89=E7=85=A7=E9=A2=84=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=89=A7=E8=A1=8C=E3=80=82=20=E6=9B=B4=E6=96=B0MD?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=AF=B9=E9=BD=90=E7=8E=B0=E6=9C=89=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 7 +- .../Quartz/QuartzController.cs | 27 +++++ .../Extensions/ServiceExtensions.cs | 56 +++++++--- .../appsettings.Application.json | 7 ++ .../Helper/RedisHelper.cs | 12 +++ .../Dto/Quartz/ReadQuartzJobOutputDto.cs | 26 +++++ .../EntityBuilder.cs | 17 ++- .../Quartz/IQuartzAppService.cs | 10 ++ .../Quartz/QuartzAppService.cs | 100 ++++++++++++++++++ README.en.md | 6 +- README.md | 6 +- 11 files changed, 249 insertions(+), 25 deletions(-) create mode 100644 EOM.TSHotelManagement.API/Controllers/SystemManagement/Quartz/QuartzController.cs create mode 100644 EOM.TSHotelManagement.Contract/SystemManagement/Dto/Quartz/ReadQuartzJobOutputDto.cs create mode 100644 EOM.TSHotelManagement.Service/SystemManagement/Quartz/IQuartzAppService.cs create mode 100644 EOM.TSHotelManagement.Service/SystemManagement/Quartz/QuartzAppService.cs diff --git a/.env.example b/.env.example index ef2c401..203c787 100644 --- a/.env.example +++ b/.env.example @@ -25,9 +25,10 @@ AllowedOrigins__0=http://localhost:8080 AllowedOrigins__1=https://www.yourdomain.com # Quartz jobs -JobKeys__0=ReservationExpirationCheckJob -JobKeys__1=MailServiceCheckJob -JobKeys__2=RedisServiceCheckJob +JobKeys__0=ReservationExpirationCheckJob:0 0 1 * * ? +JobKeys__1=MailServiceCheckJob:0 */5 * * * ? +JobKeys__2=RedisServiceCheckJob:0 */5 * * * ? +JobKeys__3=AutomaticallyUpgradeMembershipLevelJob:0 30 1 * * ? ExpirationSettings__NotifyDaysBefore=3 ExpirationSettings__CheckIntervalMinutes=5 diff --git a/EOM.TSHotelManagement.API/Controllers/SystemManagement/Quartz/QuartzController.cs b/EOM.TSHotelManagement.API/Controllers/SystemManagement/Quartz/QuartzController.cs new file mode 100644 index 0000000..019999a --- /dev/null +++ b/EOM.TSHotelManagement.API/Controllers/SystemManagement/Quartz/QuartzController.cs @@ -0,0 +1,27 @@ +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Service; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; + +namespace EOM.TSHotelManagement.WebApi.Controllers +{ + public class QuartzController : ControllerBase + { + private readonly IQuartzAppService _quartzAppService; + + public QuartzController(IQuartzAppService quartzAppService) + { + _quartzAppService = quartzAppService; + } + + /// + /// 查询当前已注册的Quartz任务和触发器列表 + /// + /// + [HttpGet] + public async Task> SelectQuartzJobList() + { + return await _quartzAppService.SelectQuartzJobList(); + } + } +} diff --git a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs index a708acd..083b0c1 100644 --- a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs @@ -60,26 +60,35 @@ namespace EOM.TSHotelManagement.WebApi services.AddQuartz(q => { var jobs = configuration.GetSection(SystemConstant.JobKeys.Code).Get() ?? Array.Empty(); - var jobRegistrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) + var jobRegistrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { - [nameof(ReservationExpirationCheckJob)] = (configurator, name) => - RegisterJobAndTrigger(configurator, name, "0 0 1 * * ?"), // 每天凌晨1点执行 - [nameof(MailServiceCheckJob)] = (configurator, name) => - RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 - [nameof(ImageHostingServiceCheckJob)] = (configurator, name) => - RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 - [nameof(RedisServiceCheckJob)] = (configurator, name) => - RegisterJobAndTrigger(configurator, name, "0 */5 * * * ?"), // 每5分钟执行一次 - [nameof(AutomaticallyUpgradeMembershipLevelJob)] = (configurator, name) => - RegisterJobAndTrigger(configurator, name, "0 30 1 * * ?") // 每天凌晨1点30分执行 + [nameof(ReservationExpirationCheckJob)] = (configurator, jobName, cronExpression) => + RegisterJobAndTrigger(configurator, jobName, cronExpression), + [nameof(MailServiceCheckJob)] = (configurator, jobName, cronExpression) => + RegisterJobAndTrigger(configurator, jobName, cronExpression), + [nameof(ImageHostingServiceCheckJob)] = (configurator, jobName, cronExpression) => + RegisterJobAndTrigger(configurator, jobName, cronExpression), + [nameof(RedisServiceCheckJob)] = (configurator, jobName, cronExpression) => + RegisterJobAndTrigger(configurator, jobName, cronExpression), + [nameof(AutomaticallyUpgradeMembershipLevelJob)] = (configurator, jobName, cronExpression) => + RegisterJobAndTrigger(configurator, jobName, cronExpression) }; + var registeredJobs = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var job in jobs.Where(a => !string.IsNullOrWhiteSpace(a)).Distinct(StringComparer.OrdinalIgnoreCase)) { - if (jobRegistrations.TryGetValue(job, out var register)) + var (jobName, cronExpression) = ParseJobRegistration(job); + if (!registeredJobs.Add(jobName)) { - register(q, job); + throw new InvalidOperationException($"Duplicate quartz job configuration found for '{jobName}'."); } + + if (!jobRegistrations.TryGetValue(jobName, out var register)) + { + throw new InvalidOperationException($"Unsupported quartz job '{jobName}' in '{SystemConstant.JobKeys.Code}'."); + } + + register(q, jobName, cronExpression); } }); @@ -105,6 +114,27 @@ namespace EOM.TSHotelManagement.WebApi .WithCronSchedule(cronExpression)); } + private static (string JobName, string CronExpression) ParseJobRegistration( + string jobConfiguration) + { + var entry = jobConfiguration?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(entry)) + { + throw new InvalidOperationException($"Invalid quartz job configuration value in '{SystemConstant.JobKeys.Code}'."); + } + + var separatorIndex = entry.IndexOf(':'); + if (separatorIndex > 0 && separatorIndex < entry.Length - 1) + { + var jobName = entry[..separatorIndex].Trim(); + var cronExpression = entry[(separatorIndex + 1)..].Trim(); + return (jobName, cronExpression); + } + + throw new InvalidOperationException( + $"Quartz job '{entry}' is missing cron expression. Use 'JobName:CronExpression' format."); + } + public static void ConfigureXForward(this IServiceCollection services) { services.Configure(options => diff --git a/EOM.TSHotelManagement.API/appsettings.Application.json b/EOM.TSHotelManagement.API/appsettings.Application.json index 3dc7a0b..f5f5b47 100644 --- a/EOM.TSHotelManagement.API/appsettings.Application.json +++ b/EOM.TSHotelManagement.API/appsettings.Application.json @@ -12,10 +12,17 @@ ], "AllowedHosts": "*", "JobKeys": [ + // For production "ReservationExpirationCheckJob:0 0 1 * * ?", "MailServiceCheckJob:0 */5 * * * ?", "RedisServiceCheckJob:0 */5 * * * ?", "AutomaticallyUpgradeMembershipLevelJob:0 */5 * * * ?" + + // For testing "* * * * * ? " + //"ReservationExpirationCheckJob:* * * * * ? ", + //"MailServiceCheckJob:* * * * * ? ", + //"RedisServiceCheckJob:* * * * * ? ", + //"AutomaticallyUpgradeMembershipLevelJob:* * * * * ? " ], "ExpirationSettings": { "NotifyDaysBefore": 3, diff --git a/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs index 9c94132..52b26ca 100644 --- a/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs @@ -84,6 +84,18 @@ namespace EOM.TSHotelManagement.Common public async Task CheckServiceStatusAsync() { + var redisConfig = configFactory.GetRedisConfig(); + if (!redisConfig.Enable) + { + logger.LogInformation("Redis功能未启用,跳过初始化"); + return false; + } + + if (string.IsNullOrWhiteSpace(redisConfig.ConnectionString)) + { + throw new ArgumentException("Redis连接字符串不能为空"); + } + try { var db = GetDatabase(); diff --git a/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Quartz/ReadQuartzJobOutputDto.cs b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Quartz/ReadQuartzJobOutputDto.cs new file mode 100644 index 0000000..8c9d2ab --- /dev/null +++ b/EOM.TSHotelManagement.Contract/SystemManagement/Dto/Quartz/ReadQuartzJobOutputDto.cs @@ -0,0 +1,26 @@ +namespace EOM.TSHotelManagement.Contract +{ + public class ReadQuartzJobOutputDto + { + public string JobName { get; set; } + public string JobGroup { get; set; } + public string JobDescription { get; set; } + public bool IsDurable { get; set; } + public bool RequestsRecovery { get; set; } + + public string TriggerName { get; set; } + public string TriggerGroup { get; set; } + public string TriggerType { get; set; } + public string TriggerState { get; set; } + + public string CronExpression { get; set; } + public string TimeZoneId { get; set; } + public int? RepeatCount { get; set; } + public double? RepeatIntervalMs { get; set; } + + public DateTime? StartTimeUtc { get; set; } + public DateTime? EndTimeUtc { get; set; } + public DateTime? NextFireTimeUtc { get; set; } + public DateTime? PreviousFireTimeUtc { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index d9faced..b9f3470 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -482,6 +482,17 @@ namespace EOM.TSHotelManagement.Migration DataInsDate = DateTime.Now, }, new Menu // 36 + { + Key = "quartzjoblist", + Title = "Quartz任务列表", + Path = "/quartzjoblist", + Parent = 31, + Icon = "OrderedListOutlined", + IsDelete = 0, + DataInsUsr = "System", + DataInsDate = DateTime.Now, + }, + new Menu // 37 { Key = "my", Title = "我的", @@ -492,7 +503,7 @@ namespace EOM.TSHotelManagement.Migration DataInsUsr = "System", DataInsDate = DateTime.Now, }, - new Menu // 37 + new Menu // 38 { Key = "dashboard", Title = "仪表盘", @@ -503,7 +514,7 @@ namespace EOM.TSHotelManagement.Migration DataInsUsr = "System", DataInsDate = DateTime.Now, }, - new Menu // 38 + new Menu // 39 { Key = "promotioncontent", Title = "宣传联动内容", @@ -514,7 +525,7 @@ namespace EOM.TSHotelManagement.Migration DataInsUsr = "System", DataInsDate = DateTime.Now, }, - new Menu // 39 + new Menu // 40 { Key = "requestlog", Title = "请求日志", diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Quartz/IQuartzAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Quartz/IQuartzAppService.cs new file mode 100644 index 0000000..7e20009 --- /dev/null +++ b/EOM.TSHotelManagement.Service/SystemManagement/Quartz/IQuartzAppService.cs @@ -0,0 +1,10 @@ +using EOM.TSHotelManagement.Contract; +using System.Threading.Tasks; + +namespace EOM.TSHotelManagement.Service +{ + public interface IQuartzAppService + { + Task> SelectQuartzJobList(); + } +} diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Quartz/QuartzAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Quartz/QuartzAppService.cs new file mode 100644 index 0000000..9a33109 --- /dev/null +++ b/EOM.TSHotelManagement.Service/SystemManagement/Quartz/QuartzAppService.cs @@ -0,0 +1,100 @@ +using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Contract; +using Quartz; +using Quartz.Impl.Matchers; + +namespace EOM.TSHotelManagement.Service +{ + public class QuartzAppService : IQuartzAppService + { + private readonly ISchedulerFactory _schedulerFactory; + + public QuartzAppService(ISchedulerFactory schedulerFactory) + { + _schedulerFactory = schedulerFactory; + } + + public async Task> SelectQuartzJobList() + { + try + { + var scheduler = await _schedulerFactory.GetScheduler(); + var jobKeys = await scheduler.GetJobKeys(GroupMatcher.AnyGroup()); + var rows = new List(); + + foreach (var jobKey in jobKeys.OrderBy(a => a.Group).ThenBy(a => a.Name)) + { + var jobDetail = await scheduler.GetJobDetail(jobKey); + if (jobDetail == null) + { + continue; + } + + var triggers = await scheduler.GetTriggersOfJob(jobKey); + if (triggers == null || triggers.Count == 0) + { + rows.Add(new ReadQuartzJobOutputDto + { + JobName = jobKey.Name, + JobGroup = jobKey.Group, + JobDescription = jobDetail.Description, + IsDurable = jobDetail.Durable, + RequestsRecovery = jobDetail.RequestsRecovery + }); + continue; + } + + foreach (var trigger in triggers.OrderBy(a => a.Key.Group).ThenBy(a => a.Key.Name)) + { + var state = await scheduler.GetTriggerState(trigger.Key); + var cronTrigger = trigger as ICronTrigger; + var simpleTrigger = trigger as ISimpleTrigger; + + rows.Add(new ReadQuartzJobOutputDto + { + JobName = jobKey.Name, + JobGroup = jobKey.Group, + JobDescription = jobDetail.Description, + IsDurable = jobDetail.Durable, + RequestsRecovery = jobDetail.RequestsRecovery, + TriggerName = trigger.Key.Name, + TriggerGroup = trigger.Key.Group, + TriggerType = trigger.GetType().Name, + TriggerState = state.ToString(), + CronExpression = cronTrigger?.CronExpressionString, + TimeZoneId = cronTrigger?.TimeZone?.Id, + RepeatCount = simpleTrigger?.RepeatCount, + RepeatIntervalMs = simpleTrigger?.RepeatInterval.TotalMilliseconds, + StartTimeUtc = trigger.StartTimeUtc.UtcDateTime, + EndTimeUtc = trigger.EndTimeUtc?.UtcDateTime, + NextFireTimeUtc = trigger.GetNextFireTimeUtc()?.UtcDateTime, + PreviousFireTimeUtc = trigger.GetPreviousFireTimeUtc()?.UtcDateTime + }); + } + } + + return new ListOutputDto + { + Data = new PagedData + { + Items = rows, + TotalCount = rows.Count + } + }; + } + catch (Exception ex) + { + return new ListOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), + Data = new PagedData + { + Items = new List(), + TotalCount = 0 + } + }; + } + } + } +} diff --git a/README.en.md b/README.en.md index 69b9e6b..2eca5a3 100644 --- a/README.en.md +++ b/README.en.md @@ -193,9 +193,9 @@ docker run -d \ |AllowedOrigins__0|Allowed Domain Sites (for Development Environments)|Y|http://localhost:8080|http://localhost:8080| |AllowedOrigins__1|Allowed domain sites for production environment|Y|https://www.yourdomain.com|https://www.yourdomain.com| |SoftwareVersion|Software version number for documentation purposes|N|N/A|N/A| -|JobKeys__0|Quartz Job 1|Y|ReservationExpirationCheckJob|ReservationExpirationCheckJob| -|JobKeys__1|Quartz Job 2|Y|MailServiceCheckJob|MailServiceCheckJob| -|JobKeys__2|Quartz Job 3|Y|RedisServiceCheckJob|RedisServiceCheckJob| +|JobKeys__0|Quartz Job 1|Y|ReservationExpirationCheckJob:0 0 1 * * ?|JobName:CronExpression| +|JobKeys__1|Quartz Job 2|Y|MailServiceCheckJob:0 */5 * * * ?|JobName:CronExpression| +|JobKeys__2|Quartz Job 3|Y|RedisServiceCheckJob:0 */5 * * * ?|JobName:CronExpression| |Redis__Enabled|Enable Redis|N|false|true/false| |Redis__ConnectionString|Redis ConnectString|N|N/A|N/A| |Redis__DefaultDatabase|Default Database of Redis|N|0|0| diff --git a/README.md b/README.md index fb6e5fa..8a70e2e 100644 --- a/README.md +++ b/README.md @@ -193,9 +193,9 @@ docker run -d \ |AllowedOrigins__0|允许域站点,用于开发环境|Y|http://localhost:8080|http://localhost:8080| |AllowedOrigins__1|允许域站点,用于生产环境|Y|https://www.yourdomain.com|https://www.yourdomain.com| |SoftwareVersion|软件版本号,用于标记说明|N|N/A|N/A| -|JobKeys__0|定时任务1|Y|ReservationExpirationCheckJob|ReservationExpirationCheckJob| -|JobKeys__1|定时任务2|Y|MailServiceCheckJob|MailServiceCheckJob| -|JobKeys__2|定时任务3|Y|RedisServiceCheckJob|RedisServiceCheckJob| +|JobKeys__0|定时任务1|Y|ReservationExpirationCheckJob:0 0 1 * * ?|JobName:CronExpression| +|JobKeys__1|定时任务2|Y|MailServiceCheckJob:0 */5 * * * ?|JobName:CronExpression| +|JobKeys__2|定时任务3|Y|RedisServiceCheckJob:0 */5 * * * ?|JobName:CronExpression| |Redis__Enabled|是否启用Redis服务|N|false|true/false| |Redis__ConnectionString|Redis连接字符串|N|N/A|N/A| |Redis__DefaultDatabase|默认数据库|N|0|0| -- Gitee From c6d5efc550e883bdbb852c357f6444bdcb6eab0c Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 7 Mar 2026 02:27:45 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=94=B6=E8=97=8F?= =?UTF-8?q?=E5=A4=B9=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E5=92=8C=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7=E6=94=B6?= =?UTF-8?q?=E8=97=8F=E5=A4=B9=E5=BF=AB=E7=85=A7=E7=9A=84=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=8F=8A=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FavoriteCollectionController.cs | 44 +++ .../Dto/ReadFavoriteCollectionOutputDto.cs | 18 + .../Dto/SaveFavoriteCollectionInputDto.cs | 39 ++ .../Dto/SaveFavoriteCollectionOutputDto.cs | 23 ++ .../DatabaseInitializer.cs | 5 + .../UserFavoriteCollection.cs | 94 +++++ .../EntityBuilder.cs | 19 +- .../FavoriteCollectionService.cs | 344 ++++++++++++++++++ .../IFavoriteCollectionService.cs | 23 ++ 9 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 EOM.TSHotelManagement.API/Controllers/Application/FavoriteCollection/FavoriteCollectionController.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionInputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionOutputDto.cs create mode 100644 EOM.TSHotelManagement.Domain/Application/FavoriteCollection/UserFavoriteCollection.cs create mode 100644 EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs create mode 100644 EOM.TSHotelManagement.Service/Application/FavoriteCollection/IFavoriteCollectionService.cs diff --git a/EOM.TSHotelManagement.API/Controllers/Application/FavoriteCollection/FavoriteCollectionController.cs b/EOM.TSHotelManagement.API/Controllers/Application/FavoriteCollection/FavoriteCollectionController.cs new file mode 100644 index 0000000..8093683 --- /dev/null +++ b/EOM.TSHotelManagement.API/Controllers/Application/FavoriteCollection/FavoriteCollectionController.cs @@ -0,0 +1,44 @@ +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Service; +using Microsoft.AspNetCore.Mvc; + +namespace EOM.TSHotelManagement.WebApi.Controllers +{ + /// + /// 收藏夹持久化接口 + /// + public class FavoriteCollectionController : ControllerBase + { + private readonly IFavoriteCollectionService _favoriteCollectionService; + + /// + /// 构造收藏夹控制器 + /// + /// 收藏夹服务 + public FavoriteCollectionController(IFavoriteCollectionService favoriteCollectionService) + { + _favoriteCollectionService = favoriteCollectionService; + } + + /// + /// 保存当前登录用户的收藏夹快照 + /// + /// 收藏夹保存请求 + /// 保存结果 + [HttpPost] + public SingleOutputDto SaveFavoriteCollection([FromBody] SaveFavoriteCollectionInputDto input) + { + return _favoriteCollectionService.SaveFavoriteCollection(input); + } + + /// + /// 获取当前登录用户的收藏夹快照 + /// + /// 收藏夹读取结果 + [HttpGet] + public SingleOutputDto GetFavoriteCollection() + { + return _favoriteCollectionService.GetFavoriteCollection(); + } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs new file mode 100644 index 0000000..faa23de --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs @@ -0,0 +1,18 @@ +namespace EOM.TSHotelManagement.Contract +{ + /// + /// 读取收藏夹响应 DTO + /// + public class ReadFavoriteCollectionOutputDto + { + /// + /// 收藏路由列表 + /// + public List FavoriteRoutes { get; set; } = new(); + + /// + /// 收藏夹最后更新时间 + /// + public DateTime? UpdatedAt { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionInputDto.cs b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionInputDto.cs new file mode 100644 index 0000000..75fe7c4 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionInputDto.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.DataAnnotations; + +namespace EOM.TSHotelManagement.Contract +{ + /// + /// 保存收藏夹请求 DTO + /// + public class SaveFavoriteCollectionInputDto + { + /// + /// 登录类型,前端可能传 admin 或 employee + /// + [MaxLength(32, ErrorMessage = "LoginType length cannot exceed 32 characters.")] + public string? LoginType { get; set; } + + /// + /// 前端当前账号 + /// + [MaxLength(128, ErrorMessage = "Account length cannot exceed 128 characters.")] + public string? Account { get; set; } + + /// + /// 当前完整收藏路由列表 + /// + [Required(ErrorMessage = "FavoriteRoutes is required.")] + public List FavoriteRoutes { get; set; } = new(); + + /// + /// 前端最后一次修改收藏夹的时间 + /// + public DateTime? UpdatedAt { get; set; } + + /// + /// 触发来源,例如 logout、pagehide、beforeunload、manual + /// + [MaxLength(32, ErrorMessage = "TriggeredBy length cannot exceed 32 characters.")] + public string? TriggeredBy { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionOutputDto.cs new file mode 100644 index 0000000..830f7f2 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionOutputDto.cs @@ -0,0 +1,23 @@ +namespace EOM.TSHotelManagement.Contract +{ + /// + /// 保存收藏夹响应 DTO + /// + public class SaveFavoriteCollectionOutputDto + { + /// + /// 是否保存成功 + /// + public bool Saved { get; set; } + + /// + /// 保存后的收藏数量 + /// + public int RouteCount { get; set; } + + /// + /// 最终生效的更新时间 + /// + public DateTime UpdatedAt { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index 0506d77..5e931f8 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -283,6 +283,7 @@ namespace EOM.TSHotelManagement.Data PromotionContent _ => 9, Administrator _ => 10, Employee _ => 11, + UserFavoriteCollection _ => 12, _ => 99 }) .ToList(); @@ -343,6 +344,10 @@ namespace EOM.TSHotelManagement.Data alreadyExists = db.Queryable().Any(a => a.EmployeeId == employee.EmployeeId); break; + case UserFavoriteCollection favoriteCollection: + alreadyExists = db.Queryable().Any(a => a.UserNumber == favoriteCollection.UserNumber); + break; + case Permission permission: alreadyExists = db.Queryable().Any(a => a.PermissionNumber == permission.PermissionNumber); break; diff --git a/EOM.TSHotelManagement.Domain/Application/FavoriteCollection/UserFavoriteCollection.cs b/EOM.TSHotelManagement.Domain/Application/FavoriteCollection/UserFavoriteCollection.cs new file mode 100644 index 0000000..3e8412a --- /dev/null +++ b/EOM.TSHotelManagement.Domain/Application/FavoriteCollection/UserFavoriteCollection.cs @@ -0,0 +1,94 @@ +using SqlSugar; + +namespace EOM.TSHotelManagement.Domain +{ + /// + /// 用户收藏夹快照实体 + /// + [SugarTable("user_favorite_collection", "User favorite collection snapshot", true)] + public class UserFavoriteCollection : AuditEntity + { + /// + /// 主键 + /// + [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "Id")] + public int Id { get; set; } + + /// + /// JWT 中的用户编号 + /// + [SugarColumn( + ColumnName = "user_number", + Length = 128, + IsNullable = false, + UniqueGroupNameList = new[] { "UK_user_favorite_collection_user_number" }, + ColumnDescription = "User number resolved from JWT" + )] + public string UserNumber { get; set; } = string.Empty; + + /// + /// 登录类型 + /// + [SugarColumn( + ColumnName = "login_type", + Length = 32, + IsNullable = true, + ColumnDescription = "Login type" + )] + public string? LoginType { get; set; } + + /// + /// 当前账号 + /// + [SugarColumn( + ColumnName = "account", + Length = 128, + IsNullable = true, + ColumnDescription = "Account" + )] + public string? Account { get; set; } + + /// + /// 收藏路由 JSON 快照 + /// + [SugarColumn( + ColumnName = "favorite_routes_json", + ColumnDataType = "text", + IsNullable = false, + ColumnDescription = "Favorite routes JSON snapshot" + )] + public string FavoriteRoutesJson { get; set; } = "[]"; + + /// + /// 收藏数量 + /// + [SugarColumn( + ColumnName = "route_count", + IsNullable = false, + DefaultValue = "0", + ColumnDescription = "Favorite route count" + )] + public int RouteCount { get; set; } + + /// + /// 业务更新时间 + /// + [SugarColumn( + ColumnName = "updated_at", + IsNullable = false, + ColumnDescription = "Snapshot updated time from client" + )] + public DateTime UpdatedAt { get; set; } + + /// + /// 最后触发来源 + /// + [SugarColumn( + ColumnName = "triggered_by", + Length = 32, + IsNullable = true, + ColumnDescription = "Last trigger source" + )] + public string? TriggeredBy { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index b9f3470..3c26813 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -52,6 +52,7 @@ namespace EOM.TSHotelManagement.Migration typeof(Menu), typeof(Nation), typeof(NavBar), + typeof(UserFavoriteCollection), typeof(OperationLog), typeof(Position), typeof(PromotionContent), @@ -540,7 +541,7 @@ namespace EOM.TSHotelManagement.Migration { NavigationBarName = "客房管理", NavigationBarOrder = 1, - NavigationBarImage = null, + NavigationBarImage = string.Empty, NavigationBarEvent = "RoomManager_Event", IsDelete = 0, MarginLeft = 0, @@ -551,7 +552,7 @@ namespace EOM.TSHotelManagement.Migration { NavigationBarName = "客户管理", NavigationBarOrder = 2, - NavigationBarImage = null, + NavigationBarImage = string.Empty, NavigationBarEvent = "CustomerManager_Event", IsDelete = 0, MarginLeft = 120, @@ -562,7 +563,7 @@ namespace EOM.TSHotelManagement.Migration { NavigationBarName = "商品消费", NavigationBarOrder = 3, - NavigationBarImage = null, + NavigationBarImage = string.Empty, NavigationBarEvent = "SellManager_Event", IsDelete = 0, MarginLeft = 120, @@ -635,6 +636,18 @@ namespace EOM.TSHotelManagement.Migration DataInsUsr = "System", DataInsDate = DateTime.Now }, + new UserFavoriteCollection + { + UserNumber = "WK010", + LoginType = "employee", + Account = "WK010", + FavoriteRoutesJson = "[\"/roommap\"]", + RouteCount = 1, + UpdatedAt = DateTime.UtcNow, + TriggeredBy = "seed", + DataInsUsr = "System", + DataInsDate = DateTime.Now + }, new PromotionContent { PromotionContentNumber = "PC-000001", diff --git a/EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs new file mode 100644 index 0000000..561bba6 --- /dev/null +++ b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs @@ -0,0 +1,344 @@ +using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Data; +using EOM.TSHotelManagement.Domain; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System.Security.Claims; +using System.Text.Json; + +namespace EOM.TSHotelManagement.Service +{ + /// + /// 收藏夹服务实现 + /// + public class FavoriteCollectionService : IFavoriteCollectionService + { + private static readonly JsonSerializerOptions JsonSerializerOptions = new(JsonSerializerDefaults.Web); + + private readonly GenericRepository _favoriteCollectionRepository; + private readonly GenericRepository _administratorRepository; + private readonly GenericRepository _employeeRepository; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ILogger _logger; + + /// + /// 构造收藏夹服务 + /// + /// 收藏夹仓储 + /// 管理员仓储 + /// 员工仓储 + /// HTTP 上下文访问器 + /// 日志组件 + public FavoriteCollectionService( + GenericRepository favoriteCollectionRepository, + GenericRepository administratorRepository, + GenericRepository employeeRepository, + IHttpContextAccessor httpContextAccessor, + ILogger logger) + { + _favoriteCollectionRepository = favoriteCollectionRepository; + _administratorRepository = administratorRepository; + _employeeRepository = employeeRepository; + _httpContextAccessor = httpContextAccessor; + _logger = logger; + } + + /// + /// 保存当前登录用户的收藏夹快照 + /// + /// 收藏夹保存请求 + /// 保存结果 + public SingleOutputDto SaveFavoriteCollection(SaveFavoriteCollectionInputDto input) + { + input ??= new SaveFavoriteCollectionInputDto(); + + try + { + var currentUser = ResolveCurrentUser(input); + if (currentUser == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.Unauthorized, + Message = LocalizationHelper.GetLocalizedString("Unauthorized.", "Unauthorized."), + Data = null + }; + } + + LogIdentityMismatchIfNeeded(currentUser, input); + + var normalizedRoutes = NormalizeRoutes(input.FavoriteRoutes); + var normalizedUpdatedAt = NormalizeUpdatedAt(input.UpdatedAt); + var normalizedTriggeredBy = NormalizeText(input.TriggeredBy, 32); + var favoriteRoutesJson = JsonSerializer.Serialize(normalizedRoutes, JsonSerializerOptions); + + var saveSuccess = TrySaveSnapshot(currentUser, favoriteRoutesJson, normalizedRoutes.Count, normalizedUpdatedAt, normalizedTriggeredBy); + if (!saveSuccess) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString("Failed to save favorite collection.", "Failed to save favorite collection."), + Data = null + }; + } + + return new SingleOutputDto + { + Message = LocalizationHelper.GetLocalizedString("Favorite collection saved.", "Favorite collection saved."), + Data = new SaveFavoriteCollectionOutputDto + { + Saved = true, + RouteCount = normalizedRoutes.Count, + UpdatedAt = normalizedUpdatedAt + } + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to save favorite collection."); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString("Failed to save favorite collection.", "Failed to save favorite collection."), + Data = null + }; + } + } + + /// + /// 获取当前登录用户的收藏夹快照 + /// + /// 收藏夹读取结果 + public SingleOutputDto GetFavoriteCollection() + { + try + { + var currentUser = ResolveCurrentUser(); + if (currentUser == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.Unauthorized, + Message = LocalizationHelper.GetLocalizedString("Unauthorized.", "Unauthorized."), + Data = null + }; + } + + var collection = _favoriteCollectionRepository.GetFirst(x => x.UserNumber == currentUser.UserNumber); + if (collection == null) + { + return new SingleOutputDto + { + Message = "OK", + Data = new ReadFavoriteCollectionOutputDto() + }; + } + + return new SingleOutputDto + { + Message = "OK", + Data = new ReadFavoriteCollectionOutputDto + { + FavoriteRoutes = DeserializeRoutes(collection.FavoriteRoutesJson), + UpdatedAt = DateTime.SpecifyKind(collection.UpdatedAt, DateTimeKind.Utc) + } + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to get favorite collection."); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString("Failed to get favorite collection.", "Failed to get favorite collection."), + Data = null + }; + } + } + + private bool TrySaveSnapshot( + CurrentUserSnapshot currentUser, + string favoriteRoutesJson, + int routeCount, + DateTime updatedAt, + string? triggeredBy) + { + const int maxRetryCount = 3; + + for (var attempt = 1; attempt <= maxRetryCount; attempt++) + { + var existing = _favoriteCollectionRepository.GetFirst(x => x.UserNumber == currentUser.UserNumber); + + if (existing == null) + { + var entity = new UserFavoriteCollection + { + UserNumber = currentUser.UserNumber, + LoginType = currentUser.LoginType, + Account = currentUser.Account, + FavoriteRoutesJson = favoriteRoutesJson, + RouteCount = routeCount, + UpdatedAt = updatedAt, + TriggeredBy = triggeredBy + }; + + try + { + if (_favoriteCollectionRepository.Insert(entity)) + { + return true; + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Insert favorite collection snapshot failed on attempt {Attempt} for user {UserNumber}.", attempt, currentUser.UserNumber); + } + + continue; + } + + existing.LoginType = currentUser.LoginType; + existing.Account = currentUser.Account; + existing.FavoriteRoutesJson = favoriteRoutesJson; + existing.RouteCount = routeCount; + existing.UpdatedAt = updatedAt; + existing.TriggeredBy = triggeredBy; + + if (_favoriteCollectionRepository.Update(existing)) + { + return true; + } + + _logger.LogWarning("Favorite collection update hit a concurrency conflict on attempt {Attempt} for user {UserNumber}.", attempt, currentUser.UserNumber); + } + + return false; + } + + private CurrentUserSnapshot? ResolveCurrentUser(SaveFavoriteCollectionInputDto? input = null) + { + var principal = _httpContextAccessor.HttpContext?.User; + var userNumber = principal?.FindFirst(ClaimTypes.SerialNumber)?.Value + ?? principal?.FindFirst("serialnumber")?.Value + ?? principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + + if (string.IsNullOrWhiteSpace(userNumber)) + { + return null; + } + + var administrator = _administratorRepository.GetFirst(x => x.Number == userNumber && x.IsDelete != 1); + if (administrator != null) + { + return new CurrentUserSnapshot(userNumber, "admin", administrator.Account); + } + + var employee = _employeeRepository.GetFirst(x => x.EmployeeId == userNumber && x.IsDelete != 1); + if (employee != null) + { + return new CurrentUserSnapshot(userNumber, "employee", employee.EmployeeId); + } + + var account = principal?.FindFirst("account")?.Value; + var loginType = NormalizeText(input?.LoginType, 32) ?? "unknown"; + var fallbackAccount = NormalizeText(account, 128) ?? NormalizeText(input?.Account, 128); + + return new CurrentUserSnapshot(userNumber, loginType, fallbackAccount); + } + + private void LogIdentityMismatchIfNeeded(CurrentUserSnapshot currentUser, SaveFavoriteCollectionInputDto input) + { + var requestAccount = NormalizeText(input.Account, 128); + var requestLoginType = NormalizeText(input.LoginType, 32); + + if (!string.IsNullOrWhiteSpace(requestAccount) + && !string.Equals(requestAccount, currentUser.Account, StringComparison.OrdinalIgnoreCase)) + { + _logger.LogInformation( + "Favorite collection request account mismatch. UserNumber={UserNumber}, RequestAccount={RequestAccount}, ResolvedAccount={ResolvedAccount}.", + currentUser.UserNumber, + requestAccount, + currentUser.Account); + } + + if (!string.IsNullOrWhiteSpace(requestLoginType) + && !string.Equals(requestLoginType, currentUser.LoginType, StringComparison.OrdinalIgnoreCase)) + { + _logger.LogInformation( + "Favorite collection request login type mismatch. UserNumber={UserNumber}, RequestLoginType={RequestLoginType}, ResolvedLoginType={ResolvedLoginType}.", + currentUser.UserNumber, + requestLoginType, + currentUser.LoginType); + } + } + + private static List NormalizeRoutes(IEnumerable? routes) + { + var result = new List(); + var uniqueRoutes = new HashSet(StringComparer.Ordinal); + + foreach (var route in routes ?? Enumerable.Empty()) + { + var normalizedRoute = NormalizeText(route, 2048); + if (string.IsNullOrWhiteSpace(normalizedRoute)) + { + continue; + } + + if (uniqueRoutes.Add(normalizedRoute)) + { + result.Add(normalizedRoute); + } + } + + return result; + } + + private static List DeserializeRoutes(string? favoriteRoutesJson) + { + if (string.IsNullOrWhiteSpace(favoriteRoutesJson)) + { + return new List(); + } + + try + { + return JsonSerializer.Deserialize>(favoriteRoutesJson, JsonSerializerOptions) ?? new List(); + } + catch + { + return new List(); + } + } + + private static DateTime NormalizeUpdatedAt(DateTime? updatedAt) + { + if (!updatedAt.HasValue) + { + return DateTime.UtcNow; + } + + return updatedAt.Value.Kind switch + { + DateTimeKind.Utc => updatedAt.Value, + DateTimeKind.Local => updatedAt.Value.ToUniversalTime(), + _ => DateTime.SpecifyKind(updatedAt.Value, DateTimeKind.Utc) + }; + } + + private static string? NormalizeText(string? value, int maxLength) + { + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + var trimmed = value.Trim(); + return trimmed.Length <= maxLength ? trimmed : trimmed[..maxLength]; + } + + private sealed record CurrentUserSnapshot(string UserNumber, string LoginType, string? Account); + } +} diff --git a/EOM.TSHotelManagement.Service/Application/FavoriteCollection/IFavoriteCollectionService.cs b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/IFavoriteCollectionService.cs new file mode 100644 index 0000000..cdb5e39 --- /dev/null +++ b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/IFavoriteCollectionService.cs @@ -0,0 +1,23 @@ +using EOM.TSHotelManagement.Contract; + +namespace EOM.TSHotelManagement.Service +{ + /// + /// 收藏夹服务接口 + /// + public interface IFavoriteCollectionService + { + /// + /// 保存当前用户的收藏夹快照 + /// + /// 收藏夹保存请求 + /// 保存结果 + SingleOutputDto SaveFavoriteCollection(SaveFavoriteCollectionInputDto input); + + /// + /// 获取当前用户的收藏夹快照 + /// + /// 收藏夹读取结果 + SingleOutputDto GetFavoriteCollection(); + } +} -- Gitee From aa56e5d9883a8d1e3c8fdf6860edb46aad055986 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 7 Mar 2026 19:26:10 +0800 Subject: [PATCH 08/20] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=9D=83=E9=99=90?= =?UTF-8?q?=E3=80=81=E5=88=86=E9=A1=B5=E4=BC=98=E5=8C=96=E5=8F=8A=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E6=89=93=E5=8D=A1=E4=B8=9A=E5=8A=A1=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次提交包括: - 新增多模块导出权限(xxx.export),支持数据导出权限控制 - 分页逻辑统一为 IgnorePaging,支持全量数据返回 - 员工打卡业务重构,自动生成打卡编号/方式/状态,避免重复打卡,增强本地化提示 - 配置文件调整:MariaDB连接、JWT密钥与有效期、数据库初始化 - 新增打卡方式常量类 CheckTypeConstant - 代码规范优化,移除 BOM --- .../Constant/CheckTypeConstant.cs | 22 +++++ .../CreateEmployeeCheckInputDto.cs | 24 ----- .../EntityBuilder.cs | 25 ++++++ .../Business/Asset/AssetService.cs | 2 +- .../Employee/Check/EmployeeCheckService.cs | 89 +++++++++++++++++-- .../RewardPunishmentService.cs | 4 +- .../SystemManagement/Notice/NoticeService.cs | 12 ++- .../SupervisionStatisticsService.cs | 11 ++- .../VipRule/VipRuleAppService.cs | 14 ++- .../Util/UtilService.cs | 4 +- 10 files changed, 164 insertions(+), 43 deletions(-) create mode 100644 EOM.TSHotelManagement.Common/Constant/CheckTypeConstant.cs diff --git a/EOM.TSHotelManagement.Common/Constant/CheckTypeConstant.cs b/EOM.TSHotelManagement.Common/Constant/CheckTypeConstant.cs new file mode 100644 index 0000000..9568ac6 --- /dev/null +++ b/EOM.TSHotelManagement.Common/Constant/CheckTypeConstant.cs @@ -0,0 +1,22 @@ +using EOM.TSHotelManagement.Infrastructure; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Common; + +public class CheckTypeConstant : CodeConstantBase +{ + /// + /// 客户端 + /// + public static readonly CheckTypeConstant Client = new CheckTypeConstant("Client", "客户端"); + /// + /// 网页端 + /// + public static readonly CheckTypeConstant Web = new CheckTypeConstant("Web", "网页端"); + private CheckTypeConstant(string code, string description) : base(code, description) + { + + } +} diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/CreateEmployeeCheckInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/CreateEmployeeCheckInputDto.cs index 7f2e1f5..d0d7526 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/CreateEmployeeCheckInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/CreateEmployeeCheckInputDto.cs @@ -4,36 +4,12 @@ namespace EOM.TSHotelManagement.Contract { public class CreateEmployeeCheckInputDto : BaseInputDto { - /// - /// 打卡编号 (Check-in/Check-out Number) - /// - [Required(ErrorMessage = "打卡编号为必填字段")] - [MaxLength(128, ErrorMessage = "打卡编号长度不超过128字符")] - public string CheckNumber { get; set; } /// /// 员工工号 (Employee ID) /// [Required(ErrorMessage = "员工工号为必填字段")] [MaxLength(128, ErrorMessage = "员工工号长度不超过128字符")] public string EmployeeId { get; set; } - - /// - /// 打卡时间 (Check-in/Check-out Time) - /// - [Required(ErrorMessage = "打卡时间为必填字段")] - public DateTime CheckTime { get; set; } - - /// - /// 打卡方式 (Check-in/Check-out Method) - /// - [Required(ErrorMessage = "打卡方式为必填字段")] - public string CheckMethod { get; set; } - - /// - /// 打卡状态 (Check-in/Check-out Status) - /// - [Required(ErrorMessage = "打卡状态为必填字段")] - public int CheckStatus { get; set; } } } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 3c26813..aee7c12 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -688,18 +688,21 @@ namespace EOM.TSHotelManagement.Migration // 部门 new Permission { PermissionNumber = "department.create", PermissionName = "新增部门", Module = "basic", Description = "基础信息-部门-新增", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "department.delete", PermissionName = "删除部门", Module = "basic", Description = "基础信息-部门-删除", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "department.export", PermissionName = "导出部门", Module = "basic", Description = "基础信息-部门-导出列表", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "department.update", PermissionName = "更新部门", Module = "basic", Description = "基础信息-部门-更新", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "department.view", PermissionName = "查询部门列表", Module = "basic", Description = "基础信息-部门-查询列表", MenuKey = "department", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 民族 new Permission { PermissionNumber = "nation.create", PermissionName = "新增民族", Module = "basic", Description = "基础信息-民族-新增", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "nation.delete", PermissionName = "删除民族", Module = "basic", Description = "基础信息-民族-删除", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "nation.export", PermissionName = "导出民族", Module = "basic", Description = "基础信息-民族-导出列表", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "nation.update", PermissionName = "更新民族", Module = "basic", Description = "基础信息-民族-更新", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "nation.view", PermissionName = "查询民族列表", Module = "basic", Description = "基础信息-民族-查询列表", MenuKey = "nation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 证件类型 new Permission { PermissionNumber = "passport.create", PermissionName = "新增证件类型", Module = "basic", Description = "基础信息-证件类型-新增", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "passport.delete", PermissionName = "删除证件类型", Module = "basic", Description = "基础信息-证件类型-删除", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "passport.export", PermissionName = "导出证件类型", Module = "basic", Description = "基础信息-证件类型-导出列表", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "passport.update", PermissionName = "更新证件类型", Module = "basic", Description = "基础信息-证件类型-更新", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "passport.view", PermissionName = "查询证件类型列表", Module = "basic", Description = "基础信息-证件类型-查询列表", MenuKey = "passport", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -712,18 +715,21 @@ namespace EOM.TSHotelManagement.Migration // 学历 new Permission { PermissionNumber = "qualification.create", PermissionName = "新增学历", Module = "basic", Description = "基础信息-学历-新增", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "qualification.delete", PermissionName = "删除学历", Module = "basic", Description = "基础信息-学历-删除", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "qualification.export", PermissionName = "导出学历", Module = "basic", Description = "基础信息-学历-导出列表", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "qualification.update", PermissionName = "更新学历", Module = "basic", Description = "基础信息-学历-更新", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "qualification.view", PermissionName = "查询学历列表", Module = "basic", Description = "基础信息-学历-查询列表", MenuKey = "qualification", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 公告类型 new Permission { PermissionNumber = "noticetype.create", PermissionName = "添加公告类型", Module = "basic", Description = "添加公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "noticetype.delete", PermissionName = "删除公告类型", Module = "basic", Description = "删除公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "noticetype.export", PermissionName = "导出公告类型", Module = "basic", Description = "导出公告类型列表", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "noticetype.update", PermissionName = "更新公告类型", Module = "basic", Description = "更新公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "noticetype.view", PermissionName = "查询所有公告类型", Module = "basic", Description = "查询所有公告类型", MenuKey = "noticetype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 宣传联动内容 new Permission { PermissionNumber = "promotioncontent.apc", PermissionName = "添加宣传联动内容", Module = "basic", Description = "添加宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "promotioncontent.dpc", PermissionName = "删除宣传联动内容", Module = "basic", Description = "删除宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "promotioncontent.export", PermissionName = "导出宣传联动内容", Module = "basic", Description = "导出宣传联动内容列表", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "promotioncontent.spca", PermissionName = "查询所有宣传联动内容", Module = "basic", Description = "查询所有宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "promotioncontent.spcs", PermissionName = "查询所有宣传联动内容(跑马灯)", Module = "basic", Description = "查询所有宣传联动内容(跑马灯)", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "promotioncontent.upc", PermissionName = "更新宣传联动内容", Module = "basic", Description = "更新宣传联动内容", MenuKey = "promotioncontent", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -732,6 +738,7 @@ namespace EOM.TSHotelManagement.Migration // 资产信息管理 new Permission { PermissionNumber = "internalfinance.aai", PermissionName = "添加资产信息", Module = "internalfinance", Description = "添加资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.dai", PermissionName = "删除资产信息", Module = "internalfinance", Description = "删除资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "internalfinance.export", PermissionName = "导出资产信息", Module = "internalfinance", Description = "导出资产信息列表", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.saia", PermissionName = "查询资产信息", Module = "internalfinance", Description = "查询资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "internalfinance.uai", PermissionName = "更新资产信息", Module = "internalfinance", Description = "更新资产信息", MenuKey = "internalfinance", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -746,6 +753,7 @@ namespace EOM.TSHotelManagement.Migration // Hydroelectricity (水电信息管理) // 水电费信息管理 new Permission { PermissionNumber = "hydroelectricinformation.demi", PermissionName = "删除水电费信息", Module = "hydroelectricity", Description = "删除水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "hydroelectricinformation.export", PermissionName = "导出水电费信息", Module = "hydroelectricity", Description = "导出水电费信息列表", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "hydroelectricinformation.iemi", PermissionName = "添加水电费信息", Module = "hydroelectricity", Description = "添加水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "hydroelectricinformation.semi", PermissionName = "查询水电费信息", Module = "hydroelectricity", Description = "查询水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "hydroelectricinformation.uemi", PermissionName = "修改水电费信息", Module = "hydroelectricity", Description = "修改水电费信息", MenuKey = "hydroelectricinformation", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -754,6 +762,7 @@ namespace EOM.TSHotelManagement.Migration // Supervision (监管统计管理) // 监管统计信息管理 new Permission { PermissionNumber = "supervisioninfo.dss", PermissionName = "删除监管统计信息", Module = "supervision", Description = "删除监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "supervisioninfo.export", PermissionName = "导出监管统计信息", Module = "supervision", Description = "导出监管统计信息列表", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "supervisioninfo.iss", PermissionName = "插入监管统计信息", Module = "supervision", Description = "插入监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "supervisioninfo.sssa", PermissionName = "查询所有监管统计信息", Module = "supervision", Description = "查询所有监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "supervisioninfo.uss", PermissionName = "更新监管统计信息", Module = "supervision", Description = "更新监管统计信息", MenuKey = "supervisioninfo", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -766,6 +775,7 @@ namespace EOM.TSHotelManagement.Migration new Permission { PermissionNumber = "roommanagement.cr", PermissionName = "退房操作", Module = "room", Description = "退房操作", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roommanagement.dbrn", PermissionName = "根据房间编号查询截止到今天住了多少天", Module = "room", Description = "根据房间编号查询截止到今天住了多少天", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roommanagement.deleteroom", PermissionName = "删除房间", Module = "room", Description = "删除房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roommanagement.export", PermissionName = "导出房间信息", Module = "room", Description = "导出房间信息列表", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roommanagement.insertroom", PermissionName = "添加房间", Module = "room", Description = "添加房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roommanagement.scura", PermissionName = "根据房间状态来查询可使用的房间", Module = "room", Description = "根据房间状态来查询可使用的房间", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roommanagement.scurabrs", PermissionName = "查询可入住房间数量", Module = "room", Description = "查询可入住房间数量", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -785,12 +795,14 @@ namespace EOM.TSHotelManagement.Migration new Permission { PermissionNumber = "roommanagement.ursbrn", PermissionName = "根据房间编号更改房间状态", Module = "room", Description = "根据房间编号更改房间状态", MenuKey = "roommanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 房间配置管理 new Permission { PermissionNumber = "roomconfig.drt", PermissionName = "删除房间配置", Module = "room", Description = "删除房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "roomconfig.export", PermissionName = "导出房间配置", Module = "room", Description = "导出房间配置列表", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roomconfig.irt", PermissionName = "添加房间配置", Module = "room", Description = "添加房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roomconfig.srtbrn", PermissionName = "根据房间编号查询房间类型名称", Module = "room", Description = "根据房间编号查询房间类型名称", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roomconfig.srta", PermissionName = "获取所有房间类型", Module = "room", Description = "获取所有房间类型", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "roomconfig.urt", PermissionName = "更新房间配置", Module = "room", Description = "更新房间配置", MenuKey = "roomconfig", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 预约信息管理 new Permission { PermissionNumber = "resermanagement.dri", PermissionName = "删除预约信息", Module = "room", Description = "删除预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "resermanagement.export", PermissionName = "导出预约信息", Module = "room", Description = "导出预约信息列表", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "resermanagement.iri", PermissionName = "添加预约信息", Module = "room", Description = "添加预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "resermanagement.sra", PermissionName = "获取所有预约信息", Module = "room", Description = "获取所有预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "resermanagement.sribrn", PermissionName = "根据房间编号获取预约信息", Module = "room", Description = "根据房间编号获取预约信息", MenuKey = "resermanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -802,11 +814,13 @@ namespace EOM.TSHotelManagement.Migration // 会员等级规则管理 new Permission { PermissionNumber = "viplevel.addviprule", PermissionName = "添加会员等级规则", Module = "customer", Description = "添加会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "viplevel.delviprule", PermissionName = "删除会员等级规则", Module = "customer", Description = "删除会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "viplevel.export", PermissionName = "导出会员等级规则", Module = "customer", Description = "导出会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "viplevel.svr", PermissionName = "查询会员等级规则", Module = "customer", Description = "查询会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "viplevel.svrlist", PermissionName = "查询会员等级规则列表", Module = "customer", Description = "查询会员等级规则列表", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "viplevel.updviprule", PermissionName = "更新会员等级规则", Module = "customer", Description = "更新会员等级规则", MenuKey = "viplevel", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户信息 new Permission { PermissionNumber = "customer.dci", PermissionName = "删除客户信息", Module = "customer", Description = "删除客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customer.export", PermissionName = "导出客户信息", Module = "customer", Description = "导出客户信息列表", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customer.ici", PermissionName = "添加客户信息", Module = "customer", Description = "添加客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customer.scbi", PermissionName = "查询指定客户信息", Module = "customer", Description = "查询指定客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customer.scs", PermissionName = "查询所有客户信息", Module = "customer", Description = "查询所有客户信息", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -814,6 +828,7 @@ namespace EOM.TSHotelManagement.Migration new Permission { PermissionNumber = "customer.uctbcn", PermissionName = "更新会员等级", Module = "customer", Description = "更新会员等级", MenuKey = "customer", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 客户消费信息 new Permission { PermissionNumber = "customerspend.acs", PermissionName = "添加客户消费信息", Module = "customer", Description = "添加客户消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customerspend.export", PermissionName = "导出客户消费信息", Module = "customer", Description = "导出客户消费信息列表", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customerspend.ssbrn", PermissionName = "查询房间消费信息", Module = "customer", Description = "查询房间消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customerspend.ssia", PermissionName = "查询所有消费信息", Module = "customer", Description = "查询所有消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customerspend.shsia", PermissionName = "查询客户历史消费信息", Module = "customer", Description = "查询客户历史消费信息", MenuKey = "customerspend", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -823,6 +838,7 @@ namespace EOM.TSHotelManagement.Migration // 客户类型 new Permission { PermissionNumber = "customertype.create", PermissionName = "新增客户类型", Module = "customer", Description = "基础信息-客户类型-新增", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customertype.delete", PermissionName = "删除客户类型", Module = "customer", Description = "基础信息-客户类型-删除", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "customertype.export", PermissionName = "导出客户类型", Module = "customer", Description = "基础信息-客户类型-导出列表", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customertype.update", PermissionName = "更新客户类型", Module = "customer", Description = "基础信息-客户类型-更新", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "customertype.view", PermissionName = "查询客户类型列表", Module = "customer", Description = "基础信息-客户类型-查询列表", MenuKey = "customertype", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -830,6 +846,7 @@ namespace EOM.TSHotelManagement.Migration // Human resource (酒店人事管理) // 员工管理 new Permission { PermissionNumber = "staffmanagement.ae", PermissionName = "添加员工信息", Module = "humanresource", Description = "添加员工信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.export", PermissionName = "导出员工信息", Module = "humanresource", Description = "导出员工信息列表", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.mea", PermissionName = "员工账号禁/启用", Module = "humanresource", Description = "员工账号禁/启用", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.reap", PermissionName = "重置员工账号密码", Module = "humanresource", Description = "重置员工账号密码", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.sea", PermissionName = "获取所有工作人员信息", Module = "humanresource", Description = "获取所有工作人员信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -860,6 +877,7 @@ namespace EOM.TSHotelManagement.Migration // Material management (酒店物资管理) // 商品管理 new Permission { PermissionNumber = "goodsmanagement.dst", PermissionName = "删除商品信息", Module = "material", Description = "删除商品信息", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "goodsmanagement.export", PermissionName = "导出商品信息", Module = "material", Description = "导出商品信息列表", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "goodsmanagement.ist", PermissionName = "添加商品", Module = "material", Description = "添加商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "goodsmanagement.ssta", PermissionName = "查询所有商品", Module = "material", Description = "查询所有商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "goodsmanagement.sstbnap", PermissionName = "根据商品名称和价格查询商品编号", Module = "material", Description = "根据商品名称和价格查询商品编号", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -869,9 +887,11 @@ namespace EOM.TSHotelManagement.Migration // Operation management (行为操作管理) // 操作日志 new Permission { PermissionNumber = "operationlog.delete", PermissionName = "删除时间范围的操作日志", Module = "operation", Description = "删除时间范围的操作日志", MenuKey = "operationlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "operationlog.export", PermissionName = "导出操作日志", Module = "operation", Description = "导出操作日志列表", MenuKey = "operationlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "operationlog.view", PermissionName = "查询所有操作日志", Module = "operation", Description = "查询所有操作日志", MenuKey = "operationlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 请求日志 new Permission { PermissionNumber = "requestlog.delete", PermissionName = "删除时间范围的请求日志", Module = "operation", Description = "删除时间范围的请求日志", MenuKey = "requestlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "requestlog.export", PermissionName = "导出请求日志", Module = "operation", Description = "导出请求日志列表", MenuKey = "requestlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "requestlog.view", PermissionName = "查询所有请求日志", Module = "operation", Description = "查询所有请求日志", MenuKey = "requestlog", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -879,11 +899,13 @@ namespace EOM.TSHotelManagement.Migration // 管理员管理 new Permission { PermissionNumber = "system:admin:addadmin", PermissionName = "添加管理员", Module = "system", Description = "添加管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:deladmin", PermissionName = "删除管理员", Module = "system", Description = "删除管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admin:export", PermissionName = "导出管理员", Module = "system", Description = "导出管理员列表", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:gaal", PermissionName = "获取所有管理员列表", Module = "system", Description = "获取所有管理员列表", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admin:updadmin", PermissionName = "更新管理员", Module = "system", Description = "更新管理员", MenuKey = "administratormanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 管理员类型管理 new Permission { PermissionNumber = "system:admintype:aat", PermissionName = "添加管理员类型", Module = "system", Description = "添加管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:dat", PermissionName = "删除管理员类型", Module = "system", Description = "删除管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:admintype:export", PermissionName = "导出管理员类型", Module = "system", Description = "导出管理员类型列表", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:gaat", PermissionName = "获取所有管理员类型", Module = "system", Description = "获取所有管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:admintype:uat", PermissionName = "更新管理员类型", Module = "system", Description = "更新管理员类型", MenuKey = "admintypemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 管理员两步验证管理 @@ -895,6 +917,7 @@ namespace EOM.TSHotelManagement.Migration // 角色管理 new Permission { PermissionNumber = "system:role:aru", PermissionName = "为角色分配管理员(全量覆盖)", Module = "system", Description = "为角色分配管理员(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:deleterole", PermissionName = "删除角色", Module = "system", Description = "删除角色", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:role:export", PermissionName = "导出角色", Module = "system", Description = "导出角色列表", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:grp", PermissionName = "为角色授予权限(全量覆盖)", Module = "system", Description = "为角色授予权限(全量覆盖)", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:insertrole", PermissionName = "添加角色", Module = "system", Description = "添加角色", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "system:role:rrp", PermissionName = "读取指定角色已授予的权限编码集合", Module = "system", Description = "读取指定角色已授予的权限编码集合", MenuKey = "rolemanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, @@ -905,9 +928,11 @@ namespace EOM.TSHotelManagement.Migration // 菜单管理 new Permission { PermissionNumber = "menumanagement.bma", PermissionName = "构建菜单树", Module = "system", Description = "构建菜单树", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "menumanagement.deletemenu", PermissionName = "删除菜单", Module = "system", Description = "删除菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "menumanagement.export", PermissionName = "导出菜单", Module = "system", Description = "导出菜单列表", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "menumanagement.insertmenu", PermissionName = "插入菜单", Module = "system", Description = "插入菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "menumanagement.sma", PermissionName = "查询所有菜单信息", Module = "system", Description = "查询所有菜单信息", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "menumanagement.updatemenu", PermissionName = "更新菜单", Module = "system", Description = "更新菜单", MenuKey = "menumanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "system:quartzjob:export", PermissionName = "导出Quartz任务", Module = "system", Description = "导出Quartz任务列表", MenuKey = "quartzjoblist", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 主页 diff --git a/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs b/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs index a376301..26a0554 100644 --- a/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs +++ b/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs @@ -107,7 +107,7 @@ namespace EOM.TSHotelManagement.Service int count = 0; List assets = new List(); - if (asset.Page != 0 && asset.PageSize != 0) + if (!asset.IgnorePaging) { assets = assetRepository.AsQueryable().Where(where.ToExpression()).OrderBy(a => a.AssetNumber) .ToPageList((int)asset.Page, (int)asset.PageSize, ref count); diff --git a/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs b/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs index 82e0d9a..13f6eae 100644 --- a/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs +++ b/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -25,6 +25,8 @@ using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; +using jvncorelib.CodeLib; +using Microsoft.Extensions.Logging; namespace EOM.TSHotelManagement.Service { @@ -39,12 +41,14 @@ namespace EOM.TSHotelManagement.Service private readonly GenericRepository workerCheckRepository; /// - /// + /// 唯一编码 /// - /// - public EmployeeCheckService(GenericRepository workerCheckRepository) + private readonly UniqueCode uniqueCode; + + public EmployeeCheckService(GenericRepository workerCheckRepository, UniqueCode uniqueCode) { this.workerCheckRepository = workerCheckRepository; + this.uniqueCode = uniqueCode; } /// @@ -60,7 +64,7 @@ namespace EOM.TSHotelManagement.Service var count = 0; - if (wid.Page != 0 && wid.PageSize != 0) + if (!wid.IgnorePaging) { workerChecks = workerCheckRepository.AsQueryable().Where(where.ToExpression()) .OrderByDescending(a => a.CheckTime) @@ -172,18 +176,85 @@ namespace EOM.TSHotelManagement.Service { try { - var entity = EntityMapper.Map(workerCheck); + if (workerCheck == null || string.IsNullOrWhiteSpace(workerCheck.EmployeeId)) + { + return new BaseResponse + { + Message = LocalizationHelper.GetLocalizedString( + "Employee ID is required.", + "员工工号为必填字段" + ), + Code = BusinessStatusCode.InternalServerError + }; + } + + var employeeId = workerCheck.EmployeeId.Trim(); + var now = DateTime.Now; + var isMorningShift = now.Hour < 12; + + var shiftStart = isMorningShift + ? now.Date + : now.Date.AddHours(12); + + var shiftEnd = isMorningShift + ? now.Date.AddHours(12) + : now.Date.AddDays(1); + + var shiftStatus = isMorningShift ? 0 : 1; + var shiftName = isMorningShift ? "早班" : "晚班"; + + var alreadyChecked = workerCheckRepository.IsAny(x => + x.EmployeeId == employeeId && + x.CheckStatus == shiftStatus && + x.CheckTime >= shiftStart && + x.CheckTime < shiftEnd + ); + + if (alreadyChecked) + { + return new BaseResponse + { + Message = LocalizationHelper.GetLocalizedString( + $"{shiftName} already checked in.", + $"{shiftName}已打卡" + ), + Code = BusinessStatusCode.InternalServerError + }; + } + + var entity = new EmployeeCheck + { + CheckNumber = uniqueCode.GetNewId("CK-"), + EmployeeId = employeeId, + CheckTime = now, + CheckMethod = CheckTypeConstant.Web.Code, + CheckStatus = shiftStatus + }; + var result = workerCheckRepository.Insert(entity); if (!result) { - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("insert employee check failed.", "员工打卡添加失败"), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse + { + Message = LocalizationHelper.GetLocalizedString( + "insert employee check failed.", + "员工打卡添加失败" + ), + Code = BusinessStatusCode.InternalServerError + }; } + + return new BaseResponse(); } catch (Exception ex) { - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse + { + Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), + Code = BusinessStatusCode.InternalServerError + }; } - return new BaseResponse(); } + } } diff --git a/EOM.TSHotelManagement.Service/Employee/RewardPunishment/RewardPunishmentService.cs b/EOM.TSHotelManagement.Service/Employee/RewardPunishment/RewardPunishmentService.cs index 2854668..079de15 100644 --- a/EOM.TSHotelManagement.Service/Employee/RewardPunishment/RewardPunishmentService.cs +++ b/EOM.TSHotelManagement.Service/Employee/RewardPunishment/RewardPunishmentService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -102,7 +102,7 @@ namespace EOM.TSHotelManagement.Service var count = 0; - if (wn.Page != 0 && wn.PageSize != 0) + if (!wn.IgnorePaging) { gb = rewardPunishmentRepository.AsQueryable().Where(where.ToExpression()) .OrderByDescending(a => a.RewardPunishmentTime) diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Notice/NoticeService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Notice/NoticeService.cs index 4d11897..260897d 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Notice/NoticeService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Notice/NoticeService.cs @@ -56,7 +56,17 @@ namespace EOM.TSHotelManagement.Service var ntc = new List(); var where = SqlFilterBuilder.BuildExpression(readAppointmentNoticeInputDto); var count = 0; - ntc = noticeRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readAppointmentNoticeInputDto.Page, readAppointmentNoticeInputDto.PageSize, ref count); + + if (!readAppointmentNoticeInputDto.IgnorePaging) + { + ntc = noticeRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readAppointmentNoticeInputDto.Page, readAppointmentNoticeInputDto.PageSize, ref count); + } + else + { + ntc = noticeRepository.AsQueryable().Where(where.ToExpression()).ToList(); + count = ntc.Count; + } + ntc.ForEach(source => { switch (source.NoticeType) diff --git a/EOM.TSHotelManagement.Service/SystemManagement/SupervisionStatistics/SupervisionStatisticsService.cs b/EOM.TSHotelManagement.Service/SystemManagement/SupervisionStatistics/SupervisionStatisticsService.cs index 1b370db..95e446b 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/SupervisionStatistics/SupervisionStatisticsService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/SupervisionStatistics/SupervisionStatisticsService.cs @@ -64,7 +64,16 @@ namespace EOM.TSHotelManagement.Service var where = SqlFilterBuilder.BuildExpression(readSupervisionStatisticsInputDto ?? new ReadSupervisionStatisticsInputDto()); var count = 0; - cif = checkInfoRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readSupervisionStatisticsInputDto.Page, readSupervisionStatisticsInputDto.PageSize, ref count); + + if (!readSupervisionStatisticsInputDto.IgnorePaging) + { + cif = checkInfoRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readSupervisionStatisticsInputDto.Page, readSupervisionStatisticsInputDto.PageSize, ref count); + } + else + { + cif = checkInfoRepository.AsQueryable().Where(where.ToExpression()).ToList(); + } + var deptId = cif.Select(a => a.SupervisingDepartment).ToList(); var depts = checkInfoRepository.Change().GetList(a => deptId.Contains(a.DepartmentNumber)); cif.ForEach(c => diff --git a/EOM.TSHotelManagement.Service/SystemManagement/VipRule/VipRuleAppService.cs b/EOM.TSHotelManagement.Service/SystemManagement/VipRule/VipRuleAppService.cs index 2de9ecb..d7a7e23 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/VipRule/VipRuleAppService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/VipRule/VipRuleAppService.cs @@ -65,17 +65,25 @@ namespace EOM.TSHotelManagement.Service var where = SqlFilterBuilder.BuildExpression(readVipLevelRuleInputDto ?? new ReadVipLevelRuleInputDto()); var count = 0; - var Data = vipRuleRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readVipLevelRuleInputDto.Page, readVipLevelRuleInputDto.PageSize, ref count); + var data = new List(); + if (readVipLevelRuleInputDto.IgnorePaging) + { + data = vipRuleRepository.AsQueryable().Where(where.ToExpression()).ToList(); + } + else + { + data = vipRuleRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readVipLevelRuleInputDto.Page, readVipLevelRuleInputDto.PageSize, ref count); + } var listUserType = custoTypeRepository.GetList(a => a.IsDelete != 1); - Data.ForEach(source => + data.ForEach(source => { var userType = listUserType.SingleOrDefault(a => a.CustomerType == source.VipLevelId); source.VipLevelName = userType == null ? "" : userType.CustomerTypeName; }); - var viprules = EntityMapper.MapList(Data); + var viprules = EntityMapper.MapList(data); return new ListOutputDto { diff --git a/EOM.TSHotelManagement.Service/Util/UtilService.cs b/EOM.TSHotelManagement.Service/Util/UtilService.cs index 1f04c1e..f0d2887 100644 --- a/EOM.TSHotelManagement.Service/Util/UtilService.cs +++ b/EOM.TSHotelManagement.Service/Util/UtilService.cs @@ -86,7 +86,7 @@ namespace EOM.TSHotelManagement.Service var where = SqlFilterBuilder.BuildExpression(readOperationLogInputDto, nameof(OperationLog.OperationTime)); var count = 0; - if (readOperationLogInputDto.Page != 0 && readOperationLogInputDto.PageSize != 0) + if (!readOperationLogInputDto.IgnorePaging) { operationLogs = operationLogRepository.AsQueryable().Where(where.ToExpression()).OrderByDescending(a => a.OperationTime).ToPageList(readOperationLogInputDto.Page, readOperationLogInputDto.PageSize, ref count); } @@ -125,7 +125,7 @@ namespace EOM.TSHotelManagement.Service var where = SqlFilterBuilder.BuildExpression(readRequestLogInputDto, nameof(RequestLog.RequestTime)); var count = 0; - if (readRequestLogInputDto.Page != 0 && readRequestLogInputDto.PageSize != 0) + if (!readRequestLogInputDto.IgnorePaging) { requestLogs = requestLogRepository.AsQueryable().Where(where.ToExpression()).OrderByDescending(a => a.RequestTime).ToPageList(readRequestLogInputDto.Page, readRequestLogInputDto.PageSize, ref count); } -- Gitee From e21be8677878c0594c0275aae53834acd5fae29f Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 7 Mar 2026 20:11:09 +0800 Subject: [PATCH 09/20] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=81=8C=E4=BD=8D?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=9D=83=E9=99=90=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 position.export 权限,用于基础信息模块职位列表的导出操作,完善权限管理。 --- EOM.TSHotelManagement.Migration/EntityBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index aee7c12..0d9a0ab 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -709,6 +709,7 @@ namespace EOM.TSHotelManagement.Migration // 职位 new Permission { PermissionNumber = "position.create", PermissionName = "新增职位", Module = "basic", Description = "基础信息-职位-新增", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "position.delete", PermissionName = "删除职位", Module = "basic", Description = "基础信息-职位-删除", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "position.export", PermissionName = "导出职位", Module = "basic", Description = "基础信息-职位-导出列表", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "position.update", PermissionName = "更新职位", Module = "basic", Description = "基础信息-职位-更新", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "position.view", PermissionName = "查询职位列表", Module = "basic", Description = "基础信息-职位-查询列表", MenuKey = "position", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, -- Gitee From 39887726a30c0929539683d056fbbd9ee45cb570 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sun, 8 Mar 2026 02:09:36 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=8A=9F=E8=83=BD=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次提交新增个人中心模块,支持管理员和员工的个人资料获取、头像上传(集成Lsky图床)、密码修改(含邮件通知),并实现ProfileController、ProfileService、IProfileService及相关DTO。升级EntityMapper为Mapster映射,增强DataProtectionHelper,优化图片上传错误提示。同步新增管理员头像实体及数据库迁移,升级多项依赖包,提升系统兼容性与安全性。 --- .../Application/Profile/ProfileController.cs | 78 +++ .../EOM.TSHotelManagement.API.csproj | 2 +- .../EOM.TSHotelManagement.Common.csproj | 10 +- .../Helper/DataProtectionHelper.cs | 6 +- .../Helper/EntityMapper.cs | 141 +++-- .../Helper/LskyHelper.cs | 4 +- .../Profile/Dto/ChangePasswordInputDto.cs | 19 + .../Profile/Dto/CurrentProfileOutputDto.cs | 57 ++ .../Profile/Dto/UploadAvatarInputDto.cs | 10 + .../Profile/Dto/UploadAvatarOutputDto.cs | 7 + .../EOM.TSHotelManagement.Data.csproj | 4 +- .../EOM.TSHotelManagement.Domain.csproj | 2 +- .../SystemManagement/AdministratorPhoto.cs | 20 + ...OM.TSHotelManagement.Infrastructure.csproj | 4 +- .../EntityBuilder.cs | 1 + .../Application/Profile/IProfileService.cs | 14 + .../Application/Profile/ProfileService.cs | 525 ++++++++++++++++++ .../EOM.TSHotelManagement.Service.csproj | 2 +- 18 files changed, 849 insertions(+), 57 deletions(-) create mode 100644 EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/Profile/Dto/ChangePasswordInputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarInputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarOutputDto.cs create mode 100644 EOM.TSHotelManagement.Domain/SystemManagement/AdministratorPhoto.cs create mode 100644 EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs create mode 100644 EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs diff --git a/EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs b/EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs new file mode 100644 index 0000000..e4e9f1f --- /dev/null +++ b/EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs @@ -0,0 +1,78 @@ +using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Service; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace EOM.TSHotelManagement.WebApi.Controllers +{ + /// + /// 个人中心控制器 + /// + public class ProfileController( + IProfileService profileService, + JwtTokenRevocationService tokenRevocationService, + ILogger logger) : ControllerBase + { + private readonly IProfileService _profileService = profileService; + private readonly JwtTokenRevocationService _tokenRevocationService = tokenRevocationService; + private readonly ILogger _logger = logger; + + /// + /// 获取当前登录人基础资料 + /// + [HttpGet] + public SingleOutputDto GetCurrentProfile() + { + return _profileService.GetCurrentProfile(GetCurrentSerialNumber()); + } + + /// + /// 上传当前登录人头像 + /// + [HttpPost] + public SingleOutputDto UploadAvatar([FromForm] UploadAvatarInputDto inputDto, IFormFile file) + { + return _profileService.UploadAvatar(GetCurrentSerialNumber(), inputDto, file); + } + + /// + /// 修改当前登录人密码 + /// + [HttpPost] + public BaseResponse ChangePassword([FromBody] ChangePasswordInputDto inputDto) + { + var response = _profileService.ChangePassword(GetCurrentSerialNumber(), inputDto); + if (!response.Success) + { + return response; + } + + try + { + var authorizationHeader = Request.Headers["Authorization"].ToString(); + if (JwtTokenRevocationService.TryGetBearerToken(authorizationHeader, out var token)) + { + Task.Run(async () => { await _tokenRevocationService.RevokeTokenAsync(token); }); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to revoke current token after password change."); + } + + return response; + } + + private string GetCurrentSerialNumber() + { + return User.FindFirstValue(ClaimTypes.SerialNumber) + ?? User.FindFirst("serialnumber")?.Value + ?? string.Empty; + } + } +} diff --git a/EOM.TSHotelManagement.API/EOM.TSHotelManagement.API.csproj b/EOM.TSHotelManagement.API/EOM.TSHotelManagement.API.csproj index 4e8ca9d..5030be8 100644 --- a/EOM.TSHotelManagement.API/EOM.TSHotelManagement.API.csproj +++ b/EOM.TSHotelManagement.API/EOM.TSHotelManagement.API.csproj @@ -23,7 +23,7 @@ - + diff --git a/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj b/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj index a0d5fec..1f09960 100644 --- a/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj +++ b/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj @@ -20,18 +20,18 @@ - - + + - + + - + - diff --git a/EOM.TSHotelManagement.Common/Helper/DataProtectionHelper.cs b/EOM.TSHotelManagement.Common/Helper/DataProtectionHelper.cs index 8241879..267eb33 100644 --- a/EOM.TSHotelManagement.Common/Helper/DataProtectionHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/DataProtectionHelper.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection; using System.Security.Cryptography; namespace EOM.TSHotelManagement.Common @@ -67,6 +67,10 @@ namespace EOM.TSHotelManagement.Common private string EncryptData(string plainText, IDataProtector protector) { + if (LooksLikeDataProtectionPayload(plainText)) + { + return plainText; + } return string.IsNullOrEmpty(plainText) ? plainText : protector.Protect(plainText); diff --git a/EOM.TSHotelManagement.Common/Helper/EntityMapper.cs b/EOM.TSHotelManagement.Common/Helper/EntityMapper.cs index db5d868..0599119 100644 --- a/EOM.TSHotelManagement.Common/Helper/EntityMapper.cs +++ b/EOM.TSHotelManagement.Common/Helper/EntityMapper.cs @@ -2,19 +2,95 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Mapster; namespace EOM.TSHotelManagement.Common { public static class EntityMapper { /// - /// 映射单个实体 + /// Maps a single object instance. /// public static TDestination Map(TSource source) where TDestination : new() { if (source == null) return default; + try + { + var destination = source.Adapt(); + ApplyLegacyOverrides(source, destination); + return destination; + } + catch + { + return LegacyMap(source); + } + } + + /// + /// Maps a list of objects. + /// + public static List MapList(List sourceList) + where TDestination : new() + { + return sourceList?.Select(Map).ToList(); + } + + // Preserve the legacy edge cases while Mapster handles the common path. + private static void ApplyLegacyOverrides(TSource source, TDestination destination) + { + var sourceProperties = typeof(TSource).GetProperties( + BindingFlags.Public | BindingFlags.Instance); + var destinationProperties = typeof(TDestination).GetProperties( + BindingFlags.Public | BindingFlags.Instance); + + foreach (var destinationProperty in destinationProperties) + { + if (!destinationProperty.CanWrite) continue; + + var exactSourceProperty = sourceProperties + .SingleOrDefault(p => p.Name.Equals(destinationProperty.Name, StringComparison.Ordinal)); + var matchedSourceProperty = exactSourceProperty ?? sourceProperties + .SingleOrDefault(p => p.Name.Equals(destinationProperty.Name, StringComparison.OrdinalIgnoreCase)); + + if (matchedSourceProperty == null) continue; + + var sourceValue = matchedSourceProperty.GetValue(source); + + if (sourceValue == null) + { + if (destinationProperty.Name.Equals("RowVersion", StringComparison.OrdinalIgnoreCase) + && destinationProperty.PropertyType == typeof(long)) + { + destinationProperty.SetValue(destination, 0L); + continue; + } + + if (destinationProperty.PropertyType.IsValueType && + Nullable.GetUnderlyingType(destinationProperty.PropertyType) != null) + { + destinationProperty.SetValue(destination, null); + } + + continue; + } + + if (matchedSourceProperty.Name.Equals(destinationProperty.Name, StringComparison.Ordinal) && + !NeedConversion(matchedSourceProperty.PropertyType, destinationProperty.PropertyType)) + { + continue; + } + + destinationProperty.SetValue( + destination, + ConvertValue(sourceValue, destinationProperty.PropertyType)); + } + } + + private static TDestination LegacyMap(TSource source) + where TDestination : new() + { var destination = new TDestination(); var sourceProperties = typeof(TSource).GetProperties( @@ -34,23 +110,8 @@ namespace EOM.TSHotelManagement.Common var sourceValue = sourceProperty.GetValue(source); - if (sourceValue is DateOnly dateOnlyValue && - destinationProperty.PropertyType == typeof(DateTime?)) - { - if (dateOnlyValue == DateOnly.MinValue || dateOnlyValue == new DateOnly(1900, 1, 1)) - { - destinationProperty.SetValue(destination, null); - } - else - { - destinationProperty.SetValue(destination, dateOnlyValue.ToDateTime(TimeOnly.MinValue)); - } - continue; - } - if (sourceValue == null) { - // Ensure optimistic-lock version does not silently fall back to entity defaults. if (destinationProperty.Name.Equals("RowVersion", StringComparison.OrdinalIgnoreCase) && destinationProperty.PropertyType == typeof(long)) { @@ -63,22 +124,30 @@ namespace EOM.TSHotelManagement.Common { destinationProperty.SetValue(destination, null); } - continue; - } - if (NeedConversion(sourceProperty.PropertyType, destinationProperty.PropertyType)) - { - sourceValue = SmartConvert(sourceValue, destinationProperty.PropertyType); + continue; } - destinationProperty.SetValue(destination, sourceValue); + destinationProperty.SetValue( + destination, + ConvertValue(sourceValue, destinationProperty.PropertyType)); } return destination; } + private static object ConvertValue(object value, Type targetType) + { + if (!NeedConversion(value.GetType(), targetType)) + { + return value; + } + + return SmartConvert(value, targetType); + } + /// - /// 智能类型转换 + /// Performs legacy type conversions. /// private static object SmartConvert(object value, Type targetType) { @@ -117,7 +186,6 @@ namespace EOM.TSHotelManagement.Common } catch { - } } @@ -127,7 +195,7 @@ namespace EOM.TSHotelManagement.Common } /// - /// 检查是否为最小值 + /// Checks whether a value is treated as a legacy minimum sentinel. /// private static bool IsMinValue(object value) { @@ -141,7 +209,7 @@ namespace EOM.TSHotelManagement.Common } /// - /// 将最小值转换为空值 + /// Converts legacy minimum sentinel values to null or empty string. /// private static object ConvertMinValueToNull(object value, Type targetType) { @@ -159,7 +227,7 @@ namespace EOM.TSHotelManagement.Common } /// - /// 处理 DateOnly 类型转换 + /// Handles DateOnly conversions. /// private static object HandleDateOnlyConversion(DateOnly dateOnly, Type targetType) { @@ -190,7 +258,7 @@ namespace EOM.TSHotelManagement.Common } /// - /// 处理 DateTime 类型转换 + /// Handles DateTime conversions. /// private static object HandleDateTimeConversion(DateTime dateTime, Type targetType) { @@ -221,7 +289,7 @@ namespace EOM.TSHotelManagement.Common } /// - /// 处理字符串日期转换 + /// Handles string-to-date conversions. /// private static object HandleStringConversion(string dateString, Type targetType) { @@ -244,25 +312,14 @@ namespace EOM.TSHotelManagement.Common } /// - /// 判断是否需要类型转换 + /// Determines whether source and target types still need a custom conversion. /// private static bool NeedConversion(Type sourceType, Type targetType) { var underlyingSource = Nullable.GetUnderlyingType(sourceType) ?? sourceType; var underlyingTarget = Nullable.GetUnderlyingType(targetType) ?? targetType; - if (underlyingSource == underlyingTarget) return false; - - return true; - } - - /// - /// 映射实体列表 - /// - public static List MapList(List sourceList) - where TDestination : new() - { - return sourceList?.Select(Map).ToList(); + return underlyingSource != underlyingTarget; } } } diff --git a/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs b/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs index 7fab1b3..27fa423 100644 --- a/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs @@ -1,4 +1,4 @@ -using EOM.TSHotelManagement.Infrastructure; +using EOM.TSHotelManagement.Infrastructure; using Microsoft.Extensions.Logging; using System; using System.IO; @@ -155,7 +155,7 @@ namespace EOM.TSHotelManagement.Common } var result = await response.Content.ReadFromJsonAsync(); - return result?.Data?.Links?.Url ?? throw new Exception("响应中未包含有效URL"); + return result?.Data?.Links?.Url ?? throw new Exception("无效图片,请重新选择图片上传"); } catch (Exception ex) { diff --git a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/ChangePasswordInputDto.cs b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/ChangePasswordInputDto.cs new file mode 100644 index 0000000..f91dc4d --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/ChangePasswordInputDto.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; + +namespace EOM.TSHotelManagement.Contract +{ + public class ChangePasswordInputDto + { + [Required(ErrorMessage = "旧密码为必填字段")] + [MaxLength(256, ErrorMessage = "旧密码长度不能超过256字符")] + public string OldPassword { get; set; } + + [Required(ErrorMessage = "新密码为必填字段")] + [MaxLength(256, ErrorMessage = "新密码长度不能超过256字符")] + public string NewPassword { get; set; } + + [Required(ErrorMessage = "确认密码为必填字段")] + [MaxLength(256, ErrorMessage = "确认密码长度不能超过256字符")] + public string ConfirmPassword { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs new file mode 100644 index 0000000..2372a18 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs @@ -0,0 +1,57 @@ +namespace EOM.TSHotelManagement.Contract +{ + public class CurrentProfileOutputDto + { + public string LoginType { get; set; } + + public string UserNumber { get; set; } + + public string Account { get; set; } + + public string DisplayName { get; set; } + + public string PhotoUrl { get; set; } + + public object? Profile { get; set; } + } + + public class CurrentProfileEmployeeDto + { + public string EmployeeId { get; set; } + + public string EmployeeName { get; set; } + + public string DepartmentName { get; set; } + + public string PositionName { get; set; } + + public string PhoneNumber { get; set; } + + public string EmailAddress { get; set; } + + public string Address { get; set; } + + public string HireDate { get; set; } + + public string DateOfBirth { get; set; } + + public string PhotoUrl { get; set; } + } + + public class CurrentProfileAdminDto + { + public string Number { get; set; } + + public string Account { get; set; } + + public string Name { get; set; } + + public string TypeName { get; set; } + + public string Type { get; set; } + + public int IsSuperAdmin { get; set; } + + public string PhotoUrl { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarInputDto.cs b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarInputDto.cs new file mode 100644 index 0000000..52d50e2 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarInputDto.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace EOM.TSHotelManagement.Contract +{ + public class UploadAvatarInputDto + { + [MaxLength(32, ErrorMessage = "账号类型长度不能超过32字符")] + public string? LoginType { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarOutputDto.cs new file mode 100644 index 0000000..750e186 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/UploadAvatarOutputDto.cs @@ -0,0 +1,7 @@ +namespace EOM.TSHotelManagement.Contract +{ + public class UploadAvatarOutputDto + { + public string PhotoUrl { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Data/EOM.TSHotelManagement.Data.csproj b/EOM.TSHotelManagement.Data/EOM.TSHotelManagement.Data.csproj index bf70ab1..ba5ee0d 100644 --- a/EOM.TSHotelManagement.Data/EOM.TSHotelManagement.Data.csproj +++ b/EOM.TSHotelManagement.Data/EOM.TSHotelManagement.Data.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/EOM.TSHotelManagement.Domain/EOM.TSHotelManagement.Domain.csproj b/EOM.TSHotelManagement.Domain/EOM.TSHotelManagement.Domain.csproj index befa5d9..9a50f0f 100644 --- a/EOM.TSHotelManagement.Domain/EOM.TSHotelManagement.Domain.csproj +++ b/EOM.TSHotelManagement.Domain/EOM.TSHotelManagement.Domain.csproj @@ -12,7 +12,7 @@ - + diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorPhoto.cs b/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorPhoto.cs new file mode 100644 index 0000000..d0eebf4 --- /dev/null +++ b/EOM.TSHotelManagement.Domain/SystemManagement/AdministratorPhoto.cs @@ -0,0 +1,20 @@ +using SqlSugar; + +namespace EOM.TSHotelManagement.Domain +{ + /// + /// 管理员头像 + /// + [SugarTable("administrator_pic", "管理员头像")] + public class AdministratorPhoto : SoftDeleteEntity + { + [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "编号")] + public int Id { get; set; } + + [SugarColumn(ColumnName = "admin_number", ColumnDescription = "管理员编号", Length = 128, IsNullable = false, IsPrimaryKey = true)] + public string AdminNumber { get; set; } + + [SugarColumn(ColumnName = "pic_url", ColumnDescription = "头像地址", Length = 256, IsNullable = true)] + public string PhotoPath { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Infrastructure/EOM.TSHotelManagement.Infrastructure.csproj b/EOM.TSHotelManagement.Infrastructure/EOM.TSHotelManagement.Infrastructure.csproj index d6e07bf..a60e237 100644 --- a/EOM.TSHotelManagement.Infrastructure/EOM.TSHotelManagement.Infrastructure.csproj +++ b/EOM.TSHotelManagement.Infrastructure/EOM.TSHotelManagement.Infrastructure.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 0d9a0ab..f1d15e0 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -34,6 +34,7 @@ namespace EOM.TSHotelManagement.Migration { typeof(Administrator), typeof(AdministratorType), + typeof(AdministratorPhoto), typeof(AppointmentNotice), typeof(AppointmentNoticeType), typeof(Asset), diff --git a/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs b/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs new file mode 100644 index 0000000..a5aab7f --- /dev/null +++ b/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs @@ -0,0 +1,14 @@ +using EOM.TSHotelManagement.Contract; +using Microsoft.AspNetCore.Http; + +namespace EOM.TSHotelManagement.Service +{ + public interface IProfileService + { + SingleOutputDto GetCurrentProfile(string serialNumber); + + SingleOutputDto UploadAvatar(string serialNumber, UploadAvatarInputDto inputDto, IFormFile file); + + BaseResponse ChangePassword(string serialNumber, ChangePasswordInputDto inputDto); + } +} diff --git a/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs b/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs new file mode 100644 index 0000000..f9c5208 --- /dev/null +++ b/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs @@ -0,0 +1,525 @@ +using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Data; +using EOM.TSHotelManagement.Domain; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Mail; + +namespace EOM.TSHotelManagement.Service +{ + public class ProfileService( + GenericRepository adminRepository, + GenericRepository adminPhotoRepository, + GenericRepository adminTypeRepository, + GenericRepository employeeRepository, + GenericRepository employeePhotoRepository, + GenericRepository departmentRepository, + GenericRepository positionRepository, + DataProtectionHelper dataProtectionHelper, + LskyHelper lskyHelper, + MailHelper mailHelper, + ILogger logger) : IProfileService + { + private const string AdminLoginType = "admin"; + private const string EmployeeLoginType = "employee"; + private readonly GenericRepository _adminRepository = adminRepository; + private readonly GenericRepository _adminPhotoRepository = adminPhotoRepository; + private readonly GenericRepository _adminTypeRepository = adminTypeRepository; + private readonly GenericRepository _employeeRepository = employeeRepository; + private readonly GenericRepository _employeePhotoRepository = employeePhotoRepository; + private readonly GenericRepository _departmentRepository = departmentRepository; + private readonly GenericRepository _positionRepository = positionRepository; + private readonly DataProtectionHelper _dataProtectionHelper = dataProtectionHelper; + private readonly LskyHelper _lskyHelper = lskyHelper; + private readonly MailHelper _mailHelper = mailHelper; + private readonly ILogger _logger = logger; + + public SingleOutputDto GetCurrentProfile(string serialNumber) + { + try + { + var currentUser = ResolveCurrentUser(serialNumber); + if (currentUser == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.NotFound, + Message = LocalizationHelper.GetLocalizedString("Current profile not found", "未找到当前登录人资料") + }; + } + + return new SingleOutputDto + { + Message = LocalizationHelper.GetLocalizedString("ok", "成功"), + Data = BuildCurrentProfileOutput(currentUser) + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error getting current profile for serial number: {SerialNumber}", serialNumber); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message) + }; + } + } + + public SingleOutputDto UploadAvatar(string serialNumber, UploadAvatarInputDto inputDto, IFormFile file) + { + try + { + var currentUser = ResolveCurrentUser(serialNumber); + if (currentUser == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.NotFound, + Message = LocalizationHelper.GetLocalizedString("Current profile not found", "未找到当前登录人资料") + }; + } + + if (!string.IsNullOrWhiteSpace(inputDto?.LoginType) + && !string.Equals(inputDto.LoginType, currentUser.LoginType, StringComparison.OrdinalIgnoreCase)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("Login type does not match current user", "账号类型与当前登录人不匹配") + }; + } + + var uploadResult = UploadImage(file); + if (!uploadResult.Success) + { + return uploadResult; + } + + var saveResult = SaveAvatarPath(currentUser, uploadResult.Data.PhotoUrl); + if (!saveResult.Success) + { + return saveResult; + } + + return new SingleOutputDto + { + Message = LocalizationHelper.GetLocalizedString("ok", "成功"), + Data = new UploadAvatarOutputDto + { + PhotoUrl = uploadResult.Data.PhotoUrl + } + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error uploading avatar for serial number: {SerialNumber}", serialNumber); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message) + }; + } + } + + public BaseResponse ChangePassword(string serialNumber, ChangePasswordInputDto inputDto) + { + try + { + var currentUser = ResolveCurrentUser(serialNumber); + if (currentUser == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.NotFound, + Message = LocalizationHelper.GetLocalizedString("Current profile not found", "未找到当前登录人资料") + }; + } + + if (!string.Equals(inputDto.NewPassword, inputDto.ConfirmPassword, StringComparison.Ordinal)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("The new password and confirmation password do not match", "新密码与确认密码不一致") + }; + } + + if (string.Equals(inputDto.OldPassword, inputDto.NewPassword, StringComparison.Ordinal)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("The new password cannot be the same as the old password", "新密码不能与旧密码相同") + }; + } + + BaseResponse updateResponse = currentUser.LoginType switch + { + AdminLoginType => ChangeAdminPassword(currentUser.Admin, inputDto), + EmployeeLoginType => ChangeEmployeePassword(currentUser.Employee, inputDto), + _ => new BaseResponse(BusinessStatusCode.BadRequest, LocalizationHelper.GetLocalizedString("Unsupported login type", "不支持的登录类型")) + }; + + if (!updateResponse.Success) + { + return new SingleOutputDto + { + Code = updateResponse.Code, + Message = updateResponse.Message + }; + } + + return new SingleOutputDto + { + Message = LocalizationHelper.GetLocalizedString("Password changed successfully", "密码修改成功"), + Data = null + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error changing password for serial number: {SerialNumber}", serialNumber); + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), + Data = null + }; + } + } + + private CurrentProfileOutputDto BuildCurrentProfileOutput(CurrentUserProfile currentUser) + { + return string.Equals(currentUser.LoginType, AdminLoginType, StringComparison.OrdinalIgnoreCase) + ? BuildAdminCurrentProfile(currentUser.Admin, currentUser.PhotoUrl) + : BuildEmployeeCurrentProfile(currentUser.Employee, currentUser.PhotoUrl); + } + + private CurrentProfileOutputDto BuildAdminCurrentProfile(Administrator admin, string photoUrl) + { + var account = FirstNonEmpty(admin.Account, admin.Number); + var displayName = FirstNonEmpty(admin.Name, account); + var typeCode = FirstNonEmpty(admin.Type, string.Empty); + var typeName = FirstNonEmpty( + _adminTypeRepository.GetFirst(a => a.TypeId == admin.Type && a.IsDelete != 1)?.TypeName, + typeCode); + + return new CurrentProfileOutputDto + { + LoginType = AdminLoginType, + UserNumber = FirstNonEmpty(admin.Number, account), + Account = account, + DisplayName = displayName, + PhotoUrl = FirstNonEmpty(photoUrl, string.Empty), + Profile = new CurrentProfileAdminDto + { + Number = FirstNonEmpty(admin.Number, account), + Account = account, + Name = displayName, + TypeName = typeName, + Type = typeCode, + IsSuperAdmin = admin.IsSuperAdmin, + PhotoUrl = FirstNonEmpty(photoUrl, string.Empty) + } + }; + } + + private CurrentProfileOutputDto BuildEmployeeCurrentProfile(Employee employee, string photoUrl) + { + var account = FirstNonEmpty(employee.EmailAddress, employee.EmployeeId); + var displayName = FirstNonEmpty(employee.EmployeeName, employee.EmployeeId); + var departmentName = FirstNonEmpty( + _departmentRepository.GetFirst(a => a.DepartmentNumber == employee.Department && a.IsDelete != 1)?.DepartmentName, + employee.Department); + var positionName = FirstNonEmpty( + _positionRepository.GetFirst(a => a.PositionNumber == employee.Position && a.IsDelete != 1)?.PositionName, + employee.Position); + + return new CurrentProfileOutputDto + { + LoginType = EmployeeLoginType, + UserNumber = FirstNonEmpty(employee.EmployeeId, account), + Account = account, + DisplayName = displayName, + PhotoUrl = FirstNonEmpty(photoUrl, string.Empty), + Profile = new CurrentProfileEmployeeDto + { + EmployeeId = FirstNonEmpty(employee.EmployeeId, account), + EmployeeName = displayName, + DepartmentName = departmentName, + PositionName = positionName, + PhoneNumber = FirstNonEmpty(dataProtectionHelper.SafeDecryptEmployeeData(employee.PhoneNumber), string.Empty), + EmailAddress = FirstNonEmpty(employee.EmailAddress, account), + Address = FirstNonEmpty(employee.Address, string.Empty), + HireDate = FormatDate(employee.HireDate), + DateOfBirth = FormatDate(employee.DateOfBirth), + PhotoUrl = FirstNonEmpty(photoUrl, string.Empty) + } + }; + } + + private BaseResponse ChangeAdminPassword(Administrator admin, ChangePasswordInputDto inputDto) + { + var currentPassword = _dataProtectionHelper.SafeDecryptAdministratorData(admin.Password); + if (!string.Equals(inputDto.OldPassword, currentPassword, StringComparison.Ordinal)) + { + return new BaseResponse( + BusinessStatusCode.BadRequest, + LocalizationHelper.GetLocalizedString("The old password is incorrect", "旧密码不正确")); + } + + admin.Password = _dataProtectionHelper.EncryptAdministratorData(inputDto.NewPassword); + var updateResult = _adminRepository.Update(admin); + if (!updateResult) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + + TrySendPasswordChangeEmail(admin.Account, admin.Name, inputDto.NewPassword); + return new BaseResponse(); + } + + private BaseResponse ChangeEmployeePassword(Employee employee, ChangePasswordInputDto inputDto) + { + var currentPassword = _dataProtectionHelper.SafeDecryptEmployeeData(employee.Password); + if (!string.Equals(inputDto.OldPassword, currentPassword, StringComparison.Ordinal)) + { + return new BaseResponse( + BusinessStatusCode.BadRequest, + LocalizationHelper.GetLocalizedString("The old password is incorrect", "旧密码不正确")); + } + + employee.Password = _dataProtectionHelper.EncryptEmployeeData(inputDto.NewPassword); + employee.IsInitialize = 1; + var updateResult = _employeeRepository.Update(employee); + if (!updateResult) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + + TrySendPasswordChangeEmail(employee.EmailAddress, employee.EmployeeName, inputDto.NewPassword); + return new BaseResponse(); + } + + private SingleOutputDto UploadImage(IFormFile file) + { + if (!_lskyHelper.GetEnabledState().Result) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("Image upload service is not enabled", "图片上传服务未启用") + }; + } + + if (file == null || file.Length == 0) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("File cannot null", "文件不能为空") + }; + } + + if (file.Length > 1048576) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("Image size exceeds 1MB limit", "图片大小不能超过1MB") + }; + } + + if (file.ContentType != "image/jpeg" && file.ContentType != "image/png") + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = LocalizationHelper.GetLocalizedString("Invalid image format", "图片格式不正确") + }; + } + + var token = _lskyHelper.GetImageStorageTokenAsync().Result; + if (string.IsNullOrWhiteSpace(token)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString("Get Token Fail", "获取Token失败") + }; + } + + using var stream = file.OpenReadStream(); + stream.Seek(0, SeekOrigin.Begin); + var imageUrl = _lskyHelper.UploadImageAsync( + fileStream: stream, + fileName: file.FileName, + contentType: file.ContentType, + token: token).Result; + + if (string.IsNullOrWhiteSpace(imageUrl)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.InternalServerError, + Message = LocalizationHelper.GetLocalizedString("Image upload failed", "图片上传失败") + }; + } + + return new SingleOutputDto + { + Data = new UploadAvatarOutputDto + { + PhotoUrl = imageUrl + } + }; + } + + private SingleOutputDto SaveAvatarPath(CurrentUserProfile currentUser, string photoUrl) + { + if (string.Equals(currentUser.LoginType, AdminLoginType, StringComparison.OrdinalIgnoreCase)) + { + var adminPhoto = _adminPhotoRepository.GetFirst(a => a.AdminNumber == currentUser.UserNumber && a.IsDelete != 1); + if (adminPhoto == null) + { + _adminPhotoRepository.Insert(new AdministratorPhoto + { + AdminNumber = currentUser.UserNumber, + PhotoPath = photoUrl + }); + + return new SingleOutputDto(); + } + + adminPhoto.PhotoPath = photoUrl; + if (!_adminPhotoRepository.Update(adminPhoto)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.Conflict, + Message = LocalizationHelper.GetLocalizedString("Data has been modified by another user. Please refresh and retry.", "数据已被其他用户修改,请刷新后重试。") + }; + } + + return new SingleOutputDto(); + } + + var employeePhoto = _employeePhotoRepository.GetFirst(a => a.EmployeeId == currentUser.UserNumber && a.IsDelete != 1); + if (employeePhoto == null) + { + _employeePhotoRepository.Insert(new EmployeePhoto + { + EmployeeId = currentUser.UserNumber, + PhotoPath = photoUrl + }); + + return new SingleOutputDto(); + } + + employeePhoto.PhotoPath = photoUrl; + if (!_employeePhotoRepository.Update(employeePhoto)) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.Conflict, + Message = LocalizationHelper.GetLocalizedString("Data has been modified by another user. Please refresh and retry.", "数据已被其他用户修改,请刷新后重试。") + }; + } + + return new SingleOutputDto(); + } + + private CurrentUserProfile? ResolveCurrentUser(string serialNumber) + { + if (string.IsNullOrWhiteSpace(serialNumber)) + { + return null; + } + + var admin = _adminRepository.GetFirst(a => a.Number == serialNumber && a.IsDelete != 1); + if (admin != null) + { + var adminPhoto = _adminPhotoRepository.GetFirst(a => a.AdminNumber == admin.Number && a.IsDelete != 1); + return new CurrentUserProfile + { + LoginType = AdminLoginType, + UserNumber = admin.Number, + Account = admin.Account, + DisplayName = admin.Name, + PhotoUrl = adminPhoto?.PhotoPath ?? string.Empty, + Admin = admin + }; + } + + var employee = _employeeRepository.GetFirst(a => a.EmployeeId == serialNumber && a.IsDelete != 1); + if (employee != null) + { + var employeePhoto = _employeePhotoRepository.GetFirst(a => a.EmployeeId == employee.EmployeeId && a.IsDelete != 1); + return new CurrentUserProfile + { + LoginType = EmployeeLoginType, + UserNumber = employee.EmployeeId, + Account = string.IsNullOrWhiteSpace(employee.EmailAddress) ? employee.EmployeeId : employee.EmailAddress, + DisplayName = employee.EmployeeName, + PhotoUrl = employeePhoto?.PhotoPath ?? string.Empty, + Employee = employee + }; + } + + return null; + } + + private void TrySendPasswordChangeEmail(string? emailAddress, string? displayName, string newPassword) + { + if (string.IsNullOrWhiteSpace(emailAddress) || !MailAddress.TryCreate(emailAddress, out _)) + { + return; + } + + try + { + var template = EmailTemplate.GetUpdatePasswordTemplate(displayName ?? "User", newPassword); + _mailHelper.SendMail(new List { emailAddress }, template.Subject, template.Body, new List { emailAddress }); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Password change email send failed for account: {Account}", emailAddress); + } + } + + private static string FirstNonEmpty(string? primary, string? fallback) + { + if (!string.IsNullOrWhiteSpace(primary)) + { + return primary; + } + + return fallback ?? string.Empty; + } + + private static string FormatDate(DateOnly date) + { + return date == default ? string.Empty : date.ToString("yyyy-MM-dd"); + } + + private sealed class CurrentUserProfile + { + public string LoginType { get; set; } + + public string UserNumber { get; set; } + + public string Account { get; set; } + + public string DisplayName { get; set; } + + public string PhotoUrl { get; set; } + + public Administrator Admin { get; set; } + + public Employee Employee { get; set; } + } + } +} diff --git a/EOM.TSHotelManagement.Service/EOM.TSHotelManagement.Service.csproj b/EOM.TSHotelManagement.Service/EOM.TSHotelManagement.Service.csproj index be64ba7..0a7c44b 100644 --- a/EOM.TSHotelManagement.Service/EOM.TSHotelManagement.Service.csproj +++ b/EOM.TSHotelManagement.Service/EOM.TSHotelManagement.Service.csproj @@ -26,7 +26,7 @@ - + -- Gitee From de03faa0dbd17db46266b541639719672c8dc113 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sun, 8 Mar 2026 14:13:49 +0800 Subject: [PATCH 11/20] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BA=BA=E5=91=98?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=8A=BD=E8=B1=A1=E4=B8=BAPersonnel=E5=9F=BA?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E9=87=8D=E6=9E=84=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次重构将姓名、性别、证件类型、联系方式、地址等字段抽象到Personnel基类,并让Customer、Employee、Administrator等实体继承,移除冗余字段。同步调整DTO、Service、Migration等相关字段命名和结构,资产相关字段也做了统一。所有字段访问、映射、加解密、邮件模板等均已适配新结构,提升代码一致性和可维护性。 --- .../Profile/Dto/CurrentProfileOutputDto.cs | 4 +- .../Asset/Dto/Asset/ReadAssetOutputDto.cs | 4 +- .../Dto/Customer/CreateCustomerInputDto.cs | 10 +- .../Dto/Customer/ReadCustomerInputDto.cs | 8 +- .../Dto/Customer/ReadCustomerOutputDto.cs | 12 +- .../Dto/Customer/UpdateCustomerInputDto.cs | 10 +- .../Dto/Employee/CreateEmployeeInputDto.cs | 2 +- .../Dto/Employee/ReadEmployeeInputDto.cs | 4 +- .../Dto/Employee/ReadEmployeeOutputDto.cs | 4 +- .../Dto/Employee/UpdateEmployeeInputDto.cs | 2 +- .../Business/Asset/Asset.cs | 2 +- .../Business/Customer/Customer.cs | 62 +---------- .../Common/Personnel.cs | 30 +++++ .../Employee/Employee.cs | 104 +----------------- .../SystemManagement/Administrator.cs | 27 +---- .../EntityBuilder.cs | 11 +- .../Application/Profile/ProfileService.cs | 8 +- .../Business/Asset/AssetService.cs | 2 +- .../Account/CustomerAccountService.cs | 10 +- .../Business/Customer/CustomerService.cs | 56 +++++----- .../Business/Room/RoomService.cs | 12 +- .../Dashboard/DashboardService.cs | 4 +- .../Employee/EmployeeService.cs | 61 +++++----- .../SystemManagement/Base/BaseService.cs | 4 +- 24 files changed, 154 insertions(+), 299 deletions(-) create mode 100644 EOM.TSHotelManagement.Domain/Common/Personnel.cs diff --git a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs index 2372a18..ea9e96d 100644 --- a/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Application/Profile/Dto/CurrentProfileOutputDto.cs @@ -1,4 +1,4 @@ -namespace EOM.TSHotelManagement.Contract +namespace EOM.TSHotelManagement.Contract { public class CurrentProfileOutputDto { @@ -19,7 +19,7 @@ { public string EmployeeId { get; set; } - public string EmployeeName { get; set; } + public string Name { get; set; } public string DepartmentName { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Asset/Dto/Asset/ReadAssetOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Asset/Dto/Asset/ReadAssetOutputDto.cs index 30a584e..c660305 100644 --- a/EOM.TSHotelManagement.Contract/Business/Asset/Dto/Asset/ReadAssetOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Asset/Dto/Asset/ReadAssetOutputDto.cs @@ -1,4 +1,4 @@ -namespace EOM.TSHotelManagement.Contract +namespace EOM.TSHotelManagement.Contract { public class ReadAssetOutputDto : BaseOutputDto { @@ -17,7 +17,7 @@ public string AssetSource { get; set; } public string AcquiredByEmployeeId { get; set; } - public string AcquiredByEmployeeName { get; set; } + public string AcquiredByName { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/CreateCustomerInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/CreateCustomerInputDto.cs index 5de097a..7faacf2 100644 --- a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/CreateCustomerInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/CreateCustomerInputDto.cs @@ -8,16 +8,16 @@ namespace EOM.TSHotelManagement.Contract public string CustomerNumber { get; set; } [Required(ErrorMessage = "客户名称为必填字段"), MaxLength(250, ErrorMessage = "客户名称长度不超过250字符")] - public string CustomerName { get; set; } + public string Name { get; set; } [Required(ErrorMessage = "客户性别为必填字段")] - public int? CustomerGender { get; set; } + public int? Gender { get; set; } [Required(ErrorMessage = "证件类型为必填字段")] - public int PassportId { get; set; } + public int IdCardType { get; set; } [Required(ErrorMessage = "客户电话为必填字段"), MaxLength(256, ErrorMessage = "客户电话长度不超过256字符")] - public string CustomerPhoneNumber { get; set; } + public string PhoneNumber { get; set; } [Required(ErrorMessage = "出生日期为必填字段")] public DateTime DateOfBirth { get; set; } @@ -26,7 +26,7 @@ namespace EOM.TSHotelManagement.Contract public string IdCardNumber { get; set; } [MaxLength(256, ErrorMessage = "客户地址长度不超过256字符")] - public string CustomerAddress { get; set; } + public string Address { get; set; } [Required(ErrorMessage = "客户类型为必填字段")] public int CustomerType { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerInputDto.cs index 976b4c5..18d1b94 100644 --- a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerInputDto.cs @@ -1,14 +1,14 @@ -using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Common; namespace EOM.TSHotelManagement.Contract { public class ReadCustomerInputDto : ListInputDto { - public string? CustomerName { get; set; } + public string? Name { get; set; } public string? CustomerNumber { get; set; } - public string? CustomerPhoneNumber { get; set; } + public string? PhoneNumber { get; set; } public string? IdCardNumber { get; set; } - public int? CustomerGender { get; set; } + public int? Gender { get; set; } public int? CustomerType { get; set; } public DateRangeDto DateRangeDto { get; set; } } diff --git a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerOutputDto.cs index abd0fdd..9bb2609 100644 --- a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/ReadCustomerOutputDto.cs @@ -1,4 +1,4 @@ - + using EOM.TSHotelManagement.Common; namespace EOM.TSHotelManagement.Contract @@ -12,19 +12,19 @@ namespace EOM.TSHotelManagement.Contract public string CustomerNumber { get; set; } [UIDisplay("客户姓名")] - public string CustomerName { get; set; } + public string Name { get; set; } [UIDisplay("性别", true, false)] - public int? CustomerGender { get; set; } + public int? Gender { get; set; } [UIDisplay("证件类型", true, false)] - public int PassportId { get; set; } + public int IdCardType { get; set; } [UIDisplay("性别", false, true)] public string GenderName { get; set; } [UIDisplay("联系方式")] - public string CustomerPhoneNumber { get; set; } + public string PhoneNumber { get; set; } [UIDisplay("出生日期")] public DateTime DateOfBirth { get; set; } @@ -42,7 +42,7 @@ namespace EOM.TSHotelManagement.Contract public string IdCardNumber { get; set; } [UIDisplay("客户地址")] - public string CustomerAddress { get; set; } + public string Address { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/UpdateCustomerInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/UpdateCustomerInputDto.cs index e982f8f..f6a4348 100644 --- a/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/UpdateCustomerInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Customer/Dto/Customer/UpdateCustomerInputDto.cs @@ -8,16 +8,16 @@ namespace EOM.TSHotelManagement.Contract public string CustomerNumber { get; set; } [Required(ErrorMessage = "客户名称为必填字段"), MaxLength(250, ErrorMessage = "客户名称长度不超过250字符")] - public string CustomerName { get; set; } + public string Name { get; set; } [Required(ErrorMessage = "客户性别为必填字段")] - public int? CustomerGender { get; set; } + public int? Gender { get; set; } [Required(ErrorMessage = "证件类型为必填字段")] - public int PassportId { get; set; } + public int IdCardType { get; set; } [Required(ErrorMessage = "客户电话为必填字段"), MaxLength(256, ErrorMessage = "客户电话长度不超过256字符")] - public string CustomerPhoneNumber { get; set; } + public string PhoneNumber { get; set; } [Required(ErrorMessage = "出生日期为必填字段")] public DateOnly DateOfBirth { get; set; } @@ -26,7 +26,7 @@ namespace EOM.TSHotelManagement.Contract public string IdCardNumber { get; set; } [MaxLength(256, ErrorMessage = "客户地址长度不超过256字符")] - public string CustomerAddress { get; set; } + public string Address { get; set; } [Required(ErrorMessage = "客户类型为必填字段")] public int CustomerType { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/CreateEmployeeInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/CreateEmployeeInputDto.cs index c8d99c4..5fb8e54 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/CreateEmployeeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/CreateEmployeeInputDto.cs @@ -10,7 +10,7 @@ namespace EOM.TSHotelManagement.Contract [Required(ErrorMessage = "员工姓名为必填字段")] [MaxLength(250, ErrorMessage = "员工姓名长度不超过250字符")] - public string EmployeeName { get; set; } + public string Name { get; set; } [Required(ErrorMessage = "员工性别为必填字段")] public int Gender { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeInputDto.cs index f465bf2..f527745 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeInputDto.cs @@ -1,11 +1,11 @@ -using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Common; namespace EOM.TSHotelManagement.Contract { public class ReadEmployeeInputDto : ListInputDto { public string? EmployeeId { get; set; } - public string? EmployeeName { get; set; } + public string? Name { get; set; } public string? Gender { get; set; } public DateOnly? DateOfBirth { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeOutputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeOutputDto.cs index 66b0108..ee59de2 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/ReadEmployeeOutputDto.cs @@ -1,10 +1,10 @@ -namespace EOM.TSHotelManagement.Contract +namespace EOM.TSHotelManagement.Contract { public class ReadEmployeeOutputDto : BaseOutputDto { public string EmployeeId { get; set; } - public string EmployeeName { get; set; } + public string Name { get; set; } public int Gender { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/UpdateEmployeeInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/UpdateEmployeeInputDto.cs index f0364f5..7d12dc3 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/UpdateEmployeeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/Employee/UpdateEmployeeInputDto.cs @@ -10,7 +10,7 @@ namespace EOM.TSHotelManagement.Contract [Required(ErrorMessage = "员工姓名为必填字段")] [MaxLength(250, ErrorMessage = "员工姓名长度不超过250字符")] - public string EmployeeName { get; set; } + public string Name { get; set; } [Required(ErrorMessage = "员工性别为必填字段")] public int Gender { get; set; } diff --git a/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs b/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs index dae0369..4435c37 100644 --- a/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs +++ b/EOM.TSHotelManagement.Domain/Business/Asset/Asset.cs @@ -105,7 +105,7 @@ namespace EOM.TSHotelManagement.Domain /// 资产经办人姓名 (Acquired By - Employee Name) /// [SqlSugar.SugarColumn(IsIgnore = true)] - public string AcquiredByEmployeeName { get; set; } + public string AcquiredByName { get; set; } } diff --git a/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs b/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs index 6620b8d..6c49b2e 100644 --- a/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs +++ b/EOM.TSHotelManagement.Domain/Business/Customer/Customer.cs @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 客户信息 /// [SqlSugar.SugarTable("customer")] - public class Customer : SoftDeleteEntity + public class Customer : Personnel //SoftDeleteEntity { /// /// 编号 (ID) @@ -45,66 +45,6 @@ namespace EOM.TSHotelManagement.Domain [SqlSugar.SugarColumn(ColumnName = "custo_no", IsPrimaryKey = true, IsNullable = false, Length = 128, ColumnDescription = "客户编号 (Customer Number)")] public string CustomerNumber { get; set; } - /// - /// 客户名称 (Customer Name) - /// - [SqlSugar.SugarColumn(ColumnName = "custo_name", IsNullable = false, Length = 250, ColumnDescription = "客户名称 (Customer Name)")] - public string CustomerName { get; set; } - - /// - /// 客户性别 (Customer Gender) - /// - [SqlSugar.SugarColumn(ColumnName = "custo_gender", IsNullable = false, ColumnDescription = "客户性别 (Customer Gender)")] - public int? CustomerGender { get; set; } - - /// - /// 证件类型 (Passport Type) - /// - [SqlSugar.SugarColumn(ColumnName = "passport_type", IsNullable = false, ColumnDescription = "客户性别 (Customer Gender)")] - public int PassportId { get; set; } - - /// - /// 性别 (Gender) - /// - [SqlSugar.SugarColumn(IsIgnore = true)] - public string GenderName { get; set; } - - /// - /// 客户电话 (Customer Phone Number) - /// - [SqlSugar.SugarColumn(ColumnName = "custo_tel", IsNullable = false, Length = 256, ColumnDescription = "客户电话 (Customer Phone Number)")] - public string CustomerPhoneNumber { get; set; } - - /// - /// 出生日期 (Date of Birth) - /// - [SqlSugar.SugarColumn(ColumnName = "custo_birth", IsNullable = false, ColumnDescription = "出生日期 (Date of Birth)")] - public DateOnly DateOfBirth { get; set; } - - /// - /// 客户类型名称 (Customer Type Name) - /// - [SqlSugar.SugarColumn(IsIgnore = true)] - public string CustomerTypeName { get; set; } - - /// - /// 证件类型名称 (Passport Type Name) - /// - [SqlSugar.SugarColumn(IsIgnore = true)] - public string PassportName { get; set; } - - /// - /// 证件号码 (Passport ID) - /// - [SqlSugar.SugarColumn(ColumnName = "passport_id", IsNullable = false, Length = 256, ColumnDescription = "证件号码 (Passport ID)")] - public string IdCardNumber { get; set; } - - /// - /// 居住地址 (Customer Address) - /// - [SqlSugar.SugarColumn(ColumnName = "custo_address", IsNullable = true, Length = 256, ColumnDescription = "居住地址 (Customer Address)")] - public string CustomerAddress { get; set; } - /// /// 客户类型 (Customer Type) /// diff --git a/EOM.TSHotelManagement.Domain/Common/Personnel.cs b/EOM.TSHotelManagement.Domain/Common/Personnel.cs new file mode 100644 index 0000000..f383a26 --- /dev/null +++ b/EOM.TSHotelManagement.Domain/Common/Personnel.cs @@ -0,0 +1,30 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Domain; + +public class Personnel : SoftDeleteEntity +{ + [SugarColumn(ColumnName = "name", IsNullable = false, ColumnDescription = "姓名", Length = 250)] + public string Name { get; set; } = string.Empty; + [SugarColumn(ColumnName = "phone_number", IsNullable = false, ColumnDescription = "电话号码", Length = 256)] + public string PhoneNumber { get; set; } = string.Empty; + [SugarColumn(ColumnName = "id_number", IsNullable = false, ColumnDescription = "证件号码", Length = 256)] + public string IdCardNumber { get; set; } = string.Empty; + [SugarColumn(ColumnName = "address", IsNullable = false, ColumnDescription = "联系地址", Length = 500)] + public string Address { get; set; } = string.Empty; + [SugarColumn(ColumnName = "date_of_birth", IsNullable = false, ColumnDescription = "出生日期")] + public DateOnly DateOfBirth { get; set; } = DateOnly.MinValue; + [SugarColumn(ColumnName = "gender", IsNullable = false, ColumnDescription = "性别(0/女,1/男)")] + public int Gender { get; set; } = 0; + [SugarColumn(ColumnName = "id_type", IsNullable = false, ColumnDescription = "证件类型")] + public int IdCardType { get; set; } = 0; + [SugarColumn(ColumnName = "ethnicity", IsNullable = false, ColumnDescription = "民族", Length = 128)] + public string Ethnicity { get; set; } = string.Empty; + [SugarColumn(ColumnName = "education_level", IsNullable = false, ColumnDescription = "教育程度", Length = 128)] + public string EducationLevel { get; set; } = string.Empty; + [SugarColumn(ColumnName = "email_address", IsNullable = false, Length = 256, ColumnDescription = "邮箱地址")] + public string EmailAddress { get; set; } = string.Empty; +} diff --git a/EOM.TSHotelManagement.Domain/Employee/Employee.cs b/EOM.TSHotelManagement.Domain/Employee/Employee.cs index d5ec972..1b16746 100644 --- a/EOM.TSHotelManagement.Domain/Employee/Employee.cs +++ b/EOM.TSHotelManagement.Domain/Employee/Employee.cs @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 员工信息 (Employee Information) /// [SugarTable("employee")] - public class Employee : SoftDeleteEntity + public class Employee : Personnel //SoftDeleteEntity { /// /// 编号 (ID) @@ -45,90 +45,18 @@ namespace EOM.TSHotelManagement.Domain [SugarColumn(ColumnName = "employee_number", IsPrimaryKey = true, IsNullable = false, Length = 128, ColumnDescription = "员工账号/工号 (Employee Account/ID)")] public string EmployeeId { get; set; } - /// - /// 员工姓名 (Employee Name) - /// - [SugarColumn(ColumnName = "employee_name", IsNullable = false, Length = 250, ColumnDescription = "员工姓名 (Employee Name)")] - public string EmployeeName { get; set; } - - /// - /// 出生日期 (Date of Birth) - /// - [SugarColumn(ColumnName = "employee_date_of_birth", IsNullable = false, ColumnDescription = "出生日期 (Date of Birth)")] - public DateOnly DateOfBirth { get; set; } - - /// - /// 员工性别 (Employee Gender) - /// - [SugarColumn(ColumnName = "employee_gender", IsNullable = false, ColumnDescription = "员工性别 (Employee Gender)")] - public int Gender { get; set; } - - /// - /// 员工性别(名称描述) (Employee Gender (Name Description)) - /// - [SugarColumn(IsIgnore = true)] - public string GenderName { get; set; } - - /// - /// 民族类型 (Ethnicity) - /// - [SugarColumn(ColumnName = "employee_nation", IsNullable = false, Length = 128, ColumnDescription = "民族类型 (Ethnicity)")] - public string Ethnicity { get; set; } - - /// - /// 民族名称 (Ethnicity Name) - /// - [SugarColumn(IsIgnore = true)] - public string EthnicityName { get; set; } - - /// - /// 员工电话 (Employee Phone Number) - /// - [SugarColumn(ColumnName = "employee_tel", IsNullable = false, Length = 256, ColumnDescription = "员工电话 (Employee Phone Number)")] - public string PhoneNumber { get; set; } - /// /// 所属部门 (Department) /// [SugarColumn(ColumnName = "employee_department", IsNullable = false, Length = 128, ColumnDescription = "所属部门 (Department)")] public string Department { get; set; } - /// - /// 部门名称 (Department Name) - /// - [SugarColumn(IsIgnore = true)] - public string DepartmentName { get; set; } - - /// - /// 居住地址 (Residential Address) - /// - [SugarColumn(ColumnName = "employee_address", IsNullable = true, Length = 500, ColumnDescription = "居住地址 (Residential Address)")] - public string Address { get; set; } - /// /// 员工职位 (Employee Position) /// [SugarColumn(ColumnName = "employee_postion", IsNullable = false, Length = 128, ColumnDescription = "员工职位 (Employee Position)")] public string Position { get; set; } - /// - /// 职位名称 (Position Name) - /// - [SugarColumn(IsIgnore = true)] - public string PositionName { get; set; } - - /// - /// 证件类型 (ID Card Type) - /// - [SugarColumn(ColumnName = "card_type", IsNullable = false, ColumnDescription = "证件类型 (ID Card Type)")] - public int IdCardType { get; set; } - - /// - /// 证件号码 (ID Card Number) - /// - [SugarColumn(ColumnName = "card_number", IsNullable = false, Length = 256, ColumnDescription = "证件号码 (ID Card Number)")] - public string IdCardNumber { get; set; } - /// /// 员工密码 (Employee Password) /// @@ -147,30 +75,6 @@ namespace EOM.TSHotelManagement.Domain [SugarColumn(ColumnName = "employee_political", IsNullable = false, Length = 128, ColumnDescription = "员工面貌 (Political Affiliation)")] public string PoliticalAffiliation { get; set; } - /// - /// 群众面貌描述 (Political Affiliation Description) - /// - [SugarColumn(IsIgnore = true)] - public string PoliticalAffiliationName { get; set; } - - /// - /// 证件类型 (ID Card Type) - /// - [SugarColumn(IsIgnore = true)] - public string IdCardTypeName { get; set; } - - /// - /// 教育程度 (Education Level) - /// - [SugarColumn(ColumnName = "employee_quality", IsNullable = false, Length = 128, ColumnDescription = "教育程度 (Education Level)")] - public string EducationLevel { get; set; } - - /// - /// 教育程度名称 (Education Level Name) - /// - [SugarColumn(IsIgnore = true)] - public string EducationLevelName { get; set; } - /// /// 禁用标记 /// @@ -182,11 +86,5 @@ namespace EOM.TSHotelManagement.Domain /// [SugarColumn(ColumnName = "initialize_mk", IsNullable = false, ColumnDescription = "初始化标记")] public int IsInitialize { get; set; } - - /// - /// 邮箱地址 - /// - [SugarColumn(ColumnName = "email_address", IsNullable = false, Length = 256, ColumnDescription = "邮箱地址")] - public string EmailAddress { get; set; } } } diff --git a/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs b/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs index 6764f27..1b52c3d 100644 --- a/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs +++ b/EOM.TSHotelManagement.Domain/SystemManagement/Administrator.cs @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain /// 管理员实体类 (Administrator Entity) /// [SugarTable("administrator", "管理员实体类 (Administrator Entity)", true)] - public class Administrator : SoftDeleteEntity + public class Administrator : Personnel //SoftDeleteEntity { /// /// 编号 (ID) @@ -67,35 +67,10 @@ namespace EOM.TSHotelManagement.Domain public string Type { get; set; } - /// - /// 管理员名称 (Administrator Name) - /// - [SugarColumn(ColumnName = "admin_name", IsNullable = false, Length = 200, ColumnDescription = "管理员名称 (Administrator Name)")] - - public string Name { get; set; } - /// /// 是否为超级管理员 (Is Super Administrator) /// [SugarColumn(ColumnName = "is_admin", IsNullable = false, ColumnDescription = "是否为超级管理员 (Is Super Administrator)")] public int IsSuperAdmin { get; set; } - - /// - /// 是否为超级管理员描述 (Is Super Administrator Description) - /// - [SugarColumn(IsIgnore = true)] - public string IsSuperAdminDescription { get; set; } - - /// - /// 管理员类型名称 (Administrator Type Name) - /// - [SugarColumn(IsIgnore = true)] - public string TypeName { get; set; } - - /// - /// 删除标记描述 (Delete Flag Description) - /// - [SugarColumn(IsIgnore = true)] - public string DeleteDescription { get; set; } } } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index f1d15e0..4393fad 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -93,6 +93,15 @@ namespace EOM.TSHotelManagement.Migration Password = string.Empty, Name = "超级管理员", Type = "Admin", + Address = "广东珠海", + DateOfBirth = DateOnly.FromDateTime(new DateTime(1990,1,1,0,0,0)), + EducationLevel = "E-000001", + EmailAddress = string.Empty, + Ethnicity = "N-000001", + Gender = 1, + IdCardNumber = "666", + IdCardType = 0, + PhoneNumber = "666", IsSuperAdmin = 1, IsDelete = 0, DataInsUsr = "System", @@ -617,7 +626,7 @@ namespace EOM.TSHotelManagement.Migration new Employee { EmployeeId = "WK010", - EmployeeName = "阿杰", + Name = "阿杰", DateOfBirth = DateOnly.FromDateTime(new DateTime(1999,7,20,0,0,0)), Password = string.Empty, Department = "D-000001", diff --git a/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs b/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs index f9c5208..7fd4e4f 100644 --- a/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs +++ b/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs @@ -230,7 +230,7 @@ namespace EOM.TSHotelManagement.Service private CurrentProfileOutputDto BuildEmployeeCurrentProfile(Employee employee, string photoUrl) { var account = FirstNonEmpty(employee.EmailAddress, employee.EmployeeId); - var displayName = FirstNonEmpty(employee.EmployeeName, employee.EmployeeId); + var displayName = FirstNonEmpty(employee.Name, employee.EmployeeId); var departmentName = FirstNonEmpty( _departmentRepository.GetFirst(a => a.DepartmentNumber == employee.Department && a.IsDelete != 1)?.DepartmentName, employee.Department); @@ -248,7 +248,7 @@ namespace EOM.TSHotelManagement.Service Profile = new CurrentProfileEmployeeDto { EmployeeId = FirstNonEmpty(employee.EmployeeId, account), - EmployeeName = displayName, + Name = displayName, DepartmentName = departmentName, PositionName = positionName, PhoneNumber = FirstNonEmpty(dataProtectionHelper.SafeDecryptEmployeeData(employee.PhoneNumber), string.Empty), @@ -300,7 +300,7 @@ namespace EOM.TSHotelManagement.Service return BaseResponseFactory.ConcurrencyConflict(); } - TrySendPasswordChangeEmail(employee.EmailAddress, employee.EmployeeName, inputDto.NewPassword); + TrySendPasswordChangeEmail(employee.EmailAddress, employee.Name, inputDto.NewPassword); return new BaseResponse(); } @@ -463,7 +463,7 @@ namespace EOM.TSHotelManagement.Service LoginType = EmployeeLoginType, UserNumber = employee.EmployeeId, Account = string.IsNullOrWhiteSpace(employee.EmailAddress) ? employee.EmployeeId : employee.EmailAddress, - DisplayName = employee.EmployeeName, + DisplayName = employee.Name, PhotoUrl = employeePhoto?.PhotoPath ?? string.Empty, Employee = employee }; diff --git a/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs b/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs index 26a0554..969313a 100644 --- a/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs +++ b/EOM.TSHotelManagement.Service/Business/Asset/AssetService.cs @@ -125,7 +125,7 @@ namespace EOM.TSHotelManagement.Service var dept = depts.SingleOrDefault(a => a.DepartmentNumber.Equals(source.DepartmentCode)); source.DepartmentName = dept == null ? "" : dept.DepartmentName; var worker = employees.SingleOrDefault(a => a.EmployeeId.Equals(source.AcquiredByEmployeeId)); - source.AcquiredByEmployeeName = worker == null ? "" : worker.EmployeeName; + source.AcquiredByName = worker == null ? "" : worker.Name; source.AssetValueFormatted = source.AssetValue == 0 ? "" : Decimal.Parse(source.AssetValue.ToString()).ToString("#,##0.00").ToString(); }); diff --git a/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs b/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs index dfeb165..2f348bb 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/Account/CustomerAccountService.cs @@ -284,14 +284,14 @@ namespace EOM.TSHotelManagement.Service var customerResult = customerRepository.Insert(new Customer { CustomerNumber = customerNumber, - CustomerName = string.Empty, - CustomerGender = 0, + Name = string.Empty, + Gender = 0, CustomerType = 0, - CustomerPhoneNumber = string.Empty, - CustomerAddress = string.Empty, + PhoneNumber = string.Empty, + Address = string.Empty, DateOfBirth = DateOnly.MinValue, IdCardNumber = string.Empty, - PassportId = 0, + IdCardType = 0, IsDelete = 0, DataInsUsr = readCustomerAccountInputDto.Account, DataInsDate = DateTime.Now diff --git a/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs b/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs index d5681ce..05603dc 100644 --- a/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs +++ b/EOM.TSHotelManagement.Service/Business/Customer/CustomerService.cs @@ -110,9 +110,9 @@ namespace EOM.TSHotelManagement.Service public BaseResponse InsertCustomerInfo(CreateCustomerInputDto custo) { string NewID = dataProtector.EncryptCustomerData(custo.IdCardNumber); - string NewTel = dataProtector.EncryptCustomerData(custo.CustomerPhoneNumber); + string NewTel = dataProtector.EncryptCustomerData(custo.PhoneNumber); custo.IdCardNumber = NewID; - custo.CustomerPhoneNumber = NewTel; + custo.PhoneNumber = NewTel; try { if (custoRepository.IsAny(a => a.CustomerNumber == custo.CustomerNumber)) @@ -173,9 +173,9 @@ namespace EOM.TSHotelManagement.Service public BaseResponse UpdCustomerInfo(UpdateCustomerInputDto custo) { string NewID = dataProtector.EncryptCustomerData(custo.IdCardNumber); - string NewTel = dataProtector.EncryptCustomerData(custo.CustomerPhoneNumber); + string NewTel = dataProtector.EncryptCustomerData(custo.PhoneNumber); custo.IdCardNumber = NewID; - custo.CustomerPhoneNumber = NewTel; + custo.PhoneNumber = NewTel; try { if (!custoRepository.IsAny(a => a.CustomerNumber == custo.CustomerNumber)) @@ -356,18 +356,18 @@ namespace EOM.TSHotelManagement.Service { Id = source.Id, CustomerNumber = source.CustomerNumber, - CustomerName = source.CustomerName, - CustomerGender = source.CustomerGender, - PassportId = source.PassportId, - GenderName = genderMap.TryGetValue(source.CustomerGender ?? 0, out var genderName) ? genderName : "", - CustomerPhoneNumber = dataProtector.SafeDecryptCustomerData(source.CustomerPhoneNumber), + Name = source.Name, + Gender = source.Gender, + IdCardType = source.IdCardType, + GenderName = genderMap.TryGetValue(source.Gender, out var genderName) ? genderName : "", + PhoneNumber = dataProtector.SafeDecryptCustomerData(source.PhoneNumber), DateOfBirth = source.DateOfBirth.ToDateTime(TimeOnly.MinValue), CustomerType = source.CustomerType, - CustomerTypeName = custoTypeMap.TryGetValue(source.CustomerType, out var customerTypeName) ? customerTypeName : "", - PassportName = passPortTypeMap.TryGetValue(source.PassportId, out var passportName) ? passportName : "", - IdCardNumber = dataProtector.SafeDecryptCustomerData(source.IdCardNumber), - CustomerAddress = source.CustomerAddress ?? "", - DataInsUsr = source.DataInsUsr, + CustomerTypeName = custoTypeMap.TryGetValue(source.CustomerType, out var customerTypeName) ? customerTypeName : "", + PassportName = passPortTypeMap.TryGetValue(source.IdCardType, out var passportName) ? passportName : "", + IdCardNumber = dataProtector.SafeDecryptCustomerData(source.IdCardNumber), + Address = source.Address ?? "", + DataInsUsr = source.DataInsUsr, DataInsDate = source.DataInsDate, DataChgUsr = source.DataChgUsr, DataChgDate = source.DataChgDate, @@ -386,17 +386,17 @@ namespace EOM.TSHotelManagement.Service { Id = source.Id, CustomerNumber = source.CustomerNumber, - CustomerName = source.CustomerName, - CustomerGender = source.CustomerGender, - PassportId = source.PassportId, - GenderName = genderMap.TryGetValue(source.CustomerGender ?? 0, out var genderName) ? genderName : "", - CustomerPhoneNumber = dataProtector.SafeDecryptCustomerData(source.CustomerPhoneNumber), + Name = source.Name, + Gender = source.Gender, + IdCardType = source.IdCardType, + GenderName = genderMap.TryGetValue(source.Gender, out var genderName) ? genderName : "", + PhoneNumber = dataProtector.SafeDecryptCustomerData(source.PhoneNumber), DateOfBirth = source.DateOfBirth.ToDateTime(TimeOnly.MinValue), CustomerType = source.CustomerType, CustomerTypeName = custoTypeMap.TryGetValue(source.CustomerType, out var customerTypeName) ? customerTypeName : "", - PassportName = passPortTypeMap.TryGetValue(source.PassportId, out var passportName) ? passportName : "", + PassportName = passPortTypeMap.TryGetValue(source.IdCardType, out var passportName) ? passportName : "", IdCardNumber = dataProtector.SafeDecryptCustomerData(source.IdCardNumber), - CustomerAddress = source.CustomerAddress ?? "", + Address = source.Address ?? "", DataInsUsr = source.DataInsUsr, DataInsDate = source.DataInsDate, DataChgUsr = source.DataChgUsr, @@ -454,17 +454,17 @@ namespace EOM.TSHotelManagement.Service return new SingleOutputDto { Code = BusinessStatusCode.InternalServerError, Message = "该用户不存在" }; } + singleOutputDto.Data = EntityMapper.Map(customer); + //解密身份证号码/联系方式(失败时回退原值) - customer.IdCardNumber = dataProtector.SafeDecryptCustomerData(customer.IdCardNumber); - customer.CustomerPhoneNumber = dataProtector.SafeDecryptCustomerData(customer.CustomerPhoneNumber); + singleOutputDto.Data.IdCardNumber = dataProtector.SafeDecryptCustomerData(customer.IdCardNumber); + singleOutputDto.Data.PhoneNumber = dataProtector.SafeDecryptCustomerData(customer.PhoneNumber); //性别类型 - customer.GenderName = genderMap.TryGetValue((int)customer.CustomerGender!, out var genderName) ? genderName : ""; + singleOutputDto.Data.GenderName = genderMap.TryGetValue((int)customer.Gender!, out var genderName) ? genderName : ""; //证件类型 - customer.PassportName = passPortTypeMap.TryGetValue(customer.PassportId, out var passportName) ? passportName : ""; + singleOutputDto.Data.PassportName = passPortTypeMap.TryGetValue(customer.IdCardType, out var passportName) ? passportName : ""; //客户类型 - customer.CustomerTypeName = custoTypeMap.TryGetValue(customer.CustomerType, out var customerTypeName) ? customerTypeName : ""; - - singleOutputDto.Data = EntityMapper.Map(customer); + singleOutputDto.Data.CustomerTypeName = custoTypeMap.TryGetValue(customer.CustomerType, out var customerTypeName) ? customerTypeName : ""; return singleOutputDto; } diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index ff820ba..9fff45f 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -192,7 +192,7 @@ namespace EOM.TSHotelManagement.Service .Where(a => a.IsDelete != 1 && customerNumbers.Contains(a.CustomerNumber)) .ToList() .GroupBy(a => a.CustomerNumber) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.CustomerName ?? "", StringComparer.OrdinalIgnoreCase); + .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.Name ?? "", StringComparer.OrdinalIgnoreCase); } var helper = new EnumHelper(); @@ -904,12 +904,12 @@ namespace EOM.TSHotelManagement.Service var customer = new Customer { CustomerNumber = checkinRoomByReservationDto.CustomerNumber, - CustomerName = checkinRoomByReservationDto.CustomerName, - CustomerGender = checkinRoomByReservationDto.CustomerGender, - CustomerPhoneNumber = checkinRoomByReservationDto.CustomerPhoneNumber, - PassportId = checkinRoomByReservationDto.PassportId, + Name = checkinRoomByReservationDto.CustomerName, + Gender = checkinRoomByReservationDto.CustomerGender ?? 0, + PhoneNumber = checkinRoomByReservationDto.CustomerPhoneNumber, + IdCardType = checkinRoomByReservationDto.PassportId, IdCardNumber = checkinRoomByReservationDto.IdCardNumber, - CustomerAddress = checkinRoomByReservationDto.CustomerAddress, + Address = checkinRoomByReservationDto.CustomerAddress, DateOfBirth = checkinRoomByReservationDto.DateOfBirth, CustomerType = checkinRoomByReservationDto.CustomerType, IsDelete = 0, diff --git a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs index 4f36ea6..5248f94 100644 --- a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs +++ b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs @@ -207,8 +207,8 @@ namespace EOM.TSHotelManagement.Service businessStatisticsOutputDto.GenderRatio = new TempGenderRatio { - Male = customers.Count(a => a.CustomerGender == (int)GenderType.Male), - Female = customers.Count(a => a.CustomerGender == (int)GenderType.Female) + Male = customers.Count(a => a.Gender == (int)GenderType.Male), + Female = customers.Count(a => a.Gender == (int)GenderType.Female) }; var memberTypeDict = customerTypes.ToDictionary(rt => rt.CustomerType, rt => rt.CustomerTypeName); diff --git a/EOM.TSHotelManagement.Service/Employee/EmployeeService.cs b/EOM.TSHotelManagement.Service/Employee/EmployeeService.cs index 205f189..59ed299 100644 --- a/EOM.TSHotelManagement.Service/Employee/EmployeeService.cs +++ b/EOM.TSHotelManagement.Service/Employee/EmployeeService.cs @@ -194,7 +194,7 @@ namespace EOM.TSHotelManagement.Service var newPassword = new RandomStringGenerator().GenerateSecurePassword(); sourcePwdStr = dataProtector.EncryptEmployeeData(newPassword); - var emailTemplate = EmailTemplate.GetNewRegistrationTemplate(createEmployeeInputDto.EmployeeName, newPassword); + var emailTemplate = EmailTemplate.GetNewRegistrationTemplate(createEmployeeInputDto.Name, newPassword); var result = mailHelper.SendMail(new List { createEmployeeInputDto.EmailAddress }, emailTemplate.Subject, emailTemplate.Body, new List { createEmployeeInputDto.EmailAddress }); if (!result) { @@ -284,7 +284,7 @@ namespace EOM.TSHotelManagement.Service { Id = source.Id, EmployeeId = source.EmployeeId, - EmployeeName = source.EmployeeName, + Name = source.Name, Gender = source.Gender, GenderName = genderMap.TryGetValue(source.Gender, out var genderName) ? genderName : "", DateOfBirth = source.DateOfBirth.ToDateTime(TimeOnly.MinValue), @@ -328,7 +328,7 @@ namespace EOM.TSHotelManagement.Service { Id = source.Id, EmployeeId = source.EmployeeId, - EmployeeName = source.EmployeeName, + Name = source.Name, Gender = source.Gender, GenderName = genderMap.TryGetValue(source.Gender, out var genderName) ? genderName : "", DateOfBirth = source.DateOfBirth.ToDateTime(TimeOnly.MinValue), @@ -392,33 +392,34 @@ namespace EOM.TSHotelManagement.Service }) .ToList(); w = workerRepository.GetFirst(a => a.EmployeeId == readEmployeeInputDto.EmployeeId); + + var source = EntityMapper.Map(w); + //解密身份证号码 var sourceStr = w.IdCardNumber.IsNullOrEmpty() ? "" : dataProtector.SafeDecryptEmployeeData(w.IdCardNumber); - w.IdCardNumber = sourceStr; + source.IdCardNumber = sourceStr; //解密联系方式 var sourceTelStr = w.PhoneNumber.IsNullOrEmpty() ? "" : dataProtector.SafeDecryptEmployeeData(w.PhoneNumber); - w.PhoneNumber = sourceTelStr; + source.PhoneNumber = sourceTelStr; //性别类型 - var sexType = genders.SingleOrDefault(a => a.Id == w.Gender); - w.GenderName = sexType.Description.IsNullOrEmpty() ? "" : sexType.Description; + var genderType = genders.SingleOrDefault(a => a.Id == w.Gender); + source.GenderName = genderType.Description.IsNullOrEmpty() ? "" : genderType.Description; //教育程度 var eduction = educationRepository.GetFirst(a => a.EducationNumber == w.EducationLevel); - w.EducationLevelName = eduction.EducationName.IsNullOrEmpty() ? "" : eduction.EducationName; + source.EducationLevelName = eduction.EducationName.IsNullOrEmpty() ? "" : eduction.EducationName; //民族类型 var nation = nationRepository.GetFirst(a => a.NationNumber == w.Ethnicity); - w.EthnicityName = nation.NationName.IsNullOrEmpty() ? "" : nation.NationName; + source.EthnicityName = nation.NationName.IsNullOrEmpty() ? "" : nation.NationName; //部门 var dept = deptRepository.GetFirst(a => a.DepartmentNumber == w.Department); - w.DepartmentName = dept.DepartmentName.IsNullOrEmpty() ? "" : dept.DepartmentName; + source.DepartmentName = dept.DepartmentName.IsNullOrEmpty() ? "" : dept.DepartmentName; //职位 var position = positionRepository.GetFirst(a => a.PositionNumber == w.Position); - w.PositionName = position.PositionName.IsNullOrEmpty() ? "" : position.PositionName; + source.PositionName = position.PositionName.IsNullOrEmpty() ? "" : position.PositionName; var passport = passportTypeRepository.GetFirst(a => a.PassportId == w.IdCardType); - w.IdCardTypeName = passport.IsNullOrEmpty() ? "" : passport.PassportName; + source.IdCardTypeName = passport.IsNullOrEmpty() ? "" : passport.PassportName; //面貌 - w.PoliticalAffiliationName = new EnumHelper().GetDescriptionByName(w.PoliticalAffiliation); - - var source = EntityMapper.Map(w); + source.PoliticalAffiliationName = new EnumHelper().GetDescriptionByName(w.PoliticalAffiliation); var employeePhoto = photoRepository.GetFirst(a => a.EmployeeId.Equals(source.EmployeeId)); if (employeePhoto != null && !string.IsNullOrEmpty(employeePhoto.PhotoPath)) @@ -470,7 +471,7 @@ namespace EOM.TSHotelManagement.Service Data = new ReadEmployeeOutputDto { EmployeeId = w.EmployeeId, - EmployeeName = w.EmployeeName, + Name = w.Name, RequiresTwoFactor = true } }; @@ -486,7 +487,7 @@ namespace EOM.TSHotelManagement.Service Data = new ReadEmployeeOutputDto { EmployeeId = w.EmployeeId, - EmployeeName = w.EmployeeName, + Name = w.Name, RequiresTwoFactor = true } }; @@ -494,33 +495,35 @@ namespace EOM.TSHotelManagement.Service } w.Password = ""; + + var output = EntityMapper.Map(w); + //性别类型 - var sexType = genders.SingleOrDefault(a => a.Id == w.Gender); - w.GenderName = sexType.Description.IsNullOrEmpty() ? "" : sexType.Description; + var genderType = genders.SingleOrDefault(a => a.Id == w.Gender); + output.GenderName = genderType.Description.IsNullOrEmpty() ? "" : genderType.Description; //教育程度 var eduction = educationRepository.GetFirst(a => a.EducationNumber == w.EducationLevel); - w.EducationLevelName = eduction.EducationName.IsNullOrEmpty() ? "" : eduction.EducationName; + output.EducationLevelName = eduction.EducationName.IsNullOrEmpty() ? "" : eduction.EducationName; //民族类型 var nation = nationRepository.GetFirst(a => a.NationNumber == w.Ethnicity); - w.EthnicityName = nation.NationName.IsNullOrEmpty() ? "" : nation.NationName; + output.EthnicityName = nation.NationName.IsNullOrEmpty() ? "" : nation.NationName; //部门 var dept = deptRepository.GetFirst(a => a.DepartmentNumber == w.Department); - w.DepartmentName = dept.DepartmentName.IsNullOrEmpty() ? "" : dept.DepartmentName; + output.DepartmentName = dept.DepartmentName.IsNullOrEmpty() ? "" : dept.DepartmentName; //职位 var position = positionRepository.GetFirst(a => a.PositionNumber == w.Position); - w.PositionName = position.PositionName.IsNullOrEmpty() ? "" : position.PositionName; + output.PositionName = position.PositionName.IsNullOrEmpty() ? "" : position.PositionName; - w.UserToken = jWTHelper.GenerateJWT(new ClaimsIdentity(new Claim[] + output.UserToken = jWTHelper.GenerateJWT(new ClaimsIdentity(new Claim[] { - new Claim(ClaimTypes.Name, w.EmployeeName), + new Claim(ClaimTypes.Name, w.Name), new Claim(ClaimTypes.SerialNumber, w.EmployeeId) })); - var output = EntityMapper.Map(w); output.RequiresTwoFactor = false; output.UsedRecoveryCodeLogin = usedRecoveryCode; if (usedRecoveryCode) { - NotifyRecoveryCodeLoginByEmail(w.EmailAddress, w.EmployeeName, w.EmployeeId); + NotifyRecoveryCodeLoginByEmail(w.EmailAddress, w.Name, w.EmployeeId); } return new SingleOutputDto { Data = output }; } @@ -621,7 +624,7 @@ namespace EOM.TSHotelManagement.Service if (!employee.EmailAddress.IsNullOrEmpty()) { - var mailTemplate = EmailTemplate.GetUpdatePasswordTemplate(employee.EmployeeName, newPwd); + var mailTemplate = EmailTemplate.GetUpdatePasswordTemplate(employee.Name, newPwd); mailHelper.SendMail(new List { employee.EmailAddress }, mailTemplate.Subject, mailTemplate.Body, new List { employee.EmailAddress }); } @@ -664,7 +667,7 @@ namespace EOM.TSHotelManagement.Service }; } - var mailTemplate = EmailTemplate.GetResetPasswordTemplate(employee.EmployeeName, newPwd); + var mailTemplate = EmailTemplate.GetResetPasswordTemplate(employee.Name, newPwd); var result = mailHelper.SendMail(new List { emailAddress }, mailTemplate.Subject, mailTemplate.Body, diff --git a/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs b/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs index a364c49..3a33895 100644 --- a/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs +++ b/EOM.TSHotelManagement.Service/SystemManagement/Base/BaseService.cs @@ -723,7 +723,7 @@ namespace EOM.TSHotelManagement.Service source.ParentDepartmentName = parentDepartment.IsNullOrEmpty() ? "" : parentDepartment.DepartmentName; var departmentLeader = departmentLeaders.SingleOrDefault(a => a.EmployeeId.Equals(source.DepartmentLeader)); - source.LeaderName = departmentLeader.IsNullOrEmpty() ? "" : departmentLeader.EmployeeName; + source.LeaderName = departmentLeader.IsNullOrEmpty() ? "" : departmentLeader.Name; }); var result = EntityMapper.MapList(depts); return new ListOutputDto @@ -1132,7 +1132,7 @@ namespace EOM.TSHotelManagement.Service // 当前证件类型下是否有客户 var passportTypeNumbers = passPortTypes.Select(a => a.PassportId).ToList(); - var customerCount = customerRepository.AsQueryable().Count(a => passportTypeNumbers.Contains(a.PassportId)); + var customerCount = customerRepository.AsQueryable().Count(a => passportTypeNumbers.Contains(a.IdCardType)); if (customerCount > 0) { return new BaseResponse -- Gitee From eba7df3d4e5db712799d9dda095439a90f3e2c38 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 14 Mar 2026 02:53:33 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E6=B6=88=E8=B4=B9DTO=E4=B8=8E=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=89=88=E6=9C=AC=E5=8F=B7=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次提交主要内容: - 客户消费DTO结构调整,字段更名与必填校验增强,新增撤销消费DTO - 撤销消费接口参数由UpdateSpendInputDto改为UndoCustomerSpendInputDto,业务逻辑仅允许撤销商品消费并自动回滚库存 - 日志记录优化,操作人从Claims获取,日志内容更详细 - 新增SoftwareVersionHelper,统一版本号获取方式,相关中间件与接口同步调整 - 新增ClaimsPrincipalExtensions,提升用户信息获取复用性 - 配置文件调整:MariaDB连接、本地初始化、JWT密钥与过期时间 - 其他:.gitignore优化,代码风格与注释完善 整体提升了消费相关接口的数据一致性、日志安全性、版本号管理统一性及系统可维护性。 --- .gitignore | 1 + .../Business/Spend/SpendController.cs | 6 +- .../Extensions/ApplicationExtensions.cs | 2 +- .../Filters/RequestLoggingMiddleware.cs | 30 +------ .../Helper/ClaimsPrincipalExtensions.cs | 15 ++++ .../Helper/SoftwareVersionHelper.cs | 51 +++++++++++ .../Dto/Spend/AddCustomerSpendInputDto.cs | 11 +-- .../Dto/Spend/UndoCustomerSpendInputDto.cs | 9 ++ .../Business/Spend/ISpendService.cs | 8 +- .../Business/Spend/SpendService.cs | 89 ++++++++++++++----- 10 files changed, 160 insertions(+), 62 deletions(-) create mode 100644 EOM.TSHotelManagement.Common/Helper/ClaimsPrincipalExtensions.cs create mode 100644 EOM.TSHotelManagement.Common/Helper/SoftwareVersionHelper.cs create mode 100644 EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UndoCustomerSpendInputDto.cs diff --git a/.gitignore b/.gitignore index 4605860..aa1f521 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ frontend/ .version *.txt docs/ +.codex-staging/ # Visual Studio 2015/2017 cache/options directory .vs/ diff --git a/EOM.TSHotelManagement.API/Controllers/Business/Spend/SpendController.cs b/EOM.TSHotelManagement.API/Controllers/Business/Spend/SpendController.cs index 136169d..227cca3 100644 --- a/EOM.TSHotelManagement.API/Controllers/Business/Spend/SpendController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Business/Spend/SpendController.cs @@ -67,13 +67,13 @@ namespace EOM.TSHotelManagement.WebApi.Controllers /// /// 撤回客户消费信息 /// - /// + /// /// [RequirePermission("customerspend.ucs")] [HttpPost] - public BaseResponse UndoCustomerSpend([FromBody] UpdateSpendInputDto updateSpendInputDto) + public BaseResponse UndoCustomerSpend([FromBody] UndoCustomerSpendInputDto undoCustomerSpendInputDto) { - return spendService.UndoCustomerSpend(updateSpendInputDto); + return spendService.UndoCustomerSpend(undoCustomerSpendInputDto); } /// diff --git a/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs index f3342a5..c08e4fc 100644 --- a/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs @@ -85,7 +85,7 @@ namespace EOM.TSHotelManagement.WebApi { app.MapControllers(); app.MapGet("api/version", () => - $"Software Version: {Environment.GetEnvironmentVariable("SoftwareVersion") ?? "Local Mode"}"); + $"Software Version: {SoftwareVersionHelper.GetSoftwareVersion(app.Configuration["SoftwareVersion"], "Local Mode")}"); } public static void ConfigureSwaggerUI(this WebApplication app) diff --git a/EOM.TSHotelManagement.API/Filters/RequestLoggingMiddleware.cs b/EOM.TSHotelManagement.API/Filters/RequestLoggingMiddleware.cs index ddad22c..a930483 100644 --- a/EOM.TSHotelManagement.API/Filters/RequestLoggingMiddleware.cs +++ b/EOM.TSHotelManagement.API/Filters/RequestLoggingMiddleware.cs @@ -25,9 +25,7 @@ public class RequestLoggingMiddleware { _next = next; _logger = logger; - _softwareVersion = Environment.GetEnvironmentVariable("APP_VERSION") - ?? config["SoftwareVersion"] - ?? GetDefaultVersion(); + _softwareVersion = EOM.TSHotelManagement.Common.SoftwareVersionHelper.GetSoftwareVersion(config["SoftwareVersion"]); } public async Task InvokeAsync(HttpContext context) @@ -147,30 +145,6 @@ public class RequestLoggingMiddleware return (long)((stop - start) * 1000 / (double)Stopwatch.Frequency); } - private string GetDefaultVersion() - { - try - { - var rootPath = Path.GetDirectoryName(GetType().Assembly.Location); - var versionFilePath = Path.Combine(rootPath, "version.txt"); - - if (File.Exists(versionFilePath)) - { - var versionContent = File.ReadAllText(versionFilePath).Trim(); - if (!string.IsNullOrWhiteSpace(versionContent)) - { - return versionContent; - } - } - } - catch (Exception ex) - { - Debug.WriteLine($"Error reading version.txt: {ex.Message}"); - } - - return GetType().Assembly.GetName().Version?.ToString(3) ?? "1.0.0"; - } - private async Task GetRequestParametersAsync(HttpRequest request) { if (request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase)) @@ -245,4 +219,4 @@ public class RequestLoggingMiddleware ip.StartsWith("172.30.") || ip.StartsWith("172.31."); } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Common/Helper/ClaimsPrincipalExtensions.cs b/EOM.TSHotelManagement.Common/Helper/ClaimsPrincipalExtensions.cs new file mode 100644 index 0000000..91e6dbc --- /dev/null +++ b/EOM.TSHotelManagement.Common/Helper/ClaimsPrincipalExtensions.cs @@ -0,0 +1,15 @@ +using System.Security.Claims; + +namespace EOM.TSHotelManagement.Common +{ + public static class ClaimsPrincipalExtensions + { + public static string GetUserNumber(this ClaimsPrincipal? principal) + { + return principal?.FindFirst(ClaimTypes.SerialNumber)?.Value + ?? principal?.FindFirst("serialnumber")?.Value + ?? principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value + ?? string.Empty; + } + } +} diff --git a/EOM.TSHotelManagement.Common/Helper/SoftwareVersionHelper.cs b/EOM.TSHotelManagement.Common/Helper/SoftwareVersionHelper.cs new file mode 100644 index 0000000..dca9932 --- /dev/null +++ b/EOM.TSHotelManagement.Common/Helper/SoftwareVersionHelper.cs @@ -0,0 +1,51 @@ +using System.Reflection; + +namespace EOM.TSHotelManagement.Common +{ + public static class SoftwareVersionHelper + { + public static string GetSoftwareVersion(string? configuredVersion = null, string defaultVersion = "1.0.0") + { + var version = Environment.GetEnvironmentVariable("APP_VERSION") + ?? Environment.GetEnvironmentVariable("SoftwareVersion") + ?? configuredVersion + ?? GetVersionFromFile() + ?? GetAssemblyVersion(); + + return string.IsNullOrWhiteSpace(version) ? defaultVersion : version.Trim(); + } + + private static string? GetVersionFromFile() + { + try + { + var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly(); + var rootPath = Path.GetDirectoryName(assembly.Location); + if (string.IsNullOrWhiteSpace(rootPath)) + { + return null; + } + + var versionFilePath = Path.Combine(rootPath, "version.txt"); + if (!File.Exists(versionFilePath)) + { + return null; + } + + var versionContent = File.ReadAllText(versionFilePath).Trim(); + return string.IsNullOrWhiteSpace(versionContent) ? null : versionContent; + } + catch + { + return null; + } + } + + private static string? GetAssemblyVersion() + { + var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly(); + return assembly.GetCustomAttribute()?.InformationalVersion + ?? assembly.GetName().Version?.ToString(3); + } + } +} diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs index 6b0e286..5894dd3 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs @@ -1,9 +1,12 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace EOM.TSHotelManagement.Contract { public class AddCustomerSpendInputDto { + [Required(ErrorMessage = "消费编号为必填字段")] + public string SpendNumber { get; set; } + [Required(ErrorMessage = "房间编号为必填字段")] public string RoomNumber { get; set; } @@ -14,12 +17,10 @@ namespace EOM.TSHotelManagement.Contract public string ProductName { get; set; } [Required(ErrorMessage = "数量为必填字段")] - public int Quantity { get; set; } + public int ConsumptionQuantity { get; set; } [Required(ErrorMessage = "价格为必填字段")] - public decimal Price { get; set; } - - public string WorkerNo { get; set; } + public decimal ProductPrice { get; set; } public string SoftwareVersion { get; set; } } diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UndoCustomerSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UndoCustomerSpendInputDto.cs new file mode 100644 index 0000000..f9905c4 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UndoCustomerSpendInputDto.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Contract; + +public class UndoCustomerSpendInputDto : BaseInputDto +{ +} diff --git a/EOM.TSHotelManagement.Service/Business/Spend/ISpendService.cs b/EOM.TSHotelManagement.Service/Business/Spend/ISpendService.cs index bd9d152..e94eb72 100644 --- a/EOM.TSHotelManagement.Service/Business/Spend/ISpendService.cs +++ b/EOM.TSHotelManagement.Service/Business/Spend/ISpendService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -68,9 +68,9 @@ namespace EOM.TSHotelManagement.Service /// /// 撤回客户消费信息 /// - /// + /// /// - BaseResponse UndoCustomerSpend(UpdateSpendInputDto updateSpendInputDto); + BaseResponse UndoCustomerSpend(UndoCustomerSpendInputDto undoCustomerSpendInputDto); /// /// 添加客户消费信息 @@ -86,4 +86,4 @@ namespace EOM.TSHotelManagement.Service /// BaseResponse UpdSpendInfo(UpdateSpendInputDto updateSpendInputDto); } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs index bfebddc..65eb0d6 100644 --- a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs +++ b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs @@ -276,24 +276,76 @@ namespace EOM.TSHotelManagement.Service /// /// 撤回客户消费信息 /// - /// + /// /// - public BaseResponse UndoCustomerSpend(UpdateSpendInputDto updateSpendInputDto) + public BaseResponse UndoCustomerSpend(UndoCustomerSpendInputDto undoCustomerSpendInputDto) { + var httpContext = _httpContextAccessor.HttpContext; + using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); + try { - var existingSpend = spendRepository.GetFirst(a => a.SpendNumber == updateSpendInputDto.SpendNumber && a.IsDelete != 1); + var existingSpend = spendRepository.GetFirst(a => a.Id == undoCustomerSpendInputDto.Id && a.IsDelete != 1); if (existingSpend == null) { return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Spend record not found", "消费记录不存在")); } + + if (existingSpend.ConsumptionType != SpendTypeConstant.Product.Code) + { + return new BaseResponse(BusinessStatusCode.BadRequest, LocalizationHelper.GetLocalizedString("Cancellation of non-commodity consumption records is not allowed", "不允许撤销非商品消费记录")); + } + + var isProductSpend = string.Equals(existingSpend.ConsumptionType, SpendTypeConstant.Product.Code, StringComparison.OrdinalIgnoreCase) + && !string.IsNullOrWhiteSpace(existingSpend.ProductNumber) + && existingSpend.ConsumptionQuantity > 0; + + if (isProductSpend) + { + var product = sellThingRepository.GetFirst(a => a.ProductNumber == existingSpend.ProductNumber && a.IsDelete != 1); + if (product == null) + { + return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Product not found", "商品不存在")); + } + + product.Stock += existingSpend.ConsumptionQuantity; + var productUpdateResult = sellThingRepository.Update(product); + if (!productUpdateResult) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + } + existingSpend.IsDelete = 1; - existingSpend.RowVersion = updateSpendInputDto.RowVersion ?? 0; + existingSpend.RowVersion = undoCustomerSpendInputDto.RowVersion ?? 0; var updateResult = spendRepository.Update(existingSpend); if (!updateResult) { return BaseResponseFactory.ConcurrencyConflict(); } + + var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} 撤销了消费记录: " + + $"房间 {existingSpend.RoomNumber}, " + + $"商品 {existingSpend.ProductName}, " + + $"数量 {existingSpend.ConsumptionQuantity}, " + + $"金额 {existingSpend.ConsumptionAmount.ToString("#,##0.00")}"; + + var context = _httpContextAccessor.HttpContext; + + var log = new OperationLog + { + OperationId = new UniqueCode().GetNewId("OP-"), + OperationTime = Convert.ToDateTime(DateTime.Now), + LogContent = logContent, + LoginIpAddress = context.Connection.RemoteIpAddress?.ToString() ?? string.Empty, + OperationAccount = ClaimsPrincipalExtensions.GetUserNumber(httpContext.User), + LogLevel = (int)Common.LogLevel.Warning, + SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), + }; + operationLogRepository.Insert(log); + + + scope.Complete(); } catch (Exception ex) { @@ -310,7 +362,8 @@ namespace EOM.TSHotelManagement.Service /// public BaseResponse AddCustomerSpend(AddCustomerSpendInputDto addCustomerSpendInputDto) { - if (addCustomerSpendInputDto?.Quantity <= 0 || addCustomerSpendInputDto.Price <= 0) + var httpContext = _httpContextAccessor.HttpContext; + if (addCustomerSpendInputDto?.ConsumptionQuantity <= 0 || addCustomerSpendInputDto.ProductPrice <= 0) { return new BaseResponse() { Message = "商品数量和价格必须大于零", Code = BusinessStatusCode.BadRequest }; } @@ -336,17 +389,15 @@ namespace EOM.TSHotelManagement.Service ? customerType.Discount / 100M : 1M; - decimal realAmount = addCustomerSpendInputDto.Price * addCustomerSpendInputDto.Quantity * discount; + decimal realAmount = addCustomerSpendInputDto.ProductPrice * addCustomerSpendInputDto.ConsumptionQuantity * discount; var existingSpend = spendRepository.AsQueryable().Single(a => a.RoomNumber == addCustomerSpendInputDto.RoomNumber && a.ProductNumber == addCustomerSpendInputDto.ProductNumber && a.IsDelete != 1 && a.SettlementStatus == ConsumptionConstant.UnSettle.Code); if (existingSpend != null) { existingSpend.ConsumptionType = SpendTypeConstant.Product.Code; - existingSpend.ConsumptionQuantity += addCustomerSpendInputDto.Quantity; + existingSpend.ConsumptionQuantity += addCustomerSpendInputDto.ConsumptionQuantity; existingSpend.ConsumptionAmount += realAmount; - existingSpend.DataChgDate = DateTime.Now; - existingSpend.DataChgUsr = addCustomerSpendInputDto.WorkerNo; var result = spendRepository.Update(existingSpend); if (!result) @@ -362,15 +413,13 @@ namespace EOM.TSHotelManagement.Service RoomNumber = addCustomerSpendInputDto.RoomNumber, ProductNumber = addCustomerSpendInputDto.ProductNumber, ProductName = addCustomerSpendInputDto.ProductName, - ConsumptionQuantity = addCustomerSpendInputDto.Quantity, + ConsumptionQuantity = addCustomerSpendInputDto.ConsumptionQuantity, CustomerNumber = room.CustomerNumber, - ProductPrice = addCustomerSpendInputDto.Price, + ProductPrice = addCustomerSpendInputDto.ProductPrice, ConsumptionAmount = realAmount, ConsumptionTime = DateTime.Now, ConsumptionType = SpendTypeConstant.Product.Code, - SettlementStatus = ConsumptionConstant.UnSettle.Code, - DataInsUsr = addCustomerSpendInputDto.WorkerNo, - DataInsDate = DateTime.Now + SettlementStatus = ConsumptionConstant.UnSettle.Code }; var result = spendRepository.Insert(newSpend); @@ -381,17 +430,17 @@ namespace EOM.TSHotelManagement.Service } var product = sellThingRepository.AsQueryable().Single(a => a.ProductNumber == addCustomerSpendInputDto.ProductNumber); - product.Stock = product.Stock - addCustomerSpendInputDto.Quantity; + product.Stock = product.Stock - addCustomerSpendInputDto.ConsumptionQuantity; var updateResult = sellThingRepository.Update(product); if (!updateResult) { return BaseResponseFactory.ConcurrencyConflict(); } - var logContent = $"{addCustomerSpendInputDto.WorkerNo} 添加了消费记录: " + + var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} 添加了消费记录: " + $"房间 {addCustomerSpendInputDto.RoomNumber}, " + $"商品 {addCustomerSpendInputDto.ProductName}, " + - $"数量 {addCustomerSpendInputDto.Quantity}, " + + $"数量 {addCustomerSpendInputDto.ConsumptionQuantity}, " + $"金额 {realAmount.ToString("#,##0.00")}"; var context = _httpContextAccessor.HttpContext; @@ -402,11 +451,9 @@ namespace EOM.TSHotelManagement.Service OperationTime = Convert.ToDateTime(DateTime.Now), LogContent = logContent, LoginIpAddress = context.Connection.RemoteIpAddress?.ToString() ?? string.Empty, - OperationAccount = addCustomerSpendInputDto.WorkerNo, + OperationAccount = ClaimsPrincipalExtensions.GetUserNumber(httpContext.User), LogLevel = (int)Common.LogLevel.Warning, - SoftwareVersion = addCustomerSpendInputDto.SoftwareVersion, - DataInsUsr = addCustomerSpendInputDto.WorkerNo, - DataInsDate = Convert.ToDateTime(DateTime.Now) + SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), }; operationLogRepository.Insert(log); -- Gitee From 5f386b966c796160922bd0201ee8d1970ac56721 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 14 Mar 2026 03:17:16 +0800 Subject: [PATCH 13/20] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A1=B9=E7=9B=AE=20Wi?= =?UTF-8?q?ki=20=E9=93=BE=E6=8E=A5=E8=87=B3=E4=B8=AD=E8=8B=B1=E6=96=87=20R?= =?UTF-8?q?EADME=20=E9=A1=B6=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 README.md 和 README.en.md 顶部增加了项目 Wiki 页面链接,便于用户快速访问和查阅相关文档与说明。 --- README.en.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.en.md b/README.en.md index 2eca5a3..88d4a10 100644 --- a/README.en.md +++ b/README.en.md @@ -8,6 +8,7 @@

## Project Overview diff --git a/README.md b/README.md index 8a70e2e..ba8b8cb 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@

## 项目简介 -- Gitee From 0541f604cf2597d8f763d17dc9dae1743b7b2b60 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 14 Mar 2026 13:16:21 +0800 Subject: [PATCH 14/20] =?UTF-8?q?=E6=88=BF=E9=97=B4=E5=94=AF=E4=B8=80?= =?UTF-8?q?=E6=A0=87=E8=AF=86=E5=8D=87=E7=BA=A7=EF=BC=9A=E6=94=AF=E6=8C=81?= =?UTF-8?q?RoomId/=E5=88=86=E5=8C=BA/=E6=A5=BC=E5=B1=82=E5=AE=9A=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 全面升级房间唯一性,支持RoomId、分区、楼层多维定位。数据库room表及相关表新增room_id、room_area、room_floor字段,领域模型与DTO同步扩展。服务层重构,所有房间操作优先用RoomId,兼容旧参数,查找歧义有明确错误提示。提升数据一致性,解决同号多房、分区/楼层管理等问题,为多楼层多分区场景打下基础。 --- .../Dto/CreateEnergyManagementInputDto.cs | 20 +- .../Dto/ReadEnergyManagementInputDto.cs | 1 + .../Dto/ReadEnergyManagementOutputDto.cs | 4 + .../Dto/UpdateEnergyManagementInputDto.cs | 20 +- .../Business/Reser/Dto/CreateReserInputDto.cs | 19 +- .../Business/Reser/Dto/ReadReserInputDto.cs | 1 + .../Business/Reser/Dto/ReadReserOutputDto.cs | 7 + .../Business/Reser/Dto/UpdateReserInputDto.cs | 18 +- .../Room/Dto/CheckinRoomByReservationDto.cs | 7 +- .../Business/Room/Dto/CheckoutRoomDto.cs | 6 +- .../Room/Dto/Room/CreateRoomInputDto.cs | 2 + .../Room/Dto/Room/ReadRoomInputDto.cs | 3 + .../Room/Dto/Room/ReadRoomOutputDto.cs | 3 + .../Room/Dto/Room/UpdateRoomInputDto.cs | 3 + .../Room/Dto/RoomType/ReadRoomTypeInputDto.cs | 3 + .../Business/Room/Dto/TransferRoomDto.cs | 12 +- .../Dto/Spend/AddCustomerSpendInputDto.cs | 14 +- .../Spend/Dto/Spend/CreateSpendInputDto.cs | 16 +- .../Spend/Dto/Spend/ReadSpendInputDto.cs | 2 + .../Spend/Dto/Spend/ReadSpendOutputDto.cs | 7 + .../Spend/Dto/Spend/UpdateSpendInputDto.cs | 14 +- .../DatabaseInitializer.cs | 93 ++ .../EnergyManagement/EnergyManagement.cs | 3 + .../Business/Reser/Reser.cs | 3 + .../Business/Room/Room.cs | 120 +- .../Business/Spend/Spend.cs | 3 + .../EnergyManagementService.cs | 249 ++-- .../Business/Reser/ReserService.cs | 526 ++++--- .../Business/Room/RoomLocatorHelper.cs | 101 ++ .../Business/Room/RoomReferenceHelper.cs | 64 + .../Business/Room/RoomService.cs | 1296 ++++++++--------- .../Business/Room/RoomTypeService.cs | 18 +- .../Business/Spend/SpendService.cs | 585 ++++---- .../Dashboard/DashboardService.cs | 2 +- 34 files changed, 1649 insertions(+), 1596 deletions(-) create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomLocatorHelper.cs create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomReferenceHelper.cs diff --git a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/CreateEnergyManagementInputDto.cs b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/CreateEnergyManagementInputDto.cs index 6451a26..2cdb089 100644 --- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/CreateEnergyManagementInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/CreateEnergyManagementInputDto.cs @@ -4,29 +4,31 @@ namespace EOM.TSHotelManagement.Contract { public class CreateEnergyManagementInputDto : BaseInputDto { - [Required(ErrorMessage = "信息编号为必填字段"), MaxLength(128, ErrorMessage = "信息编号长度不超过128字符")] + [Required(ErrorMessage = "InformationNumber is required."), MaxLength(128, ErrorMessage = "InformationNumber max length is 128.")] public string InformationNumber { get; set; } - [Required(ErrorMessage = "房间编号为必填字段"), MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + + [MaxLength(128, ErrorMessage = "RoomNumber max length is 128.")] public string RoomNumber { get; set; } - [Required(ErrorMessage = "客户编号为必填字段"), MaxLength(128, ErrorMessage = "客户编号长度不超过128字符")] + [Required(ErrorMessage = "CustomerNumber is required."), MaxLength(128, ErrorMessage = "CustomerNumber max length is 128.")] public string CustomerNumber { get; set; } - [Required(ErrorMessage = "开始日期为必填字段")] + [Required(ErrorMessage = "StartDate is required.")] public DateTime StartDate { get; set; } - [Required(ErrorMessage = "结束日期为必填字段")] + [Required(ErrorMessage = "EndDate is required.")] public DateTime EndDate { get; set; } - [Required(ErrorMessage = "电费为必填字段")] + [Required(ErrorMessage = "PowerUsage is required.")] public decimal PowerUsage { get; set; } - [Required(ErrorMessage = "水费为必填字段")] + [Required(ErrorMessage = "WaterUsage is required.")] public decimal WaterUsage { get; set; } - [Required(ErrorMessage = "记录员为必填字段"), MaxLength(150, ErrorMessage = "记录员长度不超过150字符")] + [Required(ErrorMessage = "Recorder is required."), MaxLength(150, ErrorMessage = "Recorder max length is 150.")] public string Recorder { get; set; } } } - diff --git a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs index 8cb9fe0..78f317f 100644 --- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs @@ -5,6 +5,7 @@ namespace EOM.TSHotelManagement.Contract public class ReadEnergyManagementInputDto : ListInputDto { public string? CustomerNumber { get; set; } + public int? RoomId { get; set; } public string? RoomNumber { get; set; } public DateOnly? StartDate { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementOutputDto.cs index 9f179e3..7774867 100644 --- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementOutputDto.cs @@ -6,8 +6,12 @@ namespace EOM.TSHotelManagement.Contract { public int? Id { get; set; } public string InformationId { get; set; } + public int? RoomId { get; set; } [UIDisplay("房间号")] public string RoomNumber { get; set; } + public string RoomArea { get; set; } + public int? RoomFloor { get; set; } + public string RoomLocator { get; set; } [UIDisplay("客户编号")] public string CustomerNumber { get; set; } [UIDisplay("开始日期")] diff --git a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/UpdateEnergyManagementInputDto.cs b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/UpdateEnergyManagementInputDto.cs index 9dce1db..7d6029b 100644 --- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/UpdateEnergyManagementInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/UpdateEnergyManagementInputDto.cs @@ -4,29 +4,31 @@ namespace EOM.TSHotelManagement.Contract { public class UpdateEnergyManagementInputDto : BaseInputDto { - [Required(ErrorMessage = "信息编号为必填字段"), MaxLength(128, ErrorMessage = "信息编号长度不超过128字符")] + [Required(ErrorMessage = "InformationId is required."), MaxLength(128, ErrorMessage = "InformationId max length is 128.")] public string InformationId { get; set; } - [Required(ErrorMessage = "房间编号为必填字段"), MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + + [MaxLength(128, ErrorMessage = "RoomNumber max length is 128.")] public string RoomNumber { get; set; } - [Required(ErrorMessage = "客户编号为必填字段"), MaxLength(128, ErrorMessage = "客户编号长度不超过128字符")] + [Required(ErrorMessage = "CustomerNumber is required."), MaxLength(128, ErrorMessage = "CustomerNumber max length is 128.")] public string CustomerNumber { get; set; } - [Required(ErrorMessage = "开始日期为必填字段")] + [Required(ErrorMessage = "StartDate is required.")] public DateTime StartDate { get; set; } - [Required(ErrorMessage = "结束日期为必填字段")] + [Required(ErrorMessage = "EndDate is required.")] public DateTime EndDate { get; set; } - [Required(ErrorMessage = "电费为必填字段")] + [Required(ErrorMessage = "PowerUsage is required.")] public decimal PowerUsage { get; set; } - [Required(ErrorMessage = "水费为必填字段")] + [Required(ErrorMessage = "WaterUsage is required.")] public decimal WaterUsage { get; set; } - [Required(ErrorMessage = "记录员为必填字段"), MaxLength(150, ErrorMessage = "记录员长度不超过150字符")] + [Required(ErrorMessage = "Recorder is required."), MaxLength(150, ErrorMessage = "Recorder max length is 150.")] public string Recorder { get; set; } } } - diff --git a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs index 26d2e7f..cf82876 100644 --- a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/CreateReserInputDto.cs @@ -4,27 +4,30 @@ namespace EOM.TSHotelManagement.Contract { public class CreateReserInputDto : BaseInputDto { - [Required(ErrorMessage = "预约编号为必填字段"), MaxLength(128, ErrorMessage = "预约编号长度不超过128字符")] + [Required(ErrorMessage = "ReservationId is required."), MaxLength(128, ErrorMessage = "ReservationId max length is 128.")] public string ReservationId { get; set; } - [Required(ErrorMessage = "客户名称为必填字段"), MaxLength(200, ErrorMessage = "客户名称长度不超过200字符")] + [Required(ErrorMessage = "CustomerName is required."), MaxLength(200, ErrorMessage = "CustomerName max length is 200.")] public string CustomerName { get; set; } - [Required(ErrorMessage = "预约电话为必填字段"), MaxLength(256, ErrorMessage = "预约电话长度不超过256字符")] + [Required(ErrorMessage = "ReservationPhoneNumber is required."), MaxLength(256, ErrorMessage = "ReservationPhoneNumber max length is 256.")] public string ReservationPhoneNumber { get; set; } - [Required(ErrorMessage = "预约房号为必填字段"), MaxLength(128, ErrorMessage = "预约房号长度不超过128字符")] + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + + [MaxLength(128, ErrorMessage = "ReservationRoomNumber max length is 128.")] public string ReservationRoomNumber { get; set; } - [Required(ErrorMessage = "预约渠道为必填字段"), MaxLength(50, ErrorMessage = "预约渠道长度不超过50字符")] + [Required(ErrorMessage = "ReservationChannel is required."), MaxLength(50, ErrorMessage = "ReservationChannel max length is 50.")] public string ReservationChannel { get; set; } - [Required(ErrorMessage = "预约起始日期为必填字段")] + [Required(ErrorMessage = "ReservationStartDate is required.")] public DateTime ReservationStartDate { get; set; } - [Required(ErrorMessage = "预约结束日期为必填字段")] + [Required(ErrorMessage = "ReservationEndDate is required.")] public DateTime ReservationEndDate { get; set; } + public int ReservationStatus { get; set; } = 0; } } - diff --git a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserInputDto.cs index 7dae661..0466e2b 100644 --- a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserInputDto.cs @@ -2,6 +2,7 @@ { public class ReadReserInputDto : ListInputDto { + public int? RoomId { get; set; } public string? ReservationId { get; set; } public string? CustomerName { get; set; } public string? ReservationPhoneNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserOutputDto.cs index 9ce46d1..8816cc4 100644 --- a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/ReadReserOutputDto.cs @@ -5,6 +5,7 @@ namespace EOM.TSHotelManagement.Contract public class ReadReserOutputDto : BaseOutputDto { public int? Id { get; set; } + public int? RoomId { get; set; } [UIDisplay("预约编号")] public string ReservationId { get; set; } @@ -18,6 +19,12 @@ namespace EOM.TSHotelManagement.Contract [UIDisplay("预定房号")] public string ReservationRoomNumber { get; set; } + public string RoomArea { get; set; } + + public int? RoomFloor { get; set; } + + public string RoomLocator { get; set; } + [UIDisplay("预约渠道")] public string ReservationChannel { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/UpdateReserInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/UpdateReserInputDto.cs index c0ed9a9..cb69d7b 100644 --- a/EOM.TSHotelManagement.Contract/Business/Reser/Dto/UpdateReserInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Reser/Dto/UpdateReserInputDto.cs @@ -4,26 +4,28 @@ namespace EOM.TSHotelManagement.Contract { public class UpdateReserInputDto : BaseInputDto { - [Required(ErrorMessage = "预约编号为必填字段"), MaxLength(128, ErrorMessage = "预约编号长度不超过128字符")] + [Required(ErrorMessage = "ReservationId is required."), MaxLength(128, ErrorMessage = "ReservationId max length is 128.")] public string ReservationId { get; set; } - [Required(ErrorMessage = "客户名称为必填字段"), MaxLength(200, ErrorMessage = "客户名称长度不超过200字符")] + [Required(ErrorMessage = "CustomerName is required."), MaxLength(200, ErrorMessage = "CustomerName max length is 200.")] public string CustomerName { get; set; } - [Required(ErrorMessage = "预约电话为必填字段"), MaxLength(256, ErrorMessage = "预约电话长度不超过256字符")] + [Required(ErrorMessage = "ReservationPhoneNumber is required."), MaxLength(256, ErrorMessage = "ReservationPhoneNumber max length is 256.")] public string ReservationPhoneNumber { get; set; } - [Required(ErrorMessage = "预约房号为必填字段"), MaxLength(128, ErrorMessage = "预约房号长度不超过128字符")] + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + + [MaxLength(128, ErrorMessage = "ReservationRoomNumber max length is 128.")] public string ReservationRoomNumber { get; set; } - [Required(ErrorMessage = "预约渠道为必填字段"), MaxLength(50, ErrorMessage = "预约渠道长度不超过50字符")] + [Required(ErrorMessage = "ReservationChannel is required."), MaxLength(50, ErrorMessage = "ReservationChannel max length is 50.")] public string ReservationChannel { get; set; } - [Required(ErrorMessage = "预约起始日期为必填字段")] + [Required(ErrorMessage = "ReservationStartDate is required.")] public DateTime ReservationStartDate { get; set; } - [Required(ErrorMessage = "预约结束日期为必填字段")] + [Required(ErrorMessage = "ReservationEndDate is required.")] public DateTime ReservationEndDate { get; set; } } } - diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs index e24472d..8f328fe 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs @@ -30,8 +30,13 @@ namespace EOM.TSHotelManagement.Contract [Required(ErrorMessage = "客户类型为必填字段")] public int CustomerType { get; set; } - [Required(ErrorMessage = "房间编号为必填字段"), MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] + [Required(ErrorMessage = "房间ID为必填字段")] + public int? RoomId { get; set; } + + [MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] public string RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } [Required(ErrorMessage = "预约编号为必填字段"), MaxLength(128, ErrorMessage = "预约编号长度不超过128字符")] public string ReservationId { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckoutRoomDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckoutRoomDto.cs index 96c653a..8453d24 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckoutRoomDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckoutRoomDto.cs @@ -4,8 +4,12 @@ namespace EOM.TSHotelManagement.Contract { public class CheckoutRoomDto : BaseInputDto { - [Required(ErrorMessage = "房间编号为必填字段"), MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] + [Required(ErrorMessage = "房间ID为必填字段")] + public int? RoomId { get; set; } + [MaxLength(128, ErrorMessage = "房间编号长度不超过128字符")] public string RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } [Required(ErrorMessage = "客户编号为必填字段"), MaxLength(128, ErrorMessage = "客户编号长度不超过128字符")] public string CustomerNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/CreateRoomInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/CreateRoomInputDto.cs index 12adeb5..5fa473a 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/CreateRoomInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/CreateRoomInputDto.cs @@ -3,6 +3,8 @@ namespace EOM.TSHotelManagement.Contract public class CreateRoomInputDto : BaseInputDto { public string RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } public int RoomTypeId { get; set; } public string CustomerNumber { get; set; } public DateTime? LastCheckInTime { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs index 508d6bd..47a131f 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs @@ -2,7 +2,10 @@ { public class ReadRoomInputDto : ListInputDto { + public int? Id { get; set; } public string? RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } public int? RoomTypeId { get; set; } public int? RoomStateId { get; set; } public string? RoomName { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs index 281357c..5e8c8ae 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs @@ -4,6 +4,9 @@ { public int? Id { get; set; } public string RoomNumber { get; set; } + public string RoomArea { get; set; } + public int? RoomFloor { get; set; } + public string RoomLocator { get; set; } public string RoomName { get; set; } public int RoomTypeId { get; set; } public string CustomerNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs index e5caef7..3bb5273 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs @@ -2,7 +2,10 @@ namespace EOM.TSHotelManagement.Contract { public class UpdateRoomInputDto : BaseInputDto { + public int? Id { get; set; } public string RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } public int RoomTypeId { get; set; } public string CustomerNumber { get; set; } public DateOnly? LastCheckInTime { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeInputDto.cs index 4e21263..4329350 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeInputDto.cs @@ -2,7 +2,10 @@ { public class ReadRoomTypeInputDto : ListInputDto { + public int? Id { get; set; } public string? RoomNumber { get; set; } + public string? RoomArea { get; set; } + public int? RoomFloor { get; set; } public int? RoomTypeId { get; set; } public string? RoomTypeName { get; set; } public decimal? RoomRent { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/TransferRoomDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/TransferRoomDto.cs index 4a4d3d5..52519aa 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/TransferRoomDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/TransferRoomDto.cs @@ -4,11 +4,19 @@ namespace EOM.TSHotelManagement.Contract { public class TransferRoomDto : BaseInputDto { - [Required(ErrorMessage = "源房间编号为必填字段"), MaxLength(128, ErrorMessage = "源房间编号长度不超过128字符")] + [Required(ErrorMessage = "源房间ID为必填字段")] + public int? OriginalRoomId { get; set; } + [MaxLength(128, ErrorMessage = "源房间编号长度不超过128字符")] public string OriginalRoomNumber { get; set; } + public string? OriginalRoomArea { get; set; } + public int? OriginalRoomFloor { get; set; } - [Required(ErrorMessage = "目标房间编号为必填字段"), MaxLength(128, ErrorMessage = "目标房间编号长度不超过128字符")] + [Required(ErrorMessage = "目标房间ID为必填字段")] + public int? TargetRoomId { get; set; } + [MaxLength(128, ErrorMessage = "目标房间编号长度不超过128字符")] public string TargetRoomNumber { get; set; } + public string? TargetRoomArea { get; set; } + public int? TargetRoomFloor { get; set; } [Required(ErrorMessage = "客户编号为必填字段"), MaxLength(128, ErrorMessage = "客户编号长度不超过128字符")] public string CustomerNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs index 5894dd3..e6cc288 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/AddCustomerSpendInputDto.cs @@ -4,22 +4,24 @@ namespace EOM.TSHotelManagement.Contract { public class AddCustomerSpendInputDto { - [Required(ErrorMessage = "消费编号为必填字段")] + [Required(ErrorMessage = "SpendNumber is required.")] public string SpendNumber { get; set; } - [Required(ErrorMessage = "房间编号为必填字段")] public string RoomNumber { get; set; } - [Required(ErrorMessage = "商品编号为必填字段")] + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + + [Required(ErrorMessage = "ProductNumber is required.")] public string ProductNumber { get; set; } - [Required(ErrorMessage = "商品名称为必填字段")] + [Required(ErrorMessage = "ProductName is required.")] public string ProductName { get; set; } - [Required(ErrorMessage = "数量为必填字段")] + [Required(ErrorMessage = "ConsumptionQuantity is required.")] public int ConsumptionQuantity { get; set; } - [Required(ErrorMessage = "价格为必填字段")] + [Required(ErrorMessage = "ProductPrice is required.")] public decimal ProductPrice { get; set; } public string SoftwareVersion { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/CreateSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/CreateSpendInputDto.cs index c9fd6f0..a1eb1d8 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/CreateSpendInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/CreateSpendInputDto.cs @@ -4,28 +4,31 @@ namespace EOM.TSHotelManagement.Contract { public class CreateSpendInputDto : BaseInputDto { - [Required(ErrorMessage = "商品编号为必填字段")] + [Required(ErrorMessage = "ProductNumber is required.")] public string ProductNumber { get; set; } - [Required(ErrorMessage = "消费编号为必填字段")] + [Required(ErrorMessage = "SpendNumber is required.")] public string SpendNumber { get; set; } + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + public string RoomNumber { get; set; } public string CustomerNumber { get; set; } public string ProductName { get; set; } - [Required(ErrorMessage = "消费数量为必填字段")] + [Required(ErrorMessage = "ConsumptionQuantity is required.")] public int ConsumptionQuantity { get; set; } - [Required(ErrorMessage = "商品单价为必填字段")] + [Required(ErrorMessage = "ProductPrice is required.")] public decimal ProductPrice { get; set; } - [Required(ErrorMessage = "消费金额为必填字段")] + [Required(ErrorMessage = "ConsumptionAmount is required.")] public decimal ConsumptionAmount { get; set; } - [Required(ErrorMessage = "消费时间为必填字段")] + [Required(ErrorMessage = "ConsumptionTime is required.")] public DateTime ConsumptionTime { get; set; } public string SettlementStatus { get; set; } @@ -33,4 +36,3 @@ namespace EOM.TSHotelManagement.Contract public string ConsumptionType { get; set; } } } - diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendInputDto.cs index 9a87c94..7467751 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendInputDto.cs @@ -6,6 +6,8 @@ namespace EOM.TSHotelManagement.Contract { public string? SpendNumber { get; set; } + public int? RoomId { get; set; } + public string? RoomNumber { get; set; } public string? CustomerNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendOutputDto.cs index 4c92a75..801a9f5 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/ReadSpendOutputDto.cs @@ -5,6 +5,7 @@ namespace EOM.TSHotelManagement.Contract public class ReadSpendOutputDto : BaseOutputDto { public int? Id { get; set; } + public int? RoomId { get; set; } [UIDisplay("消费编号", false, false)] public string SpendNumber { get; set; } @@ -12,6 +13,12 @@ namespace EOM.TSHotelManagement.Contract [UIDisplay("房间号")] public string RoomNumber { get; set; } + public string RoomArea { get; set; } + + public int? RoomFloor { get; set; } + + public string RoomLocator { get; set; } + [UIDisplay("客户编号")] public string CustomerNumber { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UpdateSpendInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UpdateSpendInputDto.cs index 60413f8..f75fd45 100644 --- a/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UpdateSpendInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Spend/Dto/Spend/UpdateSpendInputDto.cs @@ -4,9 +4,12 @@ namespace EOM.TSHotelManagement.Contract { public class UpdateSpendInputDto : BaseInputDto { - [Required(ErrorMessage = "消费编号为必填字段")] + [Required(ErrorMessage = "SpendNumber is required.")] public string SpendNumber { get; set; } + [Required(ErrorMessage = "RoomId is required.")] + public int? RoomId { get; set; } + public string RoomNumber { get; set; } public string OriginalRoomNumber { get; set; } @@ -15,16 +18,16 @@ namespace EOM.TSHotelManagement.Contract public string ProductName { get; set; } - [Required(ErrorMessage = "消费数量为必填字段")] + [Required(ErrorMessage = "ConsumptionQuantity is required.")] public int ConsumptionQuantity { get; set; } - [Required(ErrorMessage = "商品单价为必填字段")] + [Required(ErrorMessage = "ProductPrice is required.")] public decimal ProductPrice { get; set; } - [Required(ErrorMessage = "消费金额为必填字段")] + [Required(ErrorMessage = "ConsumptionAmount is required.")] public decimal ConsumptionAmount { get; set; } - [Required(ErrorMessage = "消费时间为必填字段")] + [Required(ErrorMessage = "ConsumptionTime is required.")] public DateTime ConsumptionTime { get; set; } public string SettlementStatus { get; set; } @@ -32,4 +35,3 @@ namespace EOM.TSHotelManagement.Contract public string ConsumptionType { get; set; } } } - diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index 5e931f8..483431e 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -102,6 +102,7 @@ namespace EOM.TSHotelManagement.Data .ToArray(); db.CodeFirst.InitTables(needCreateTableTypes); + EnsureRoomSchema(db); Console.WriteLine("Database schema initialized"); @@ -258,6 +259,98 @@ namespace EOM.TSHotelManagement.Data return configString; } + private void EnsureRoomSchema(ISqlSugarClient db) + { + EnsureColumn(db, "room", "room_area", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_area` varchar(128) NULL", + [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_area` varchar(128) NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_area\" varchar(128)", + [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_area] nvarchar(128) NULL", + [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_area TEXT NULL" + }); + + EnsureColumn(db, "room", "room_floor", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_floor` int NULL", + [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_floor` int NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_floor\" integer", + [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_floor] int NULL", + [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_floor INTEGER NULL" + }); + + EnsureColumn(db, "reser", "room_id", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `reser` ADD COLUMN `room_id` int NULL", + [DbType.MySqlConnector] = "ALTER TABLE `reser` ADD COLUMN `room_id` int NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"reser\" ADD COLUMN \"room_id\" integer", + [DbType.SqlServer] = "ALTER TABLE [reser] ADD [room_id] int NULL", + [DbType.Sqlite] = "ALTER TABLE reser ADD COLUMN room_id INTEGER NULL" + }); + + EnsureColumn(db, "customer_spend", "room_id", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `customer_spend` ADD COLUMN `room_id` int NULL", + [DbType.MySqlConnector] = "ALTER TABLE `customer_spend` ADD COLUMN `room_id` int NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"customer_spend\" ADD COLUMN \"room_id\" integer", + [DbType.SqlServer] = "ALTER TABLE [customer_spend] ADD [room_id] int NULL", + [DbType.Sqlite] = "ALTER TABLE customer_spend ADD COLUMN room_id INTEGER NULL" + }); + + EnsureColumn(db, "energy_management", "room_id", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `energy_management` ADD COLUMN `room_id` int NULL", + [DbType.MySqlConnector] = "ALTER TABLE `energy_management` ADD COLUMN `room_id` int NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"energy_management\" ADD COLUMN \"room_id\" integer", + [DbType.SqlServer] = "ALTER TABLE [energy_management] ADD [room_id] int NULL", + [DbType.Sqlite] = "ALTER TABLE energy_management ADD COLUMN room_id INTEGER NULL" + }); + } + + private void EnsureColumn(ISqlSugarClient db, string tableName, string columnName, IReadOnlyDictionary sqlMap) + { + if (ColumnExists(db, tableName, columnName)) + { + return; + } + + if (!sqlMap.TryGetValue(db.CurrentConnectionConfig.DbType, out var sql)) + { + Console.WriteLine($"Skip schema patch for unsupported DbType {db.CurrentConnectionConfig.DbType} on {tableName}.{columnName}"); + return; + } + + db.Ado.ExecuteCommand(sql); + } + + private bool ColumnExists(ISqlSugarClient db, string tableName, string columnName) + { + var dbType = db.CurrentConnectionConfig.DbType; + string sql = dbType switch + { + DbType.MySql or DbType.MySqlConnector => + "SELECT COUNT(1) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = @tableName AND column_name = @columnName", + DbType.PostgreSQL => + "SELECT COUNT(1) FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = @tableName AND column_name = @columnName", + DbType.SqlServer => + "SELECT COUNT(1) FROM information_schema.columns WHERE table_name = @tableName AND column_name = @columnName", + DbType.Sqlite => + $"SELECT COUNT(1) FROM pragma_table_info('{tableName}') WHERE name = @columnName", + _ => string.Empty + }; + + if (string.IsNullOrEmpty(sql)) + { + return true; + } + + return db.Ado.GetInt(sql, new List + { + new SugarParameter("@tableName", tableName), + new SugarParameter("@columnName", columnName) + }) > 0; + } + private void SeedInitialData(ISqlSugarClient db) { Console.WriteLine("Initializing database data..."); diff --git a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs index d12bc48..78062a0 100644 --- a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs +++ b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs @@ -51,6 +51,9 @@ namespace EOM.TSHotelManagement.Domain [SqlSugar.SugarColumn(ColumnName = "room_no", Length = 128, IsNullable = false, ColumnDescription = "房间编号 (Room Number)")] public string RoomNumber { get; set; } + [SqlSugar.SugarColumn(ColumnName = "room_id", IsNullable = true, ColumnDescription = "Room ID")] + public int? RoomId { get; set; } + /// /// 开始使用时间 (Start Date) /// diff --git a/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs b/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs index 8e27af8..93bbf61 100644 --- a/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs +++ b/EOM.TSHotelManagement.Domain/Business/Reser/Reser.cs @@ -96,6 +96,9 @@ namespace EOM.TSHotelManagement.Domain )] public string ReservationRoomNumber { get; set; } + [SugarColumn(ColumnName = "room_id", ColumnDescription = "Room ID", IsNullable = true)] + public int? RoomId { get; set; } + /// /// 预约起始日期 (Reservation Start Date) /// diff --git a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs index 7be37c6..6a91b14 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs @@ -1,177 +1,115 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - *模块说明:房间类 - */ - using SqlSugar; using System; namespace EOM.TSHotelManagement.Domain { - /// - /// 酒店房间信息表 (Hotel Room Information) - /// - [SugarTable("room", "酒店房间信息表 (Hotel Room Information)")] + [SugarTable("room", "Hotel room information")] public class Room : SoftDeleteEntity { - /// - /// 编号 (ID) - /// - [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "编号 (ID)")] + [SugarColumn(ColumnName = "id", IsIdentity = true, IsPrimaryKey = true, IsNullable = false, ColumnDescription = "ID")] public int Id { get; set; } - /// - /// 房间编号 (Room Number) - /// [SugarColumn( ColumnName = "room_no", IsPrimaryKey = true, - ColumnDescription = "房间唯一编号 (Unique Room Number)", + ColumnDescription = "Room number", IsNullable = false, Length = 128 )] - public string RoomNumber { get; set; } - /// - /// 房间类型ID (Room Type ID) - /// + [SugarColumn( + ColumnName = "room_area", + ColumnDescription = "Room area", + IsNullable = true, + Length = 128 + )] + public string RoomArea { get; set; } + + [SugarColumn( + ColumnName = "room_floor", + ColumnDescription = "Room floor", + IsNullable = true + )] + public int? RoomFloor { get; set; } + [SugarColumn( ColumnName = "room_type", - ColumnDescription = "房间类型ID (关联房间类型表)", + ColumnDescription = "Room type ID", IsNullable = false )] - public int RoomTypeId { get; set; } - /// - /// 客户编号 (Customer Number) - /// [SugarColumn( ColumnName = "custo_no", - ColumnDescription = "当前入住客户编号 (Linked Customer ID)", + ColumnDescription = "Linked customer number", IsNullable = true, Length = 128 )] public string CustomerNumber { get; set; } - /// - /// 客户姓名 (Customer Name)(不存储到数据库) - /// [SugarColumn(IsIgnore = true)] public string CustomerName { get; set; } - /// - /// 最后一次入住时间 (Last Check-In Time) - /// [SugarColumn( ColumnName = "check_in_time", - ColumnDescription = "最后一次入住时间 (Last Check-In Time)", + ColumnDescription = "Last check-in time", IsNullable = true )] public DateOnly? LastCheckInTime { get; set; } - /// - /// 最后一次退房时间 (Last Check-Out Time) - /// [SugarColumn( ColumnName = "check_out_time", - ColumnDescription = "最后一次退房时间 (Last Check-Out Time)", + ColumnDescription = "Last check-out time", IsNullable = true )] public DateOnly LastCheckOutTime { get; set; } - /// - /// 房间状态ID (Room State ID) - /// [SugarColumn( ColumnName = "room_state_id", - ColumnDescription = "房间状态ID (如0-空闲/1-已入住)", + ColumnDescription = "Room state ID", IsNullable = false )] - public int RoomStateId { get; set; } - /// - /// 房间状态名称 (Room State Name)(不存储到数据库) - /// [SugarColumn(IsIgnore = true)] public string RoomState { get; set; } - /// - /// 房间单价 (Room Rent) - /// [SugarColumn( ColumnName = "room_rent", - ColumnDescription = "房间单价(单位:元) (Price per Night in CNY)", + ColumnDescription = "Room rent", IsNullable = false, DecimalDigits = 2 )] - public decimal RoomRent { get; set; } - /// - /// 房间押金 (Room Deposit) - /// [SugarColumn( ColumnName = "room_deposit", - ColumnDescription = "房间押金(单位:元) (Deposit Amount in CNY)", + ColumnDescription = "Room deposit", IsNullable = false, DecimalDigits = 2, DefaultValue = "0.00" )] - public decimal RoomDeposit { get; set; } - /// - /// 房间位置 (Room Location) - /// [SugarColumn( ColumnName = "room_position", - ColumnDescription = "房间位置描述 (如楼层+门牌号)", + ColumnDescription = "Room location", IsNullable = false, Length = 200 )] - public string RoomLocation { get; set; } - /// - /// 客户类型名称 (Customer Type Name)(不存储到数据库) - /// [SugarColumn(IsIgnore = true)] public string CustomerTypeName { get; set; } - /// - /// 房间名称 (Room Name)(不存储到数据库) - /// [SugarColumn(IsIgnore = true)] public string RoomName { get; set; } - /// - /// 最后一次入住时间(格式化字符串) (Last Check-In Time Formatted) - /// + [SugarColumn(IsIgnore = true)] + public string RoomLocator { get; set; } + [SugarColumn(IsIgnore = true)] public string LastCheckInTimeFormatted { get; set; } } - } diff --git a/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs b/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs index c1ecda6..412fd44 100644 --- a/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs +++ b/EOM.TSHotelManagement.Domain/Business/Spend/Spend.cs @@ -46,6 +46,9 @@ namespace EOM.TSHotelManagement.Domain [SugarColumn(ColumnName = "room_no", ColumnDescription = "房间编号")] public string RoomNumber { get; set; } + [SugarColumn(ColumnName = "room_id", ColumnDescription = "Room ID", IsNullable = true)] + public int? RoomId { get; set; } + /// /// 客户编号 (Customer Number) /// diff --git a/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs b/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs index 09b7d43..72a8467 100644 --- a/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs +++ b/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs @@ -1,169 +1,161 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - */ using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; +using jvncorelib.EntityLib; using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; namespace EOM.TSHotelManagement.Service { - /// - /// 水电信息接口实现类 - /// public class EnergyManagementService : IEnergyManagementService { - /// - /// 水电信息 - /// private readonly GenericRepository wtiRepository; - private readonly ILogger _logger; + private readonly GenericRepository roomRepository; + private readonly ILogger logger; - public EnergyManagementService(GenericRepository wtiRepository, ILogger logger) + public EnergyManagementService( + GenericRepository wtiRepository, + GenericRepository roomRepository, + ILogger logger) { this.wtiRepository = wtiRepository; - _logger = logger; + this.roomRepository = roomRepository; + this.logger = logger; } - /// - /// 根据条件查询水电费信息 - /// - /// Dto - /// 符合条件的水电费信息列表 public ListOutputDto SelectEnergyManagementInfo(ReadEnergyManagementInputDto readEnergyManagementInputDto) { - var where = SqlFilterBuilder.BuildExpression(readEnergyManagementInputDto); + readEnergyManagementInputDto ??= new ReadEnergyManagementInputDto(); + var filterInput = CreateEnergyFilter(readEnergyManagementInputDto); - var count = 0; - var Data = new List(); + var where = SqlFilterBuilder.BuildExpression(filterInput); + var query = wtiRepository.AsQueryable().Where(a => a.IsDelete != 1); + var whereExpression = where.ToExpression(); + if (whereExpression != null) + { + query = query.Where(whereExpression); + } + + if (readEnergyManagementInputDto.RoomId.HasValue && readEnergyManagementInputDto.RoomId.Value > 0) + { + query = query.Where(a => a.RoomId == readEnergyManagementInputDto.RoomId.Value); + } + var count = 0; + List data; if (readEnergyManagementInputDto.IgnorePaging) { - Data = wtiRepository.AsQueryable() - .Where(where.ToExpression()).ToList(); - count = Data.Count; + data = query.ToList(); + count = data.Count; } else { - Data = wtiRepository.AsQueryable() - .Where(where.ToExpression()).ToPageList(readEnergyManagementInputDto.Page, readEnergyManagementInputDto.PageSize, ref count); + var page = readEnergyManagementInputDto.Page > 0 ? readEnergyManagementInputDto.Page : 1; + var pageSize = readEnergyManagementInputDto.PageSize > 0 ? readEnergyManagementInputDto.PageSize : 15; + data = query.ToPageList(page, pageSize, ref count); } - var readEnergies = EntityMapper.MapList(Data); + var rooms = RoomReferenceHelper.LoadRooms(roomRepository, data.Select(a => a.RoomId), data.Select(a => a.RoomNumber)); + var outputs = data.Select(a => MapEnergyToOutput(a, RoomReferenceHelper.FindRoom(rooms, a.RoomId, a.RoomNumber))).ToList(); return new ListOutputDto { Data = new PagedData { - Items = readEnergies, + Items = outputs, TotalCount = count } }; } - /// - /// 添加水电费信息 - /// - /// - /// - public BaseResponse InsertEnergyManagementInfo(CreateEnergyManagementInputDto w) + public BaseResponse InsertEnergyManagementInfo(CreateEnergyManagementInputDto input) { try { - if (wtiRepository.IsAny(a => a.InformationId == w.InformationNumber)) + if (wtiRepository.IsAny(a => a.InformationId == input.InformationNumber && a.IsDelete != 1)) { - return new BaseResponse() { Message = LocalizationHelper.GetLocalizedString("information number already exist.", "信息编号已存在"), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse(BusinessStatusCode.Conflict, "Information number already exists."); } - var result = wtiRepository.Insert(EntityMapper.Map(w)); + + var roomResult = RoomReferenceHelper.Resolve(roomRepository, input?.RoomId, input?.RoomNumber); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, input?.RoomId, input?.RoomNumber); + } + + var entity = EntityMapper.Map(input); + entity.InformationId = input.InformationNumber; + entity.RoomId = roomResult.Room.Id; + entity.RoomNumber = roomResult.Room.RoomNumber; + entity.StartDate = DateOnly.FromDateTime(input.StartDate); + entity.EndDate = DateOnly.FromDateTime(input.EndDate); + + wtiRepository.Insert(entity); + return new BaseResponse(BusinessStatusCode.Success, "Insert energy management success."); } catch (Exception ex) { - _logger.LogError(ex, LocalizationHelper.GetLocalizedString("Insert Energy Management Failed", "水电信息添加失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Insert Energy Management Failed", "水电信息添加失败")); + logger.LogError(ex, "Insert energy management failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Insert energy management failed."); } - - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Insert Energy Management Success", "水电信息添加成功")); } - /// - /// 修改水电费信息 - /// - /// 包含要修改的数据,以及EnergyManagementNo作为查询条件 - /// - public BaseResponse UpdateEnergyManagementInfo(UpdateEnergyManagementInputDto w) + public BaseResponse UpdateEnergyManagementInfo(UpdateEnergyManagementInputDto input) { try { - if (!wtiRepository.IsAny(a => a.InformationId == w.InformationId)) + var entity = wtiRepository.GetFirst(a => a.InformationId == input.InformationId && a.IsDelete != 1); + if (entity == null) { - return new BaseResponse() { Message = LocalizationHelper.GetLocalizedString("information number does not exist.", "信息编号不存在"), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse(BusinessStatusCode.NotFound, "Information number does not exist."); } - var result = wtiRepository.Update(EntityMapper.Map(w)); - if (result) + var roomResult = RoomReferenceHelper.Resolve(roomRepository, input?.RoomId, input?.RoomNumber); + if (roomResult.Room == null) { - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Update Energy Management Success", "水电费信息更新成功")); - } - else - { - return BaseResponseFactory.ConcurrencyConflict(); + return CreateRoomLookupFailure(roomResult, input?.RoomId, input?.RoomNumber); } + + entity.RoomId = roomResult.Room.Id; + entity.RoomNumber = roomResult.Room.RoomNumber; + entity.CustomerNumber = input.CustomerNumber; + entity.StartDate = DateOnly.FromDateTime(input.StartDate); + entity.EndDate = DateOnly.FromDateTime(input.EndDate); + entity.PowerUsage = input.PowerUsage; + entity.WaterUsage = input.WaterUsage; + entity.Recorder = input.Recorder; + entity.DataChgUsr = input.DataChgUsr; + entity.DataChgDate = input.DataChgDate; + entity.RowVersion = input.RowVersion ?? 0; + + return wtiRepository.Update(entity) + ? new BaseResponse(BusinessStatusCode.Success, "Update energy management success.") + : BaseResponseFactory.ConcurrencyConflict(); } catch (Exception ex) { - _logger.LogError(ex, LocalizationHelper.GetLocalizedString("Update Energy Management Failed", "水电费信息更新失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Update Energy Management Failed", "水电费信息更新失败")); + logger.LogError(ex, "Update energy management failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Update energy management failed."); } } - /// - /// 根据房间编号、使用时间删除水电费信息 - /// - /// public BaseResponse DeleteEnergyManagementInfo(DeleteEnergyManagementInputDto hydroelectricity) { try { if (hydroelectricity?.DelIds == null || !hydroelectricity.DelIds.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.BadRequest, - Message = LocalizationHelper.GetLocalizedString("Parameters Invalid", "参数错误") - }; + return new BaseResponse(BusinessStatusCode.BadRequest, "Parameters invalid."); } var delIds = DeleteConcurrencyHelper.GetDeleteIds(hydroelectricity); var energyManagements = wtiRepository.GetList(a => delIds.Contains(a.Id)); - if (!energyManagements.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.NotFound, - Message = LocalizationHelper.GetLocalizedString("Energy Management Information Not Found", "水电费信息未找到") - }; + return new BaseResponse(BusinessStatusCode.NotFound, "Energy management information not found."); } if (DeleteConcurrencyHelper.HasDeleteConflict(hydroelectricity, energyManagements, a => a.Id, a => a.RowVersion)) @@ -171,22 +163,71 @@ namespace EOM.TSHotelManagement.Service return BaseResponseFactory.ConcurrencyConflict(); } - var result = wtiRepository.SoftDeleteRange(energyManagements); - - if (result) - { - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Delete Energy Management Success", "水电费信息删除成功")); - } - else - { - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Delete Energy Management Failed", "水电费信息删除失败")); - } + return wtiRepository.SoftDeleteRange(energyManagements) + ? new BaseResponse(BusinessStatusCode.Success, "Delete energy management success.") + : new BaseResponse(BusinessStatusCode.InternalServerError, "Delete energy management failed."); } catch (Exception ex) { - _logger.LogError(ex, LocalizationHelper.GetLocalizedString("Delete Energy Management Failed", "水电费信息删除失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Delete Energy Management Failed", "水电费信息删除失败")); + logger.LogError(ex, "Delete energy management failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Delete energy management failed."); } } + + private static ReadEnergyManagementOutputDto MapEnergyToOutput(EnergyManagement source, Room room) + { + return new ReadEnergyManagementOutputDto + { + Id = source.Id, + InformationId = source.InformationId, + RoomId = source.RoomId ?? room?.Id, + RoomNumber = room?.RoomNumber ?? source.RoomNumber, + RoomArea = RoomReferenceHelper.GetRoomArea(room), + RoomFloor = RoomReferenceHelper.GetRoomFloor(room), + RoomLocator = RoomReferenceHelper.GetRoomLocator(room), + CustomerNumber = source.CustomerNumber, + StartDate = source.StartDate.ToDateTime(TimeOnly.MinValue), + EndDate = source.EndDate.ToDateTime(TimeOnly.MinValue), + PowerUsage = source.PowerUsage, + WaterUsage = source.WaterUsage, + Recorder = source.Recorder, + DataInsUsr = source.DataInsUsr, + DataInsDate = source.DataInsDate, + DataChgUsr = source.DataChgUsr, + DataChgDate = source.DataChgDate, + RowVersion = source.RowVersion, + IsDelete = source.IsDelete + }; + } + + private static BaseResponse CreateRoomLookupFailure(RoomResolveResult result, int? roomId, string roomNumber) + { + if (!roomId.HasValue || roomId.Value <= 0) + { + return new BaseResponse(BusinessStatusCode.BadRequest, "RoomId is required."); + } + + if (result?.IsAmbiguous == true) + { + return new BaseResponse(BusinessStatusCode.Conflict, $"Multiple rooms match room id '{roomId.Value}'."); + } + + return new BaseResponse(BusinessStatusCode.NotFound, $"RoomId '{roomId.Value}' was not found."); + } + + private static ReadEnergyManagementInputDto CreateEnergyFilter(ReadEnergyManagementInputDto input) + { + return new ReadEnergyManagementInputDto + { + Page = input.Page, + PageSize = input.PageSize, + IgnorePaging = input.IgnorePaging, + CustomerNumber = input.CustomerNumber, + RoomId = null, + RoomNumber = null, + StartDate = input.StartDate, + EndDate = input.EndDate + }; + } } } diff --git a/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs b/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs index 23f86b8..6b2b8e9 100644 --- a/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs +++ b/EOM.TSHotelManagement.Service/Business/Reser/ReserService.cs @@ -1,59 +1,27 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - */ using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; using Microsoft.Extensions.Logging; -using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; using System.Transactions; namespace EOM.TSHotelManagement.Service { - /// - /// 预约信息接口实现类 - /// public class ReserService : IReserService { - /// - /// 预约信息 - /// private readonly GenericRepository reserRepository; - - /// - /// 房间信息 - /// private readonly GenericRepository roomRepository; - - /// - /// 数据保护 - /// private readonly DataProtectionHelper dataProtector; - private readonly ILogger logger; - public ReserService(GenericRepository reserRepository, GenericRepository roomRepository, DataProtectionHelper dataProtector, ILogger logger) + public ReserService( + GenericRepository reserRepository, + GenericRepository roomRepository, + DataProtectionHelper dataProtector, + ILogger logger) { this.reserRepository = reserRepository; this.roomRepository = roomRepository; @@ -61,24 +29,22 @@ namespace EOM.TSHotelManagement.Service this.logger = logger; } - /// - /// 获取所有预约信息 - /// - /// public ListOutputDto SelectReserAll(ReadReserInputDto readReserInputDto) { readReserInputDto ??= new ReadReserInputDto(); + var filterInput = CreateReservationFilter(readReserInputDto); var helper = new EnumHelper(); var reserTypeMap = Enum.GetValues(typeof(ReserType)) .Cast() - .ToDictionary(e => e.ToString(), e => helper.GetEnumDescription(e) ?? "", StringComparer.OrdinalIgnoreCase); + .ToDictionary(a => a.ToString(), a => helper.GetEnumDescription(a) ?? string.Empty, StringComparer.OrdinalIgnoreCase); - var where = SqlFilterBuilder.BuildExpression(readReserInputDto, new Dictionary + var where = SqlFilterBuilder.BuildExpression(filterInput, new Dictionary { { nameof(ReadReserInputDto.ReservationStartDateStart), nameof(Reser.ReservationStartDate) }, - { nameof(ReadReserInputDto.ReservationStartDateEnd), nameof(Reser.ReservationEndDate) }, + { nameof(ReadReserInputDto.ReservationStartDateEnd), nameof(Reser.ReservationEndDate) } }); + var query = reserRepository.AsQueryable().Where(a => a.IsDelete != 1); var whereExpression = where.ToExpression(); if (whereExpression != null) @@ -86,337 +52,271 @@ namespace EOM.TSHotelManagement.Service query = query.Where(whereExpression); } - var count = 0; - List data; - if (!readReserInputDto.IgnorePaging) + if (readReserInputDto.RoomId.HasValue && readReserInputDto.RoomId.Value > 0) { - var page = readReserInputDto.Page > 0 ? readReserInputDto.Page : 1; - var pageSize = readReserInputDto.PageSize > 0 ? readReserInputDto.PageSize : 15; - data = query.ToPageList(page, pageSize, ref count); - } - else - { - data = query.ToList(); - count = data.Count; + query = query.Where(a => a.RoomId == readReserInputDto.RoomId.Value); } - List mapped; - var useParallelProjection = readReserInputDto.IgnorePaging && data.Count >= 200; - if (useParallelProjection) + var count = 0; + List reservations; + if (readReserInputDto.IgnorePaging) { - var dtoArray = new ReadReserOutputDto[data.Count]; - System.Threading.Tasks.Parallel.For(0, data.Count, i => - { - var source = data[i]; - dtoArray[i] = new ReadReserOutputDto - { - Id = source.Id, - ReservationId = source.ReservationId, - CustomerName = source.CustomerName, - ReservationPhoneNumber = dataProtector.SafeDecryptReserData(source.ReservationPhoneNumber), - ReservationRoomNumber = source.ReservationRoomNumber, - ReservationChannel = source.ReservationChannel, - ReservationChannelDescription = reserTypeMap.TryGetValue(source.ReservationChannel ?? "", out var channelDescription) ? channelDescription : "", - ReservationStartDate = source.ReservationStartDate.ToDateTime(TimeOnly.MinValue), - ReservationEndDate = source.ReservationEndDate.ToDateTime(TimeOnly.MinValue), - DataInsUsr = source.DataInsUsr, - DataInsDate = source.DataInsDate, - DataChgUsr = source.DataChgUsr, - DataChgDate = source.DataChgDate, - RowVersion = source.RowVersion, - IsDelete = source.IsDelete - }; - }); - mapped = dtoArray.ToList(); + reservations = query.ToList(); + count = reservations.Count; } else { - mapped = new List(data.Count); - data.ForEach(source => - { - mapped.Add(new ReadReserOutputDto - { - Id = source.Id, - ReservationId = source.ReservationId, - CustomerName = source.CustomerName, - ReservationPhoneNumber = dataProtector.SafeDecryptReserData(source.ReservationPhoneNumber), - ReservationRoomNumber = source.ReservationRoomNumber, - ReservationChannel = source.ReservationChannel, - ReservationChannelDescription = reserTypeMap.TryGetValue(source.ReservationChannel ?? "", out var channelDescription) ? channelDescription : "", - ReservationStartDate = source.ReservationStartDate.ToDateTime(TimeOnly.MinValue), - ReservationEndDate = source.ReservationEndDate.ToDateTime(TimeOnly.MinValue), - DataInsUsr = source.DataInsUsr, - DataInsDate = source.DataInsDate, - DataChgUsr = source.DataChgUsr, - DataChgDate = source.DataChgDate, - RowVersion = source.RowVersion, - IsDelete = source.IsDelete - }); - }); + var page = readReserInputDto.Page > 0 ? readReserInputDto.Page : 1; + var pageSize = readReserInputDto.PageSize > 0 ? readReserInputDto.PageSize : 15; + reservations = query.ToPageList(page, pageSize, ref count); } + var rooms = RoomReferenceHelper.LoadRooms(roomRepository, reservations.Select(a => a.RoomId), reservations.Select(a => a.ReservationRoomNumber)); + var outputs = reservations + .Select(a => MapReservationToOutput(a, RoomReferenceHelper.FindRoom(rooms, a.RoomId, a.ReservationRoomNumber), reserTypeMap)) + .ToList(); + return new ListOutputDto { Data = new PagedData { - Items = mapped, + Items = outputs, TotalCount = count } }; } - /// - /// 根据房间编号获取预约信息 - /// - /// - /// public SingleOutputDto SelectReserInfoByRoomNo(ReadReserInputDto readReserInputDt) { var helper = new EnumHelper(); - var reserType = Enum.GetValues(typeof(ReserType)) + var reserTypeMap = Enum.GetValues(typeof(ReserType)) .Cast() - .Select(e => new EnumDto - { - Id = (int)e, - Name = e.ToString(), - Description = helper.GetEnumDescription(e) - }) - .ToList(); + .ToDictionary(a => a.ToString(), a => helper.GetEnumDescription(a) ?? string.Empty, StringComparer.OrdinalIgnoreCase); - Reser res = null; - res = reserRepository.GetFirst(a => a.ReservationRoomNumber == readReserInputDt.ReservationRoomNumber && a.ReservationStatus == 0 && a.IsDelete != 1); - //解密联系方式 - var sourceTelStr = dataProtector.SafeDecryptReserData(res.ReservationPhoneNumber); - res.ReservationPhoneNumber = sourceTelStr; - - var outputReser = EntityMapper.Map(res); + var query = reserRepository.AsQueryable().Where(a => a.ReservationStatus == 0 && a.IsDelete != 1); + if (readReserInputDt?.RoomId > 0) + { + query = query.Where(a => a.RoomId == readReserInputDt.RoomId); + } + else + { + return new SingleOutputDto + { + Code = BusinessStatusCode.BadRequest, + Message = "RoomId is required.", + Data = new ReadReserOutputDto() + }; + } - outputReser.ReservationChannelDescription = reserType.Where(a => a.Name == outputReser.ReservationChannel).Single().Description; + var reservation = query.First(); + if (reservation == null) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.NotFound, + Message = "Reservation not found.", + Data = new ReadReserOutputDto() + }; + } - return new SingleOutputDto { Data = outputReser }; + var room = RoomReferenceHelper.Resolve(roomRepository, reservation.RoomId, reservation.ReservationRoomNumber).Room; + return new SingleOutputDto + { + Data = MapReservationToOutput(reservation, room, reserTypeMap) + }; } - /// - /// 删除预约信息 - /// - /// - /// public BaseResponse DeleteReserInfo(DeleteReserInputDto reser) { - if (reser?.DelIds == null || !reser.DelIds.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.BadRequest, - Message = LocalizationHelper.GetLocalizedString("Parameters Invalid", "参数错误") - }; + return new BaseResponse(BusinessStatusCode.BadRequest, "Parameters invalid."); } var delIds = DeleteConcurrencyHelper.GetDeleteIds(reser); - var resers = reserRepository.GetList(a => delIds.Contains(a.Id)); - - if (!resers.Any()) + var reservations = reserRepository.GetList(a => delIds.Contains(a.Id)); + if (!reservations.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.NotFound, - Message = LocalizationHelper.GetLocalizedString("Reservation Information Not Found", "预约信息未找到") - }; + return new BaseResponse(BusinessStatusCode.NotFound, "Reservation information not found."); } - if (DeleteConcurrencyHelper.HasDeleteConflict(reser, resers, a => a.Id, a => a.RowVersion)) + if (DeleteConcurrencyHelper.HasDeleteConflict(reser, reservations, a => a.Id, a => a.RowVersion)) { return BaseResponseFactory.ConcurrencyConflict(); } try { - using (TransactionScope scope = new TransactionScope()) + using var scope = new TransactionScope(); + if (!reserRepository.SoftDeleteRange(reservations)) { - var roomNumbers = resers.Select(a => a.ReservationRoomNumber).ToList(); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Delete reservation failed."); + } - var result = reserRepository.SoftDeleteRange(resers); + var rooms = RoomReferenceHelper.LoadRooms(roomRepository, reservations.Select(a => a.RoomId), reservations.Select(a => a.ReservationRoomNumber)); + if (rooms.Count > 0) + { + var remainingReservations = reserRepository.AsQueryable() + .Where(a => a.IsDelete != 1 && a.ReservationStatus == 0) + .ToList(); - if (result) + var changedRooms = new List(); + foreach (var room in rooms) { - var rooms = roomRepository.AsQueryable().Where(a => roomNumbers.Contains(a.RoomNumber)).ToList(); - rooms = rooms.Select(a => + var hasOtherActiveReservation = remainingReservations.Any(a => IsSameRoom(a, room)); + if (!hasOtherActiveReservation) { - a.RoomStateId = (int)RoomState.Vacant; - return a; - }).ToList(); - - var roomUpdateResult = roomRepository.UpdateRange(rooms); - if (!roomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); + room.RoomStateId = (int)RoomState.Vacant; + changedRooms.Add(room); } - - scope.Complete(); - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Delete Reser Success", "预约信息删除成功")); } - else + + if (changedRooms.Count > 0 && !roomRepository.UpdateRange(changedRooms)) { - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Delete Reser Failed", "预约信息删除失败")); + return BaseResponseFactory.ConcurrencyConflict(); } } + + scope.Complete(); + return new BaseResponse(BusinessStatusCode.Success, "Delete reservation success."); } catch (Exception ex) { - logger.LogError(ex, LocalizationHelper.GetLocalizedString("Delete Reser Failed", "预约信息删除失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Delete Reser Failed", "预约信息删除失败")); + logger.LogError(ex, "Delete reservation failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Delete reservation failed."); } } - /// - /// 更新预约信息(支持恢复功能) - /// - /// - /// public BaseResponse UpdateReserInfo(UpdateReserInputDto reser) { - string NewTel = dataProtector.EncryptReserData(reser.ReservationPhoneNumber); - reser.ReservationPhoneNumber = NewTel; - try { - using (TransactionScope scope = new TransactionScope()) - { - // 获取原预约(包括软删除的记录) - var originalReser = reserRepository.GetFirst(a => a.Id == reser.Id); - - if (originalReser == null) - { - return new BaseResponse(BusinessStatusCode.NotFound, - LocalizationHelper.GetLocalizedString("Reservation not found", "预约信息不存在")); - } + using var scope = new TransactionScope(); - bool isRestoring = originalReser.IsDelete == 1 && reser.IsDelete == 0; + var originalReser = reserRepository.GetFirst(a => a.Id == reser.Id); + if (originalReser == null) + { + return new BaseResponse(BusinessStatusCode.NotFound, "Reservation not found."); + } - // 如果是恢复操作 - if (isRestoring) - { - // 检查原房间的当前状态 - var room = roomRepository.GetFirst(a => a.RoomNumber == originalReser.ReservationRoomNumber); + var targetRoomResult = RoomReferenceHelper.Resolve(roomRepository, reser.RoomId ?? originalReser.RoomId, reser.ReservationRoomNumber ?? originalReser.ReservationRoomNumber); + if (targetRoomResult.Room == null) + { + return CreateRoomLookupFailure(targetRoomResult, reser.RoomId ?? originalReser.RoomId, reser.ReservationRoomNumber ?? originalReser.ReservationRoomNumber); + } - if (room == null) - { - return new BaseResponse(BusinessStatusCode.Conflict, - LocalizationHelper.GetLocalizedString("Room does not exist, cannot restore reservation", - "关联的房间不存在,无法恢复预约")); - } + var targetRoom = targetRoomResult.Room; + var startDate = DateOnly.FromDateTime(reser.ReservationStartDate); + var endDate = DateOnly.FromDateTime(reser.ReservationEndDate); - // 检查房间是否可用 - if (room.RoomStateId != (int)RoomState.Vacant) - { - return new BaseResponse(BusinessStatusCode.Conflict, - string.Format(LocalizationHelper.GetLocalizedString( - "Room {0} is currently occupied, cannot restore reservation", - "房间{0}当前已被占用,无法恢复预约"), - room.RoomNumber)); - } + var isRestoring = originalReser.IsDelete == 1 && reser.IsDelete == 0; + if (isRestoring && targetRoom.RoomStateId != (int)RoomState.Vacant) + { + return new BaseResponse(BusinessStatusCode.Conflict, "Room is not vacant."); + } - // 检查时间段冲突(如果有时间字段) - var conflictingReservation = reserRepository.GetFirst(r => - r.Id != originalReser.Id && - r.IsDelete == 0 && - r.ReservationRoomNumber == originalReser.ReservationRoomNumber && - r.ReservationStartDate < originalReser.ReservationEndDate && - r.ReservationEndDate > originalReser.ReservationStartDate); + var hasConflict = reserRepository.AsQueryable().Any(a => + a.Id != originalReser.Id && + a.IsDelete != 1 && + a.ReservationStatus == 0 && + a.RoomId == targetRoom.Id && + a.ReservationStartDate < endDate && + a.ReservationEndDate > startDate); - if (conflictingReservation != null) - { - return new BaseResponse(BusinessStatusCode.Conflict, - LocalizationHelper.GetLocalizedString( - "Room is already reserved during this period, cannot restore reservation", - "该时间段内房间已被预订,无法恢复预约")); - } + if (hasConflict) + { + return new BaseResponse(BusinessStatusCode.Conflict, "Room is already reserved during this period."); + } - // 恢复预约并更新房间状态 - var entity = EntityMapper.Map(reser); - var reserUpdateResult = reserRepository.Update(entity); - if (!reserUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + originalReser.ReservationId = reser.ReservationId; + originalReser.CustomerName = reser.CustomerName; + originalReser.ReservationPhoneNumber = dataProtector.EncryptReserData(reser.ReservationPhoneNumber); + originalReser.RoomId = targetRoom.Id; + originalReser.ReservationRoomNumber = targetRoom.RoomNumber; + originalReser.ReservationChannel = reser.ReservationChannel; + originalReser.ReservationStartDate = startDate; + originalReser.ReservationEndDate = endDate; + originalReser.IsDelete = reser.IsDelete; + originalReser.DataChgUsr = reser.DataChgUsr; + originalReser.DataChgDate = reser.DataChgDate; + originalReser.RowVersion = reser.RowVersion ?? 0; + + if (!reserRepository.Update(originalReser)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } - room.RoomStateId = (int)RoomState.Reserved; - var roomUpdateResult = roomRepository.Update(room); - if (!roomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } - } - else + if (originalReser.IsDelete != 1 && originalReser.ReservationStatus == 0) + { + targetRoom.RoomStateId = (int)RoomState.Reserved; + if (!roomRepository.Update(targetRoom)) { - // 普通更新逻辑 - var entity = EntityMapper.Map(reser); - var reserUpdateResult = reserRepository.Update(entity); - if (!reserUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + return BaseResponseFactory.ConcurrencyConflict(); } - - scope.Complete(); - return new BaseResponse(BusinessStatusCode.Success, - LocalizationHelper.GetLocalizedString("Update Reservation Success", "预约信息更新成功")); } + + scope.Complete(); + return new BaseResponse(BusinessStatusCode.Success, "Update reservation success."); } catch (Exception ex) { - logger.LogError(ex, LocalizationHelper.GetLocalizedString("Update Customer Failed", "预约信息更新失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, - LocalizationHelper.GetLocalizedString("Update Customer Failed", "预约信息更新失败")); + logger.LogError(ex, "Update reservation failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Update reservation failed."); } } - /// - /// 添加预约信息 - /// - /// - /// - public BaseResponse InserReserInfo(CreateReserInputDto r) + public BaseResponse InserReserInfo(CreateReserInputDto input) { - string NewTel = dataProtector.EncryptReserData(r.ReservationPhoneNumber); - r.ReservationPhoneNumber = NewTel; try { - var entity = EntityMapper.Map(r); - reserRepository.Insert(entity); + var roomResult = RoomReferenceHelper.Resolve(roomRepository, input?.RoomId, input?.ReservationRoomNumber); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, input?.RoomId, input?.ReservationRoomNumber); + } - var room = roomRepository.GetFirst(a => a.RoomNumber == r.ReservationRoomNumber); - room.RoomStateId = new EnumHelper().GetEnumValue(RoomState.Reserved); - var updateResult = roomRepository.Update(room); + var entity = new Reser + { + ReservationId = input.ReservationId, + CustomerName = input.CustomerName, + ReservationPhoneNumber = dataProtector.EncryptReserData(input.ReservationPhoneNumber), + RoomId = roomResult.Room.Id, + ReservationRoomNumber = roomResult.Room.RoomNumber, + ReservationChannel = input.ReservationChannel, + ReservationStartDate = DateOnly.FromDateTime(input.ReservationStartDate), + ReservationEndDate = DateOnly.FromDateTime(input.ReservationEndDate), + ReservationStatus = input.ReservationStatus, + DataInsUsr = input.DataInsUsr, + DataInsDate = input.DataInsDate + }; + + reserRepository.Insert(entity); - if (!updateResult) + roomResult.Room.RoomStateId = new EnumHelper().GetEnumValue(RoomState.Reserved); + if (!roomRepository.Update(roomResult.Room)) { - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Add Customer Failed", "预约信息添加失败")); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Insert reservation failed."); } - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Add Customer Success", "预约信息添加成功")); + + return new BaseResponse(BusinessStatusCode.Success, "Insert reservation success."); } catch (Exception ex) { - logger.LogError(ex, LocalizationHelper.GetLocalizedString("Add Customer Failed", "预约信息添加失败")); - return new BaseResponse(BusinessStatusCode.InternalServerError, LocalizationHelper.GetLocalizedString("Add Customer Failed", "预约信息添加失败")); + logger.LogError(ex, "Insert reservation failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, "Insert reservation failed."); } } - /// - /// 查询所有预约类型 - /// - /// public ListOutputDto SelectReserTypeAll() { var helper = new EnumHelper(); var enumList = Enum.GetValues(typeof(ReserType)) .Cast() - .Select(e => new EnumDto + .Select(a => new EnumDto { - Id = (int)e, - Name = e.ToString(), - Description = helper.GetEnumDescription(e) + Id = (int)a, + Name = a.ToString(), + Description = helper.GetEnumDescription(a) }) .ToList(); @@ -430,5 +330,73 @@ namespace EOM.TSHotelManagement.Service }; } + private ReadReserOutputDto MapReservationToOutput(Reser source, Room room, Dictionary reserTypeMap) + { + return new ReadReserOutputDto + { + Id = source.Id, + RoomId = source.RoomId ?? room?.Id, + ReservationId = source.ReservationId, + CustomerName = source.CustomerName, + ReservationPhoneNumber = dataProtector.SafeDecryptReserData(source.ReservationPhoneNumber), + ReservationRoomNumber = room?.RoomNumber ?? source.ReservationRoomNumber, + RoomArea = RoomReferenceHelper.GetRoomArea(room), + RoomFloor = RoomReferenceHelper.GetRoomFloor(room), + RoomLocator = RoomReferenceHelper.GetRoomLocator(room), + ReservationChannel = source.ReservationChannel, + ReservationChannelDescription = reserTypeMap.TryGetValue(source.ReservationChannel ?? string.Empty, out var channelDescription) ? channelDescription : string.Empty, + ReservationStartDate = source.ReservationStartDate.ToDateTime(TimeOnly.MinValue), + ReservationEndDate = source.ReservationEndDate.ToDateTime(TimeOnly.MinValue), + DataInsUsr = source.DataInsUsr, + DataInsDate = source.DataInsDate, + DataChgUsr = source.DataChgUsr, + DataChgDate = source.DataChgDate, + RowVersion = source.RowVersion, + IsDelete = source.IsDelete + }; + } + + private static bool IsSameRoom(Reser reservation, Room room) + { + if (reservation == null || room == null || !reservation.RoomId.HasValue || reservation.RoomId.Value <= 0) + { + return false; + } + + return reservation.RoomId.Value == room.Id; + } + + private static BaseResponse CreateRoomLookupFailure(RoomResolveResult result, int? roomId, string roomNumber) + { + if (!roomId.HasValue || roomId.Value <= 0) + { + return new BaseResponse(BusinessStatusCode.BadRequest, "RoomId is required."); + } + + if (result?.IsAmbiguous == true) + { + return new BaseResponse(BusinessStatusCode.Conflict, $"Multiple rooms match room id '{roomId.Value}'."); + } + + return new BaseResponse(BusinessStatusCode.NotFound, $"RoomId '{roomId.Value}' was not found."); + } + + private static ReadReserInputDto CreateReservationFilter(ReadReserInputDto input) + { + return new ReadReserInputDto + { + Page = input.Page, + PageSize = input.PageSize, + IgnorePaging = input.IgnorePaging, + RoomId = null, + ReservationId = input.ReservationId, + CustomerName = input.CustomerName, + ReservationPhoneNumber = input.ReservationPhoneNumber, + ReservationRoomNumber = null, + ReservationChannel = input.ReservationChannel, + ReservationStartDateStart = input.ReservationStartDateStart, + ReservationStartDateEnd = input.ReservationStartDateEnd + }; + } } } diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomLocatorHelper.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomLocatorHelper.cs new file mode 100644 index 0000000..68679c3 --- /dev/null +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomLocatorHelper.cs @@ -0,0 +1,101 @@ +using EOM.TSHotelManagement.Data; +using EOM.TSHotelManagement.Domain; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace EOM.TSHotelManagement.Service +{ + internal sealed class RoomResolveResult + { + public Room Room { get; init; } + + public bool IsAmbiguous { get; init; } + } + + internal static class RoomLocatorHelper + { + public static RoomResolveResult Resolve( + GenericRepository repository, + int? roomId, + string roomNumber, + string roomArea, + int? roomFloor, + bool includeDeleted = false) + { + if (roomId.HasValue && roomId.Value > 0) + { + var room = includeDeleted + ? repository.GetFirst(a => a.Id == roomId.Value) + : repository.GetFirst(a => a.Id == roomId.Value && a.IsDelete != 1); + + return new RoomResolveResult { Room = room, IsAmbiguous = false }; + } + + if (string.IsNullOrWhiteSpace(roomNumber)) + { + return new RoomResolveResult(); + } + + var normalizedNumber = roomNumber.Trim(); + var normalizedArea = NormalizeArea(roomArea); + var candidates = includeDeleted + ? repository.GetList(a => a.RoomNumber == normalizedNumber) + : repository.GetList(a => a.RoomNumber == normalizedNumber && a.IsDelete != 1); + + if (!candidates.Any()) + { + return new RoomResolveResult(); + } + + var hasArea = !string.IsNullOrWhiteSpace(normalizedArea); + var hasFloor = roomFloor.HasValue; + if (!hasArea && !hasFloor) + { + return candidates.Count == 1 + ? new RoomResolveResult { Room = candidates[0], IsAmbiguous = false } + : new RoomResolveResult { IsAmbiguous = true }; + } + + var exactMatches = candidates + .Where(a => (!hasArea || string.Equals(NormalizeArea(a.RoomArea), normalizedArea, StringComparison.OrdinalIgnoreCase)) + && (!hasFloor || a.RoomFloor == roomFloor)) + .Take(2) + .ToList(); + + if (exactMatches.Count == 1) + { + return new RoomResolveResult { Room = exactMatches[0], IsAmbiguous = false }; + } + + return new RoomResolveResult { IsAmbiguous = exactMatches.Count > 1 }; + } + + public static string NormalizeArea(string area) + { + return string.IsNullOrWhiteSpace(area) ? string.Empty : area.Trim(); + } + + public static string BuildLocator(string roomArea, int? roomFloor, string roomNumber) + { + var parts = new List(); + + if (!string.IsNullOrWhiteSpace(roomArea)) + { + parts.Add(roomArea.Trim()); + } + + if (roomFloor.HasValue) + { + parts.Add($"{roomFloor.Value}F"); + } + + if (!string.IsNullOrWhiteSpace(roomNumber)) + { + parts.Add(roomNumber.Trim()); + } + + return string.Join(" / ", parts); + } + } +} diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomReferenceHelper.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomReferenceHelper.cs new file mode 100644 index 0000000..0bd758e --- /dev/null +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomReferenceHelper.cs @@ -0,0 +1,64 @@ +using EOM.TSHotelManagement.Data; +using EOM.TSHotelManagement.Domain; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace EOM.TSHotelManagement.Service +{ + internal static class RoomReferenceHelper + { + public static RoomResolveResult Resolve(GenericRepository repository, int? roomId, string roomNumber, bool includeDeleted = false) + { + return RoomLocatorHelper.Resolve(repository, roomId, null, null, null, includeDeleted); + } + + public static List LoadRooms(GenericRepository repository, IEnumerable roomIds, IEnumerable roomNumbers) + { + var ids = roomIds? + .Where(a => a.HasValue && a.Value > 0) + .Select(a => a.Value) + .Distinct() + .ToList() ?? new List(); + + if (ids.Count == 0) + { + return new List(); + } + + return repository.AsQueryable() + .Where(a => a.IsDelete != 1 && ids.Contains(a.Id)) + .ToList(); + } + + public static Room FindRoom(IEnumerable rooms, int? roomId, string roomNumber) + { + if (!roomId.HasValue || roomId.Value <= 0) + { + return null; + } + + return rooms.FirstOrDefault(a => a.Id == roomId.Value); + } + + public static string GetRoomArea(Room room) + { + return room?.RoomArea ?? string.Empty; + } + + public static int? GetRoomFloor(Room room) + { + return room?.RoomFloor; + } + + public static string GetRoomLocator(Room room, string fallbackRoomNumber = null) + { + if (room != null) + { + return RoomLocatorHelper.BuildLocator(room.RoomArea, room.RoomFloor, room.RoomNumber); + } + + return string.Empty; + } + } +} diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index 9fff45f..87dcdd6 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -1,26 +1,3 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - */ using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; @@ -29,63 +6,37 @@ using jvncorelib.CodeLib; using jvncorelib.EntityLib; using Microsoft.Extensions.Logging; using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; using System.Transactions; namespace EOM.TSHotelManagement.Service { - /// - /// 客房信息接口实现类 - /// public class RoomService : IRoomService { - /// - /// 客房信息 - /// private readonly GenericRepository roomRepository; - - /// - /// 消费记录 - /// private readonly GenericRepository spendRepository; - - /// - /// 客房类型 - /// private readonly GenericRepository roomTypeRepository; - - /// - /// 能耗管理 - /// private readonly GenericRepository energyRepository; - - /// - /// 客户信息 - /// private readonly GenericRepository custoRepository; - - /// - /// 客户类型 - /// private readonly GenericRepository custoTypeRepository; - - /// - /// 会员等级规则 - /// private readonly GenericRepository vipLevelRuleRepository; - - /// - /// 预约信息 - /// private readonly GenericRepository reserRepository; - - /// - /// 唯一编码 - /// private readonly UniqueCode uniqueCode; - private readonly ILogger logger; - public RoomService(GenericRepository roomRepository, GenericRepository spendRepository, GenericRepository roomTypeRepository, GenericRepository energyRepository, GenericRepository custoRepository, GenericRepository custoTypeRepository, GenericRepository vipLevelRuleRepository, GenericRepository reserRepository, UniqueCode uniqueCode, ILogger logger) + public RoomService( + GenericRepository roomRepository, + GenericRepository spendRepository, + GenericRepository roomTypeRepository, + GenericRepository energyRepository, + GenericRepository custoRepository, + GenericRepository custoTypeRepository, + GenericRepository vipLevelRuleRepository, + GenericRepository reserRepository, + UniqueCode uniqueCode, + ILogger logger) { this.roomRepository = roomRepository; this.spendRepository = spendRepository; @@ -99,529 +50,235 @@ namespace EOM.TSHotelManagement.Service this.logger = logger; } - /// - /// 根据房间状态获取相应状态的房间信息 - /// - /// - /// - public ListOutputDto SelectRoomByRoomState(ReadRoomInputDto readRoomInputDto) - { - return BuildRoomList(readRoomInputDto); - } + public ListOutputDto SelectRoomByRoomState(ReadRoomInputDto readRoomInputDto) => BuildRoomList(readRoomInputDto); - /// - /// 根据房间状态来查询可使用的房间 - /// - /// - public ListOutputDto SelectCanUseRoomAll() + public ListOutputDto SelectCanUseRoomAll() => BuildRoomList(new ReadRoomInputDto { - var rooms = roomRepository.GetList(a => a.RoomStateId == (int)RoomState.Vacant); - var result = EntityMapper.MapList(rooms); - return new ListOutputDto - { - Data = new PagedData - { - Items = result, - TotalCount = result.Count - } - }; - } + IgnorePaging = true, + RoomStateId = (int)RoomState.Vacant + }); - /// - /// 获取所有房间信息 - /// - /// - public ListOutputDto SelectRoomAll(ReadRoomInputDto readRoomInputDto) - { - return BuildRoomList(readRoomInputDto); - } + public ListOutputDto SelectRoomAll(ReadRoomInputDto readRoomInputDto) => BuildRoomList(readRoomInputDto); - /// - /// 获取房间分区的信息 - /// - /// - public ListOutputDto SelectRoomByTypeName(ReadRoomInputDto readRoomInputDto) - { - return BuildRoomList(readRoomInputDto); - } + public ListOutputDto SelectRoomByTypeName(ReadRoomInputDto readRoomInputDto) => BuildRoomList(readRoomInputDto); - private ListOutputDto BuildRoomList(ReadRoomInputDto readRoomInputDto) + public SingleOutputDto SelectRoomByRoomNo(ReadRoomInputDto readRoomInputDto) { - readRoomInputDto ??= new ReadRoomInputDto(); - - var where = SqlFilterBuilder.BuildExpression(readRoomInputDto); - var query = roomRepository.AsQueryable().Where(a => a.IsDelete != 1); - var whereExpression = where.ToExpression(); - if (whereExpression != null) + var roomResult = ResolveRoom(readRoomInputDto); + if (roomResult.Room == null) { - query = query.Where(whereExpression); + return CreateRoomLookupFailureOutput(roomResult, readRoomInputDto?.RoomNumber, readRoomInputDto?.RoomArea, readRoomInputDto?.RoomFloor); } - query = query.OrderBy(a => a.RoomNumber); - - var count = 0; - List rooms; - if (!readRoomInputDto.IgnorePaging) - { - var page = readRoomInputDto.Page > 0 ? readRoomInputDto.Page : 1; - var pageSize = readRoomInputDto.PageSize > 0 ? readRoomInputDto.PageSize : 15; - rooms = query.ToPageList(page, pageSize, ref count); - } - else - { - rooms = query.ToList(); - count = rooms.Count; - } - - var roomTypeMap = roomTypeRepository.AsQueryable() - .Where(a => a.IsDelete != 1) - .ToList() - .GroupBy(a => a.RoomTypeId) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.RoomTypeName ?? ""); + NormalizeRoom(roomResult.Room); + var data = MapRoomToOutput( + roomResult.Room, + BuildRoomTypeMap(), + BuildCustomerMap(new List { roomResult.Room }), + BuildRoomStateMap()); - var customerNumbers = rooms - .Select(a => a.CustomerNumber) - .Where(a => !a.IsNullOrEmpty()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - - var customerMap = new Dictionary(StringComparer.OrdinalIgnoreCase); - if (customerNumbers.Count > 0) - { - customerMap = custoRepository.AsQueryable() - .Where(a => a.IsDelete != 1 && customerNumbers.Contains(a.CustomerNumber)) - .ToList() - .GroupBy(a => a.CustomerNumber) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.Name ?? "", StringComparer.OrdinalIgnoreCase); - } - - var helper = new EnumHelper(); - var roomStateMap = Enum.GetValues(typeof(RoomState)) - .Cast() - .ToDictionary(e => (int)e, e => helper.GetEnumDescription(e) ?? ""); - - List result; - var useParallelProjection = readRoomInputDto.IgnorePaging && rooms.Count >= 200; - if (useParallelProjection) - { - var dtoArray = new ReadRoomOutputDto[rooms.Count]; - System.Threading.Tasks.Parallel.For(0, rooms.Count, i => - { - var source = rooms[i]; - dtoArray[i] = new ReadRoomOutputDto - { - Id = source.Id, - RoomNumber = source.RoomNumber, - RoomTypeId = source.RoomTypeId, - RoomName = roomTypeMap.TryGetValue(source.RoomTypeId, out var roomTypeName) ? roomTypeName : "", - CustomerNumber = source.CustomerNumber ?? "", - CustomerName = customerMap.TryGetValue(source.CustomerNumber ?? "", out var customerName) ? customerName : "", - LastCheckInTime = source.LastCheckInTime.HasValue ? source.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) : null, - LastCheckOutTime = source.LastCheckOutTime == DateOnly.MinValue ? null : source.LastCheckOutTime.ToDateTime(TimeOnly.MinValue), - RoomStateId = source.RoomStateId, - RoomState = roomStateMap.TryGetValue(source.RoomStateId, out var roomStateName) ? roomStateName : "", - RoomRent = source.RoomRent, - RoomDeposit = source.RoomDeposit, - RoomLocation = source.RoomLocation, - DataInsUsr = source.DataInsUsr, - DataInsDate = source.DataInsDate, - DataChgUsr = source.DataChgUsr, - DataChgDate = source.DataChgDate, - RowVersion = source.RowVersion, - IsDelete = source.IsDelete - }; - }); - result = dtoArray.ToList(); - } - else - { - result = new List(rooms.Count); - rooms.ForEach(source => - { - result.Add(new ReadRoomOutputDto - { - Id = source.Id, - RoomNumber = source.RoomNumber, - RoomTypeId = source.RoomTypeId, - RoomName = roomTypeMap.TryGetValue(source.RoomTypeId, out var roomTypeName) ? roomTypeName : "", - CustomerNumber = source.CustomerNumber ?? "", - CustomerName = customerMap.TryGetValue(source.CustomerNumber ?? "", out var customerName) ? customerName : "", - LastCheckInTime = source.LastCheckInTime.HasValue ? source.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) : null, - LastCheckOutTime = source.LastCheckOutTime == DateOnly.MinValue ? null : source.LastCheckOutTime.ToDateTime(TimeOnly.MinValue), - RoomStateId = source.RoomStateId, - RoomState = roomStateMap.TryGetValue(source.RoomStateId, out var roomStateName) ? roomStateName : "", - RoomRent = source.RoomRent, - RoomDeposit = source.RoomDeposit, - RoomLocation = source.RoomLocation, - DataInsUsr = source.DataInsUsr, - DataInsDate = source.DataInsDate, - DataChgUsr = source.DataChgUsr, - DataChgDate = source.DataChgDate, - RowVersion = source.RowVersion, - IsDelete = source.IsDelete - }); - }); - } - - return new ListOutputDto - { - Data = new PagedData - { - Items = result, - TotalCount = count - } - }; + return new SingleOutputDto { Data = data }; } - /// - /// 根据房间编号查询房间信息 - /// - /// - /// - public SingleOutputDto SelectRoomByRoomNo(ReadRoomInputDto readRoomInputDto) + public SingleOutputDto DayByRoomNo(ReadRoomInputDto roomInputDto) { - List roomStates = new List(); - var helper = new EnumHelper(); - roomStates = Enum.GetValues(typeof(RoomState)) - .Cast() - .Select(e => new EnumDto - { - Id = (int)e, - Name = e.ToString(), - Description = helper.GetEnumDescription(e) - }) - .ToList(); - Room room = new Room(); - room = roomRepository.GetFirst(a => a.IsDelete != 1 && a.RoomNumber == readRoomInputDto.RoomNumber); - if (!room.IsNullOrEmpty()) - { - var roomSate = roomStates.SingleOrDefault(a => a.Id == room.RoomStateId); - room.RoomState = roomSate.Description.IsNullOrEmpty() ? "" : roomSate.Description; - var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId); - room.RoomName = roomType.RoomTypeName.IsNullOrEmpty() ? "" : roomType.RoomTypeName; - } - else + var roomResult = ResolveRoom(roomInputDto); + if (roomResult.Room == null) { - room = new Room(); + return CreateRoomLookupFailureOutput(roomResult, roomInputDto?.RoomNumber, roomInputDto?.RoomArea, roomInputDto?.RoomFloor); } - var Data = EntityMapper.Map(room); - - return new SingleOutputDto() { Data = Data }; - } - - /// - /// 根据房间编号查询截止到今天住了多少天 - /// - /// - /// - public SingleOutputDto DayByRoomNo(ReadRoomInputDto roomInputDto) - { - var room = roomRepository.GetFirst(a => a.RoomNumber == roomInputDto.RoomNumber); - if (room?.LastCheckInTime != null) + if (roomResult.Room.LastCheckInTime.HasValue && roomResult.Room.LastCheckInTime.Value != DateOnly.MinValue) { - var days = Math.Abs((room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - DateTime.Now).Days); + var days = Math.Abs((roomResult.Room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - DateTime.Now).Days); return new SingleOutputDto { Data = new ReadRoomOutputDto { StayDays = days } }; } + return new SingleOutputDto { Data = new ReadRoomOutputDto { StayDays = 0 } }; } - /// - /// 根据房间编号修改房间信息(入住) - /// - /// - /// public BaseResponse UpdateRoomInfo(UpdateRoomInputDto r) { try { - var room = this.roomRepository.GetFirst(a => a.RoomNumber == r.RoomNumber); + var roomResult = ResolveRoom(r); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, r?.RoomNumber, r?.RoomArea, r?.RoomFloor); + } + + var room = roomResult.Room; room.RoomStateId = r.RoomStateId; room.CustomerNumber = r.CustomerNumber; room.LastCheckInTime = r.LastCheckInTime; room.DataChgDate = r.DataChgDate; room.DataChgUsr = r.DataChgUsr; room.RowVersion = r.RowVersion ?? 0; - var updateResult = roomRepository.Update(room); - if (!updateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + return roomRepository.Update(room) ? new BaseResponse() : BaseResponseFactory.ConcurrencyConflict(); } catch (Exception ex) { logger.LogError(ex, "Error updating room info for room number {RoomNumber}", r.RoomNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } - return new BaseResponse(); } - /// - /// 根据房间编号修改房间信息(预约) - /// - /// - /// public BaseResponse UpdateRoomInfoWithReser(UpdateRoomInputDto r) { try { - var room = this.roomRepository.GetFirst(a => a.RoomNumber == r.RoomNumber); + var roomResult = ResolveRoom(r); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, r?.RoomNumber, r?.RoomArea, r?.RoomFloor); + } + + var room = roomResult.Room; room.RoomStateId = r.RoomStateId; room.DataChgDate = r.DataChgDate; room.DataChgUsr = r.DataChgUsr; room.RowVersion = r.RowVersion ?? 0; - var updateResult = roomRepository.Update(room); - if (!updateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + return roomRepository.Update(room) ? new BaseResponse() : BaseResponseFactory.ConcurrencyConflict(); } catch (Exception ex) { logger.LogError(ex, "Error updating room info with reservation for room number {RoomNumber}", r.RoomNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } - return new BaseResponse(); } - /// - /// 查询可入住房间数量 - /// - /// - public SingleOutputDto SelectCanUseRoomAllByRoomState() - { - try - { - var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Vacant && a.IsDelete != 1); - return new SingleOutputDto - { - Data = new ReadRoomOutputDto { Vacant = count } - }; - } - catch (Exception ex) - { - return new SingleOutputDto - { - Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), - Code = BusinessStatusCode.InternalServerError - }; - } - } + public SingleOutputDto SelectCanUseRoomAllByRoomState() => CountByState(RoomState.Vacant, count => new ReadRoomOutputDto { Vacant = count }); - /// - /// 查询已入住房间数量 - /// - /// - public SingleOutputDto SelectNotUseRoomAllByRoomState() - { - try - { - var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Occupied && a.IsDelete != 1); - return new SingleOutputDto - { - Data = new ReadRoomOutputDto { Occupied = count } - }; - } - catch (Exception ex) - { - return new SingleOutputDto - { - Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), - Code = BusinessStatusCode.InternalServerError - }; - } - } + public SingleOutputDto SelectNotUseRoomAllByRoomState() => CountByState(RoomState.Occupied, count => new ReadRoomOutputDto { Occupied = count }); - /// - /// 根据房间编号查询房间价格 - /// - /// - public object SelectRoomByRoomPrice(ReadRoomInputDto r) + public object SelectRoomByRoomPrice(ReadRoomInputDto readRoomInputDto) { - return roomRepository.GetFirst(a => a.RoomNumber == r.RoomNumber).RoomRent; + var roomResult = ResolveRoom(readRoomInputDto); + return roomResult.Room?.RoomRent ?? 0M; } - /// - /// 查询脏房数量 - /// - /// - public SingleOutputDto SelectNotClearRoomAllByRoomState() - { - try - { - var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Dirty && a.IsDelete != 1); - return new SingleOutputDto - { - Data = new ReadRoomOutputDto { Dirty = count } - }; - } - catch (Exception ex) - { - return new SingleOutputDto - { - Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), - Code = BusinessStatusCode.InternalServerError - }; - } - } + public SingleOutputDto SelectNotClearRoomAllByRoomState() => CountByState(RoomState.Dirty, count => new ReadRoomOutputDto { Dirty = count }); - /// - /// 查询维修房数量 - /// - /// - public SingleOutputDto SelectFixingRoomAllByRoomState() - { - try - { - var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Maintenance && a.IsDelete != 1); - return new SingleOutputDto - { - Data = new ReadRoomOutputDto { Maintenance = count } - }; - } - catch (Exception ex) - { - return new SingleOutputDto - { - Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), - Code = BusinessStatusCode.InternalServerError - }; - } - } + public SingleOutputDto SelectFixingRoomAllByRoomState() => CountByState(RoomState.Maintenance, count => new ReadRoomOutputDto { Maintenance = count }); - /// - /// 查询预约房数量 - /// - /// - public SingleOutputDto SelectReservedRoomAllByRoomState() - { - try - { - var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Reserved && a.IsDelete != 1); - return new SingleOutputDto - { - Data = new ReadRoomOutputDto { Reserved = count } - }; - } - catch (Exception ex) - { - return new SingleOutputDto - { - Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), - Code = BusinessStatusCode.InternalServerError - }; - } - } + public SingleOutputDto SelectReservedRoomAllByRoomState() => CountByState(RoomState.Reserved, count => new ReadRoomOutputDto { Reserved = count }); - /// - /// 根据房间编号更改房间状态 - /// - /// - /// public BaseResponse UpdateRoomStateByRoomNo(UpdateRoomInputDto updateRoomInputDto) { try { - var room = roomRepository.GetFirst(a => a.RoomNumber == updateRoomInputDto.RoomNumber); - room.RoomStateId = updateRoomInputDto.RoomStateId; - room.RowVersion = updateRoomInputDto.RowVersion ?? 0; - var updateResult = roomRepository.Update(room); - if (!updateResult) + var roomResult = ResolveRoom(updateRoomInputDto); + if (roomResult.Room == null) { - return BaseResponseFactory.ConcurrencyConflict(); + return CreateRoomLookupFailure(roomResult, updateRoomInputDto?.RoomNumber, updateRoomInputDto?.RoomArea, updateRoomInputDto?.RoomFloor); } + + roomResult.Room.RoomStateId = updateRoomInputDto.RoomStateId; + roomResult.Room.RowVersion = updateRoomInputDto.RowVersion ?? 0; + return roomRepository.Update(roomResult.Room) ? new BaseResponse() : BaseResponseFactory.ConcurrencyConflict(); } catch (Exception ex) { - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } - return new BaseResponse(); } - /// - /// 添加房间 - /// - /// - /// public BaseResponse InsertRoom(CreateRoomInputDto rn) { try { - var isExist = roomRepository.IsAny(a => a.RoomNumber == rn.RoomNumber && a.IsDelete != 1); - if (isExist) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room already exists.", "房间已存在。"), Code = BusinessStatusCode.InternalServerError }; + var normalizedRoomNumber = rn.RoomNumber?.Trim(); + var normalizedRoomArea = RoomLocatorHelper.NormalizeArea(rn.RoomArea); + var duplicateExists = roomRepository.AsQueryable() + .Where(a => a.IsDelete != 1 && a.RoomNumber == normalizedRoomNumber) + .ToList() + .Any(a => string.Equals(RoomLocatorHelper.NormalizeArea(a.RoomArea), normalizedRoomArea, StringComparison.OrdinalIgnoreCase) + && a.RoomFloor == rn.RoomFloor); + + if (duplicateExists) + { + return new BaseResponse { Message = "This room already exists.", Code = BusinessStatusCode.InternalServerError }; + } var entity = EntityMapper.Map(rn); - entity.LastCheckInTime = DateOnly.MinValue; + entity.RoomNumber = normalizedRoomNumber; + entity.RoomArea = string.IsNullOrWhiteSpace(normalizedRoomArea) ? null : normalizedRoomArea; + entity.LastCheckInTime = null; entity.LastCheckOutTime = DateOnly.MinValue; + NormalizeRoom(entity); roomRepository.Insert(entity); + return new BaseResponse(); } catch (Exception ex) { logger.LogError(ex, "Error inserting room with room number {RoomNumber}", rn.RoomNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } - - return new BaseResponse(); } - /// - /// 更新房间 - /// - /// - /// public BaseResponse UpdateRoom(UpdateRoomInputDto rn) { try { - var isExist = roomRepository.IsAny(a => a.RoomNumber == rn.RoomNumber); - if (!isExist) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room does not exist.", "房间不存在。"), Code = BusinessStatusCode.InternalServerError }; + var roomResult = ResolveRoom(rn); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, rn?.RoomNumber, rn?.RoomArea, rn?.RoomFloor); + } + + var room = roomResult.Room; + var normalizedRoomNumber = rn.RoomNumber?.Trim(); + var normalizedRoomArea = RoomLocatorHelper.NormalizeArea(rn.RoomArea); + var duplicateExists = roomRepository.AsQueryable() + .Where(a => a.IsDelete != 1 && a.Id != room.Id && a.RoomNumber == normalizedRoomNumber) + .ToList() + .Any(a => string.Equals(RoomLocatorHelper.NormalizeArea(a.RoomArea), normalizedRoomArea, StringComparison.OrdinalIgnoreCase) + && a.RoomFloor == rn.RoomFloor); - var entity = EntityMapper.Map(rn); - var updateResult = roomRepository.Update(entity); - if (!updateResult) + if (duplicateExists) { - return BaseResponseFactory.ConcurrencyConflict(); + return new BaseResponse { Message = "This room already exists.", Code = BusinessStatusCode.InternalServerError }; } + + room.RoomNumber = normalizedRoomNumber; + room.RoomArea = string.IsNullOrWhiteSpace(normalizedRoomArea) ? null : normalizedRoomArea; + room.RoomFloor = rn.RoomFloor; + room.RoomTypeId = rn.RoomTypeId; + room.CustomerNumber = rn.CustomerNumber; + room.LastCheckInTime = rn.LastCheckInTime; + room.LastCheckOutTime = rn.LastCheckOutTime ?? DateOnly.MinValue; + room.RoomStateId = rn.RoomStateId; + room.RoomRent = rn.RoomRent; + room.RoomDeposit = rn.RoomDeposit; + room.RoomLocation = rn.RoomLocation; + room.RowVersion = rn.RowVersion ?? 0; + room.DataChgUsr = rn.DataChgUsr; + room.DataChgDate = rn.DataChgDate; + NormalizeRoom(room); + + return roomRepository.Update(room) ? new BaseResponse() : BaseResponseFactory.ConcurrencyConflict(); } catch (Exception ex) { logger.LogError(ex, "Error updating room with room number {RoomNumber}", rn.RoomNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to update room.", "更新房间失败。"), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } - - return new BaseResponse(); } - /// - /// 删除房间 - /// - /// - /// public BaseResponse DeleteRoom(DeleteRoomInputDto rn) { try { if (rn?.DelIds == null || !rn.DelIds.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.BadRequest, - Message = LocalizationHelper.GetLocalizedString("Parameters Invalid", "参数错误") - }; + return new BaseResponse { Code = BusinessStatusCode.BadRequest, Message = "Parameters invalid" }; } var delIds = DeleteConcurrencyHelper.GetDeleteIds(rn); var rooms = roomRepository.GetList(a => delIds.Contains(a.Id)); - if (!rooms.Any()) { - return new BaseResponse - { - Code = BusinessStatusCode.NotFound, - Message = LocalizationHelper.GetLocalizedString("Room Information Not Found", "房间信息未找到") - }; + return new BaseResponse { Code = BusinessStatusCode.NotFound, Message = "Room information not found" }; } if (DeleteConcurrencyHelper.HasDeleteConflict(rn, rooms, a => a.Id, a => a.RowVersion)) @@ -629,329 +286,522 @@ namespace EOM.TSHotelManagement.Service return BaseResponseFactory.ConcurrencyConflict(); } - // 如果房间存在预约信息,则不允许删除 - var roomNumbers = rooms.Select(a => a.RoomNumber).ToList(); - var hasReservation = reserRepository.IsAny(a => roomNumbers.Contains(a.ReservationRoomNumber) && a.IsDelete != 1 && a.ReservationEndDate >= DateOnly.FromDateTime(DateTime.Today)); + var roomIds = rooms.Select(a => a.Id).ToList(); + var hasReservation = reserRepository.IsAny(a => + a.IsDelete != 1 && + a.ReservationEndDate >= DateOnly.FromDateTime(DateTime.Today) && + a.RoomId.HasValue && + roomIds.Contains(a.RoomId.Value)); if (hasReservation) { - return new BaseResponse - { - Code = BusinessStatusCode.Conflict, - Message = LocalizationHelper.GetLocalizedString("Cannot delete rooms with active reservations", "无法删除存在有效预约的房间") - }; + return new BaseResponse { Code = BusinessStatusCode.Conflict, Message = "Cannot delete rooms with active reservations" }; } - var result = roomRepository.SoftDeleteRange(rooms); - - return new BaseResponse(BusinessStatusCode.Success, LocalizationHelper.GetLocalizedString("Delete Room Success", "房间信息删除成功")); + roomRepository.SoftDeleteRange(rooms); + return new BaseResponse(BusinessStatusCode.Success, "Delete room success"); } catch (Exception ex) { - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return ErrorResponse(ex); } } - /// - /// 转房操作 - /// - /// - /// public BaseResponse TransferRoom(TransferRoomDto transferRoomDto) { try { - using (TransactionScope scope = new TransactionScope()) + if (transferRoomDto == null + || !transferRoomDto.OriginalRoomId.HasValue + || transferRoomDto.OriginalRoomId.Value <= 0 + || !transferRoomDto.TargetRoomId.HasValue + || transferRoomDto.TargetRoomId.Value <= 0) { - var customer = custoRepository.GetFirst(a => a.CustomerNumber == transferRoomDto.CustomerNumber && a.IsDelete != 1); - if (customer.IsNullOrEmpty()) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not exist", "客户不存在"), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse { Message = "OriginalRoomId and TargetRoomId are required", Code = BusinessStatusCode.BadRequest }; + } - var originalSpends = spendRepository.GetList(a => a.RoomNumber == transferRoomDto.OriginalRoomNumber - && a.CustomerNumber == transferRoomDto.CustomerNumber && a.SettlementStatus == ConsumptionConstant.UnSettle.Code - && a.IsDelete == 0).ToList(); + using var scope = new TransactionScope(); - var vipRules = vipLevelRuleRepository.GetList(a => a.IsDelete != 1).ToList(); + var customer = custoRepository.GetFirst(a => a.CustomerNumber == transferRoomDto.CustomerNumber && a.IsDelete != 1); + if (customer.IsNullOrEmpty()) + { + return new BaseResponse { Message = "The customer does not exist", Code = BusinessStatusCode.InternalServerError }; + } - var originalRoom = roomRepository.GetFirst(a => a.RoomNumber == transferRoomDto.OriginalRoomNumber); - if (originalRoom.CustomerNumber != transferRoomDto.CustomerNumber) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not match the original room", "客户与原房间不匹配"), Code = BusinessStatusCode.InternalServerError }; + var originalRoomResult = ResolveOriginalRoom(transferRoomDto); + if (originalRoomResult.Room == null) + { + return CreateRoomLookupFailure(originalRoomResult, transferRoomDto?.OriginalRoomNumber, transferRoomDto?.OriginalRoomArea, transferRoomDto?.OriginalRoomFloor); + } - if (!originalRoom.LastCheckInTime.HasValue) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The original room lacks check-in time", "原房间缺少入住时间"), Code = BusinessStatusCode.InternalServerError }; + var targetRoomResult = ResolveTargetRoom(transferRoomDto); + if (targetRoomResult.Room == null) + { + return CreateRoomLookupFailure(targetRoomResult, transferRoomDto?.TargetRoomNumber, transferRoomDto?.TargetRoomArea, transferRoomDto?.TargetRoomFloor); + } - var targetRoom = roomRepository.GetFirst(a => a.RoomNumber == transferRoomDto.TargetRoomNumber); - if (targetRoom.IsNullOrEmpty()) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The room does not exist", "房间不存在"), Code = BusinessStatusCode.InternalServerError }; - if (targetRoom.RoomStateId != (int)RoomState.Vacant) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The room is not vacant", "房间不处于空房状态"), Code = BusinessStatusCode.InternalServerError }; + var originalRoom = originalRoomResult.Room; + var targetRoom = targetRoomResult.Room; + if (originalRoom.CustomerNumber != transferRoomDto.CustomerNumber) + { + return new BaseResponse { Message = "The customer does not match the original room", Code = BusinessStatusCode.InternalServerError }; + } - var staySpan = DateTime.Now - originalRoom.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue); - var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + if (!originalRoom.LastCheckInTime.HasValue) + { + return new BaseResponse { Message = "The original room lacks check-in time", Code = BusinessStatusCode.InternalServerError }; + } - var originalSpendNumbers = originalSpends.Select(a => a.SpendNumber).ToList(); - var TotalCountSpent = originalSpends.Sum(a => a.ConsumptionAmount); + if (targetRoom.RoomStateId != (int)RoomState.Vacant) + { + return new BaseResponse { Message = "The room is not vacant", Code = BusinessStatusCode.InternalServerError }; + } - var newLevelId = vipRules - .Where(vipRule => TotalCountSpent >= vipRule.RuleValue) - .OrderByDescending(vipRule => vipRule.RuleValue) - .ThenByDescending(vipRule => vipRule.VipLevelId) - .FirstOrDefault()?.VipLevelId ?? 0; + var originalSpends = spendRepository.GetList(a => + a.RoomId.HasValue && a.RoomId.Value == originalRoom.Id + && a.CustomerNumber == transferRoomDto.CustomerNumber + && a.SettlementStatus == ConsumptionConstant.UnSettle.Code + && a.IsDelete == 0); + + var staySpan = DateTime.Now - originalRoom.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue); + var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + var totalSpent = originalSpends.Sum(a => a.ConsumptionAmount); + var vipRules = vipLevelRuleRepository.GetList(a => a.IsDelete != 1); + var newLevelId = vipRules + .Where(vipRule => totalSpent >= vipRule.RuleValue) + .OrderByDescending(vipRule => vipRule.RuleValue) + .ThenByDescending(vipRule => vipRule.VipLevelId) + .FirstOrDefault()?.VipLevelId ?? 0; + + if (newLevelId != 0) + { + custoRepository.Update(a => new Customer { CustomerType = newLevelId }, a => a.CustomerNumber == transferRoomDto.CustomerNumber); + } - if (newLevelId != 0) - { - custoRepository.Update(a => new Customer - { - CustomerType = newLevelId - }, a => a.CustomerNumber == transferRoomDto.CustomerNumber); - } + var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType && a.IsDelete != 1); + if (customerType.IsNullOrEmpty()) + { + return new BaseResponse { Message = "The customer type does not exist", Code = BusinessStatusCode.InternalServerError }; + } - var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType && a.IsDelete != 1); - if (customerType.IsNullOrEmpty()) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer type does not exist", "客户类型不存在"), Code = BusinessStatusCode.InternalServerError }; - - decimal discount = (customerType != null && customerType.Discount > 0 && customerType.Discount < 100) - ? customerType.Discount / 100M - : 1M; - decimal originalRoomBill = originalRoom.RoomRent * stayDays * discount; - - //更新目标房间状态 - targetRoom.CustomerNumber = originalRoom.CustomerNumber; - targetRoom.RoomStateId = (int)RoomState.Occupied; - targetRoom.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); - var targetRoomUpdateResult = roomRepository.Update(targetRoom); - if (!targetRoomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M; + var originalRoomBill = originalRoom.RoomRent * stayDays * discount; - //更新原房间状态 - originalRoom.CustomerNumber = string.Empty; - originalRoom.RoomStateId = (int)RoomState.Dirty; - originalRoom.LastCheckInTime = DateOnly.MinValue; - originalRoom.LastCheckOutTime = DateOnly.MinValue; - var originalRoomUpdateResult = roomRepository.Update(originalRoom); - if (!originalRoomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + targetRoom.CustomerNumber = originalRoom.CustomerNumber; + targetRoom.RoomStateId = (int)RoomState.Occupied; + targetRoom.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); + if (!roomRepository.Update(targetRoom)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } - //转移原房间消费记录 - if (originalSpendNumbers.Count > 0) - { - var originalSpendList = spendRepository.AsQueryable().Where(a => originalSpendNumbers.Contains(a.SpendNumber)).ToList(); - var spends = new List(); - - foreach (var spend in originalSpendList) - { - spend.SpendNumber = spend.SpendNumber; - spend.RoomNumber = transferRoomDto.TargetRoomNumber; - spends.Add(spend); - } - - var spendTransferResult = spendRepository.UpdateRange(spends); - if (!spendTransferResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } - } + originalRoom.CustomerNumber = string.Empty; + originalRoom.RoomStateId = (int)RoomState.Dirty; + originalRoom.LastCheckInTime = null; + originalRoom.LastCheckOutTime = DateOnly.MinValue; + if (!roomRepository.Update(originalRoom)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } - //添加旧房间消费记录 - var originalSpend = new Spend + if (originalSpends.Count > 0) + { + var originalSpendNumbers = originalSpends.Select(a => a.SpendNumber).ToList(); + var spends = spendRepository.AsQueryable().Where(a => originalSpendNumbers.Contains(a.SpendNumber)).ToList(); + spends.ForEach(spend => { - CustomerNumber = transferRoomDto.CustomerNumber, - RoomNumber = transferRoomDto.TargetRoomNumber, - SpendNumber = uniqueCode.GetNewId("SP-"), - ProductNumber = transferRoomDto.OriginalRoomNumber, - ProductName = "居住" + transferRoomDto.OriginalRoomNumber + "共" + stayDays + "天", - ProductPrice = originalRoom.RoomRent, - ConsumptionTime = DateTime.Now, - SettlementStatus = ConsumptionConstant.UnSettle.Code, - ConsumptionQuantity = stayDays, - ConsumptionAmount = originalRoomBill, - ConsumptionType = SpendTypeConstant.Room.Code, - IsDelete = 0 - }; - spendRepository.Insert(originalSpend); + spend.RoomId = targetRoom.Id; + spend.RoomNumber = targetRoom.RoomNumber; + }); + if (!spendRepository.UpdateRange(spends)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + } - scope.Complete(); + spendRepository.Insert(new Spend + { + CustomerNumber = transferRoomDto.CustomerNumber, + RoomId = targetRoom.Id, + RoomNumber = targetRoom.RoomNumber, + SpendNumber = uniqueCode.GetNewId("SP-"), + ProductNumber = originalRoom.RoomNumber, + ProductName = "Stay " + originalRoom.RoomNumber + " " + stayDays + " days", + ProductPrice = originalRoom.RoomRent, + ConsumptionTime = DateTime.Now, + SettlementStatus = ConsumptionConstant.UnSettle.Code, + ConsumptionQuantity = stayDays, + ConsumptionAmount = originalRoomBill, + ConsumptionType = SpendTypeConstant.Room.Code, + IsDelete = 0 + }); - } + scope.Complete(); + return new BaseResponse(); } catch (Exception ex) { - logger.LogError(ex, "Error transferring room from {OriginalRoomNumber} to {TargetRoomNumber} for customer {CustomerNumber}", transferRoomDto.OriginalRoomNumber, transferRoomDto.TargetRoomNumber, transferRoomDto.CustomerNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + logger.LogError(ex, "Error transferring room"); + return ErrorResponse(ex); } - return new BaseResponse(); } - /// - /// 退房操作 - /// - /// - /// public BaseResponse CheckoutRoom(CheckoutRoomDto checkoutRoomDto) { try { - using (TransactionScope scope = new TransactionScope()) + if (checkoutRoomDto == null || !checkoutRoomDto.RoomId.HasValue || checkoutRoomDto.RoomId.Value <= 0) { - var customer = custoRepository.AsQueryable().Where(a => a.CustomerNumber == checkoutRoomDto.CustomerNumber && a.IsDelete != 1); - if (!customer.Any()) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not exist", "客户不存在"), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse { Message = "RoomId is required", Code = BusinessStatusCode.BadRequest }; + } - var room = roomRepository.GetFirst(a => a.RoomNumber == checkoutRoomDto.RoomNumber); + using var scope = new TransactionScope(); - var checkinDate = room.LastCheckInTime; - var checkoutDate = room.LastCheckOutTime; + var customer = custoRepository.AsQueryable().Where(a => a.CustomerNumber == checkoutRoomDto.CustomerNumber && a.IsDelete != 1); + if (!customer.Any()) + { + return new BaseResponse { Message = "The customer does not exist", Code = BusinessStatusCode.InternalServerError }; + } - //更新房间状态 - room.CustomerNumber = string.Empty; - room.LastCheckInTime = DateOnly.MinValue; - room.LastCheckOutTime = DateOnly.MinValue; - room.RoomStateId = (int)RoomState.Dirty; - var roomUpdateResult = roomRepository.Update(room); - if (!roomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + var roomResult = ResolveRoom(checkoutRoomDto); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, checkoutRoomDto?.RoomNumber, checkoutRoomDto?.RoomArea, checkoutRoomDto?.RoomFloor); + } - //添加能源使用记录 - var energy = new EnergyManagement - { - InformationId = uniqueCode.GetNewId("EM-"), - StartDate = checkinDate ?? DateOnly.MinValue, - EndDate = DateOnly.FromDateTime(DateTime.Today), - WaterUsage = checkoutRoomDto.WaterUsage, - PowerUsage = checkoutRoomDto.ElectricityUsage, - Recorder = "System", - CustomerNumber = room.CustomerNumber, - RoomNumber = checkoutRoomDto.RoomNumber, - IsDelete = 0, - }; - energyRepository.Insert(energy); - - //结算消费记录 - var spendNumbers = spendRepository.GetList(a => a.RoomNumber == checkoutRoomDto.RoomNumber - && a.CustomerNumber.Equals(checkoutRoomDto.CustomerNumber) && a.SettlementStatus == ConsumptionConstant.UnSettle.Code - && a.IsDelete == 0).ToList(); - if (spendNumbers.Count > 0) + var room = roomResult.Room; + var checkinDate = room.LastCheckInTime; + var occupiedCustomerNumber = room.CustomerNumber; + + room.CustomerNumber = string.Empty; + room.LastCheckInTime = null; + room.LastCheckOutTime = DateOnly.MinValue; + room.RoomStateId = (int)RoomState.Dirty; + if (!roomRepository.Update(room)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + + energyRepository.Insert(new EnergyManagement + { + InformationId = uniqueCode.GetNewId("EM-"), + StartDate = checkinDate ?? DateOnly.MinValue, + EndDate = DateOnly.FromDateTime(DateTime.Today), + WaterUsage = checkoutRoomDto.WaterUsage, + PowerUsage = checkoutRoomDto.ElectricityUsage, + Recorder = "System", + CustomerNumber = occupiedCustomerNumber, + RoomId = room.Id, + RoomNumber = room.RoomNumber, + IsDelete = 0 + }); + + var unsettledSpends = spendRepository.GetList(a => + a.RoomId.HasValue && a.RoomId.Value == room.Id + && a.CustomerNumber == checkoutRoomDto.CustomerNumber + && a.SettlementStatus == ConsumptionConstant.UnSettle.Code + && a.IsDelete == 0); + + if (unsettledSpends.Count > 0) + { + unsettledSpends.ForEach(spend => spend.SettlementStatus = ConsumptionConstant.Settled.Code); + if (!spendRepository.UpdateRange(unsettledSpends)) { - var spends = new List(); - foreach (var spend in spendNumbers) - { - spend.SettlementStatus = ConsumptionConstant.Settled.Code; - spends.Add(spend); - } - - var settleSpendResult = spendRepository.UpdateRange(spends); - if (!settleSpendResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + return BaseResponseFactory.ConcurrencyConflict(); } + } - // 插入住房消费记录 - var staySpan = DateTime.Now - room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue); - var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); - var customerType = custoTypeRepository.GetSingle(a => a.CustomerType == customer.First().CustomerType && a.IsDelete != 1); - if (customerType.IsNullOrEmpty()) - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer type does not exist", "客户类型不存在"), Code = BusinessStatusCode.InternalServerError }; - - decimal discount = (customerType != null && customerType.Discount > 0 && customerType.Discount < 100) - ? customerType.Discount / 100M - : 1M; - decimal roomBill = room.RoomRent * stayDays * discount; - var bill = new Spend - { - SpendNumber = uniqueCode.GetNewId("SP-"), - ProductName = $"居住 {checkoutRoomDto.RoomNumber} 共 {stayDays} 天", - SettlementStatus = ConsumptionConstant.Settled.Code, - ConsumptionType = SpendTypeConstant.Room.Code, - ConsumptionQuantity = stayDays, - ConsumptionTime = checkinDate.Value.ToDateTime(TimeOnly.MinValue), - ProductNumber = room.RoomNumber, - ProductPrice = room.RoomRent, - ConsumptionAmount = roomBill, - CustomerNumber = room.CustomerNumber, - RoomNumber = checkoutRoomDto.RoomNumber, - IsDelete = 0, - }; - spendRepository.Insert(bill); - - scope.Complete(); + var staySpan = DateTime.Now - (checkinDate ?? DateOnly.FromDateTime(DateTime.Now)).ToDateTime(TimeOnly.MinValue); + var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + var customerType = custoTypeRepository.GetSingle(a => a.CustomerType == customer.First().CustomerType && a.IsDelete != 1); + if (customerType.IsNullOrEmpty()) + { + return new BaseResponse { Message = "The customer type does not exist", Code = BusinessStatusCode.InternalServerError }; } + + var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M; + var roomBill = room.RoomRent * stayDays * discount; + + spendRepository.Insert(new Spend + { + SpendNumber = uniqueCode.GetNewId("SP-"), + ProductName = "Stay " + room.RoomNumber + " " + stayDays + " days", + SettlementStatus = ConsumptionConstant.Settled.Code, + ConsumptionType = SpendTypeConstant.Room.Code, + ConsumptionQuantity = stayDays, + ConsumptionTime = (checkinDate ?? DateOnly.FromDateTime(DateTime.Now)).ToDateTime(TimeOnly.MinValue), + ProductNumber = room.RoomNumber, + ProductPrice = room.RoomRent, + ConsumptionAmount = roomBill, + CustomerNumber = occupiedCustomerNumber, + RoomId = room.Id, + RoomNumber = room.RoomNumber, + IsDelete = 0 + }); + + scope.Complete(); + return new BaseResponse(); } catch (Exception ex) { - logger.LogError(ex, "Error checking out room number {RoomNumber} for customer {CustomerNumber}", checkoutRoomDto.RoomNumber, checkoutRoomDto.CustomerNumber); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + logger.LogError(ex, "Error checking out room"); + return ErrorResponse(ex); } - return new BaseResponse(); } - /// - /// 根据预约信息办理入住 - /// - /// - /// public BaseResponse CheckinRoomByReservation(CheckinRoomByReservationDto checkinRoomByReservationDto) { try { - using (TransactionScope scope = new TransactionScope()) + if (checkinRoomByReservationDto == null + || !checkinRoomByReservationDto.RoomId.HasValue + || checkinRoomByReservationDto.RoomId.Value <= 0) { - var customer = new Customer - { - CustomerNumber = checkinRoomByReservationDto.CustomerNumber, - Name = checkinRoomByReservationDto.CustomerName, - Gender = checkinRoomByReservationDto.CustomerGender ?? 0, - PhoneNumber = checkinRoomByReservationDto.CustomerPhoneNumber, - IdCardType = checkinRoomByReservationDto.PassportId, - IdCardNumber = checkinRoomByReservationDto.IdCardNumber, - Address = checkinRoomByReservationDto.CustomerAddress, - DateOfBirth = checkinRoomByReservationDto.DateOfBirth, - CustomerType = checkinRoomByReservationDto.CustomerType, - IsDelete = 0, - DataInsUsr = checkinRoomByReservationDto.DataInsUsr, - DataInsDate = checkinRoomByReservationDto.DataInsDate - }; - var customerResult = custoRepository.Insert(customer); - if (!customerResult) - { - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to add customer.", "添加客户失败。"), Code = BusinessStatusCode.InternalServerError }; - } + return new BaseResponse { Message = "RoomId is required", Code = BusinessStatusCode.BadRequest }; + } - var room = roomRepository.GetFirst(a => a.RoomNumber == checkinRoomByReservationDto.RoomNumber && a.IsDelete != 1); - room.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); - room.CustomerNumber = customer.CustomerNumber; - room.RoomStateId = new EnumHelper().GetEnumValue(RoomState.Occupied); - var roomUpdateResult = roomRepository.Update(room); + using var scope = new TransactionScope(); - if (!roomUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + var customer = new Customer + { + CustomerNumber = checkinRoomByReservationDto.CustomerNumber, + Name = checkinRoomByReservationDto.CustomerName, + Gender = checkinRoomByReservationDto.CustomerGender ?? 0, + PhoneNumber = checkinRoomByReservationDto.CustomerPhoneNumber, + IdCardType = checkinRoomByReservationDto.PassportId, + IdCardNumber = checkinRoomByReservationDto.IdCardNumber, + Address = checkinRoomByReservationDto.CustomerAddress, + DateOfBirth = checkinRoomByReservationDto.DateOfBirth, + CustomerType = checkinRoomByReservationDto.CustomerType, + IsDelete = 0, + DataInsUsr = checkinRoomByReservationDto.DataInsUsr, + DataInsDate = checkinRoomByReservationDto.DataInsDate + }; - var reser = reserRepository.GetFirst(a => a.ReservationId == checkinRoomByReservationDto.ReservationId && a.IsDelete != 1); - reser.ReservationStatus = 1; - reser.IsDelete = 1; - var reserUpdateResult = reserRepository.Update(reser); + if (!custoRepository.Insert(customer)) + { + return new BaseResponse { Message = "Failed to add customer.", Code = BusinessStatusCode.InternalServerError }; + } - if (!reserUpdateResult) - { - return BaseResponseFactory.ConcurrencyConflict(); - } + var roomResult = ResolveRoom(checkinRoomByReservationDto); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, checkinRoomByReservationDto?.RoomNumber, checkinRoomByReservationDto?.RoomArea, checkinRoomByReservationDto?.RoomFloor); + } - scope.Complete(); + var room = roomResult.Room; + room.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); + room.CustomerNumber = customer.CustomerNumber; + room.RoomStateId = new EnumHelper().GetEnumValue(RoomState.Occupied); + if (!roomRepository.Update(room)) + { + return BaseResponseFactory.ConcurrencyConflict(); } + + var reser = reserRepository.GetFirst(a => a.ReservationId == checkinRoomByReservationDto.ReservationId && a.IsDelete != 1); + reser.ReservationStatus = 1; + reser.IsDelete = 1; + if (!reserRepository.Update(reser)) + { + return BaseResponseFactory.ConcurrencyConflict(); + } + + scope.Complete(); + return new BaseResponse(); } catch (Exception ex) { - logger.LogError(ex, "Error checking in room number {RoomNumber} by reservation ID {ReservationId}", checkinRoomByReservationDto.RoomNumber, checkinRoomByReservationDto.ReservationId); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + logger.LogError(ex, "Error checking in room by reservation"); + return ErrorResponse(ex); } - return new BaseResponse(); + } + + private ListOutputDto BuildRoomList(ReadRoomInputDto readRoomInputDto) + { + readRoomInputDto ??= new ReadRoomInputDto(); + + var where = SqlFilterBuilder.BuildExpression(readRoomInputDto); + var query = roomRepository.AsQueryable().Where(a => a.IsDelete != 1); + var whereExpression = where.ToExpression(); + if (whereExpression != null) + { + query = query.Where(whereExpression); + } + + query = query.OrderBy($"{nameof(Room.RoomArea)} asc,{nameof(Room.RoomFloor)} asc,{nameof(Room.RoomNumber)} asc"); + + var count = 0; + List rooms; + if (!readRoomInputDto.IgnorePaging) + { + var page = readRoomInputDto.Page > 0 ? readRoomInputDto.Page : 1; + var pageSize = readRoomInputDto.PageSize > 0 ? readRoomInputDto.PageSize : 15; + rooms = query.ToPageList(page, pageSize, ref count); + } + else + { + rooms = query.ToList(); + count = rooms.Count; + } + + rooms.ForEach(NormalizeRoom); + var roomTypeMap = BuildRoomTypeMap(); + var customerMap = BuildCustomerMap(rooms); + var roomStateMap = BuildRoomStateMap(); + + List result; + var useParallelProjection = readRoomInputDto.IgnorePaging && rooms.Count >= 200; + if (useParallelProjection) + { + var dtoArray = new ReadRoomOutputDto[rooms.Count]; + System.Threading.Tasks.Parallel.For(0, rooms.Count, i => + { + dtoArray[i] = MapRoomToOutput(rooms[i], roomTypeMap, customerMap, roomStateMap); + }); + result = dtoArray.ToList(); + } + else + { + result = rooms.Select(a => MapRoomToOutput(a, roomTypeMap, customerMap, roomStateMap)).ToList(); + } + + return new ListOutputDto + { + Data = new PagedData + { + Items = result, + TotalCount = count + } + }; + } + + private SingleOutputDto CountByState(RoomState state, Func builder) + { + try + { + var count = roomRepository.Count(a => a.RoomStateId == (int)state && a.IsDelete != 1); + return new SingleOutputDto { Data = builder(count) }; + } + catch (Exception ex) + { + return new SingleOutputDto { Code = BusinessStatusCode.InternalServerError, Message = ex.Message }; + } + } + + private RoomResolveResult ResolveRoom(ReadRoomInputDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.Id, inputDto?.RoomNumber, inputDto?.RoomArea, inputDto?.RoomFloor); + + private RoomResolveResult ResolveRoom(UpdateRoomInputDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.Id, inputDto?.RoomNumber, inputDto?.RoomArea, inputDto?.RoomFloor); + + private RoomResolveResult ResolveRoom(CheckoutRoomDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.RoomId, null, null, null); + + private RoomResolveResult ResolveRoom(CheckinRoomByReservationDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.RoomId, null, null, null); + + private RoomResolveResult ResolveOriginalRoom(TransferRoomDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.OriginalRoomId, null, null, null); + + private RoomResolveResult ResolveTargetRoom(TransferRoomDto inputDto) => RoomLocatorHelper.Resolve(roomRepository, inputDto?.TargetRoomId, null, null, null); + + private static void NormalizeRoom(Room room) + { + if (room == null) + { + return; + } + + room.RoomNumber = room.RoomNumber?.Trim(); + room.RoomArea = string.IsNullOrWhiteSpace(room.RoomArea) ? null : RoomLocatorHelper.NormalizeArea(room.RoomArea); + room.RoomLocator = RoomLocatorHelper.BuildLocator(room.RoomArea, room.RoomFloor, room.RoomNumber); + } + + private static BaseResponse CreateRoomLookupFailure(RoomResolveResult result, string roomNumber, string roomArea, int? roomFloor) + { + var locator = RoomLocatorHelper.BuildLocator(roomArea, roomFloor, roomNumber); + if (result?.IsAmbiguous == true) + { + return new BaseResponse { Code = BusinessStatusCode.Conflict, Message = $"Multiple rooms match '{locator}'. Please specify room area or floor." }; + } + + if (string.IsNullOrWhiteSpace(locator)) + { + return new BaseResponse { Code = BusinessStatusCode.NotFound, Message = "RoomId was not found." }; + } + + return new BaseResponse { Code = BusinessStatusCode.NotFound, Message = $"Room '{locator}' was not found." }; + } + + private static SingleOutputDto CreateRoomLookupFailureOutput(RoomResolveResult result, string roomNumber, string roomArea, int? roomFloor) + { + var response = CreateRoomLookupFailure(result, roomNumber, roomArea, roomFloor); + return new SingleOutputDto { Code = response.Code, Message = response.Message, Data = new ReadRoomOutputDto() }; + } + + private Dictionary BuildRoomTypeMap() + { + return roomTypeRepository.AsQueryable() + .Where(a => a.IsDelete != 1) + .ToList() + .GroupBy(a => a.RoomTypeId) + .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.RoomTypeName ?? ""); + } + + private Dictionary BuildCustomerMap(List rooms) + { + var customerNumbers = rooms + .Select(a => a.CustomerNumber) + .Where(a => !a.IsNullOrEmpty()) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + if (customerNumbers.Count == 0) + { + return new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + return custoRepository.AsQueryable() + .Where(a => a.IsDelete != 1 && customerNumbers.Contains(a.CustomerNumber)) + .ToList() + .GroupBy(a => a.CustomerNumber) + .ToDictionary(g => g.Key, g => g.FirstOrDefault()?.Name ?? "", StringComparer.OrdinalIgnoreCase); + } + + private static Dictionary BuildRoomStateMap() + { + var helper = new EnumHelper(); + return Enum.GetValues(typeof(RoomState)).Cast().ToDictionary(e => (int)e, e => helper.GetEnumDescription(e) ?? ""); + } + + private static ReadRoomOutputDto MapRoomToOutput(Room source, Dictionary roomTypeMap, Dictionary customerMap, Dictionary roomStateMap) + { + return new ReadRoomOutputDto + { + Id = source.Id, + RoomNumber = source.RoomNumber, + RoomArea = source.RoomArea ?? string.Empty, + RoomFloor = source.RoomFloor, + RoomLocator = RoomLocatorHelper.BuildLocator(source.RoomArea, source.RoomFloor, source.RoomNumber), + RoomTypeId = source.RoomTypeId, + RoomName = roomTypeMap.TryGetValue(source.RoomTypeId, out var roomTypeName) ? roomTypeName : "", + CustomerNumber = source.CustomerNumber ?? "", + CustomerName = customerMap.TryGetValue(source.CustomerNumber ?? "", out var customerName) ? customerName : "", + LastCheckInTime = source.LastCheckInTime.HasValue && source.LastCheckInTime.Value != DateOnly.MinValue + ? source.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) + : null, + LastCheckOutTime = source.LastCheckOutTime == DateOnly.MinValue ? null : source.LastCheckOutTime.ToDateTime(TimeOnly.MinValue), + RoomStateId = source.RoomStateId, + RoomState = roomStateMap.TryGetValue(source.RoomStateId, out var roomStateName) ? roomStateName : "", + RoomRent = source.RoomRent, + RoomDeposit = source.RoomDeposit, + RoomLocation = source.RoomLocation, + DataInsUsr = source.DataInsUsr, + DataInsDate = source.DataInsDate, + DataChgUsr = source.DataChgUsr, + DataChgDate = source.DataChgDate, + RowVersion = source.RowVersion, + IsDelete = source.IsDelete + }; + } + + private static BaseResponse ErrorResponse(Exception ex) + { + return new BaseResponse { Message = ex.Message, Code = BusinessStatusCode.InternalServerError }; } } } diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs index ebfadc0..536c15a 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs @@ -150,13 +150,19 @@ namespace EOM.TSHotelManagement.Service /// public SingleOutputDto SelectRoomTypeByRoomNo(ReadRoomTypeInputDto readRoomTypeInputDto) { - RoomType roomtype = new RoomType(); - Room room = new Room(); - room = roomRepository.GetFirst(a => a.RoomNumber == readRoomTypeInputDto.RoomNumber && a.IsDelete != 1); - roomtype.RoomTypeName = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId).RoomTypeName; - - var source = EntityMapper.Map(roomtype); + var roomResult = RoomLocatorHelper.Resolve(roomRepository, readRoomTypeInputDto?.Id, readRoomTypeInputDto?.RoomNumber, readRoomTypeInputDto?.RoomArea, readRoomTypeInputDto?.RoomFloor); + if (roomResult.Room == null) + { + return new SingleOutputDto + { + Code = roomResult.IsAmbiguous ? BusinessStatusCode.Conflict : BusinessStatusCode.NotFound, + Message = roomResult.IsAmbiguous ? "Multiple rooms match the current room number." : "Room not found.", + Data = new ReadRoomTypeOutputDto() + }; + } + var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == roomResult.Room.RoomTypeId && a.IsDelete != 1) ?? new RoomType(); + var source = EntityMapper.Map(roomType); return new SingleOutputDto { Data = source }; } #endregion diff --git a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs index 65eb0d6..351509f 100644 --- a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs +++ b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs @@ -1,83 +1,37 @@ -/* - * MIT License - *Copyright (c) 2021 易开元(Easy-Open-Meta) - - *Permission is hereby granted, free of charge, to any person obtaining a copy - *of this software and associated documentation files (the "Software"), to deal - *in the Software without restriction, including without limitation the rights - *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - *copies of the Software, and to permit persons to whom the Software is - *furnished to do so, subject to the following conditions: - - *The above copyright notice and this permission notice shall be included in all - *copies or substantial portions of the Software. - - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - *SOFTWARE. - * - */ using EOM.TSHotelManagement.Common; using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; using jvncorelib.CodeLib; -using jvncorelib.EntityLib; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; -using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; using System.Transactions; namespace EOM.TSHotelManagement.Service { - /// - /// 商品消费接口实现类 - /// public class SpendService : ISpendService { - /// - /// 商品消费 - /// private readonly GenericRepository spendRepository; - - /// - /// 商品 - /// private readonly GenericRepository sellThingRepository; - - /// - /// 房间 - /// - private readonly GenericRepository roomRepository; - - /// - /// 客户 - /// - private readonly GenericRepository customerRepository; - - /// - /// 客户类型 - /// - private readonly GenericRepository custoTypeRepository; - - /// - /// 操作日志 - /// - private readonly GenericRepository operationLogRepository; - - private readonly IHttpContextAccessor _httpContextAccessor; - + private readonly IHttpContextAccessor httpContextAccessor; private readonly ILogger logger; - public SpendService(GenericRepository spendRepository, GenericRepository sellThingRepository, GenericRepository roomRepository, GenericRepository customerRepository, GenericRepository custoTypeRepository, GenericRepository operationLogRepository, IHttpContextAccessor httpContextAccessor, ILogger logger) + public SpendService( + GenericRepository spendRepository, + GenericRepository sellThingRepository, + GenericRepository roomRepository, + GenericRepository customerRepository, + GenericRepository custoTypeRepository, + GenericRepository operationLogRepository, + IHttpContextAccessor httpContextAccessor, + ILogger logger) { this.spendRepository = spendRepository; this.sellThingRepository = sellThingRepository; @@ -85,202 +39,44 @@ namespace EOM.TSHotelManagement.Service this.customerRepository = customerRepository; this.custoTypeRepository = custoTypeRepository; this.operationLogRepository = operationLogRepository; - _httpContextAccessor = httpContextAccessor; + this.httpContextAccessor = httpContextAccessor; this.logger = logger; } - #region 根据客户编号查询历史消费信息 - /// - /// 根据客户编号查询历史消费信息 - /// - /// - /// - public ListOutputDto SeletHistorySpendInfoAll(ReadSpendInputDto readSpendInputDto) - { - readSpendInputDto ??= new ReadSpendInputDto(); - - var where = SqlFilterBuilder.BuildExpression(readSpendInputDto); - var query = spendRepository.AsQueryable().Where(a => a.IsDelete != 1); - var whereExpression = where.ToExpression(); - if (whereExpression != null) - { - query = query.Where(whereExpression); - } - - var count = 0; - List spends; - if (!readSpendInputDto.IgnorePaging) - { - var page = readSpendInputDto.Page > 0 ? readSpendInputDto.Page : 1; - var pageSize = readSpendInputDto.PageSize > 0 ? readSpendInputDto.PageSize : 15; - spends = query.ToPageList(page, pageSize, ref count); - } - else - { - spends = query.ToList(); - count = spends.Count; - } - var result = EntityMapper.MapList(spends); - var useParallelProjection = readSpendInputDto.IgnorePaging && result.Count >= 200; - if (useParallelProjection) - { - System.Threading.Tasks.Parallel.For(0, result.Count, i => FillSpendDerivedFields(result[i])); - } - else - { - result.ForEach(FillSpendDerivedFields); - } - - return new ListOutputDto - { - Data = new PagedData - { - Items = result, - TotalCount = count - } - }; - } - #endregion - - #region 根据房间编号查询消费信息 - /// - /// 根据房间编号查询消费信息 - /// - /// - /// - public ListOutputDto SelectSpendByRoomNo(ReadSpendInputDto readSpendInputDto) - { - readSpendInputDto ??= new ReadSpendInputDto(); + public ListOutputDto SeletHistorySpendInfoAll(ReadSpendInputDto readSpendInputDto) => BuildSpendList(readSpendInputDto); - var where = SqlFilterBuilder.BuildExpression(readSpendInputDto); - var query = spendRepository.AsQueryable().Where(a => a.IsDelete != 1); - var whereExpression = where.ToExpression(); - if (whereExpression != null) - { - query = query.Where(whereExpression); - } + public ListOutputDto SelectSpendByRoomNo(ReadSpendInputDto readSpendInputDto) => BuildSpendList(readSpendInputDto); - var count = 0; - List spends; - if (!readSpendInputDto.IgnorePaging) - { - var page = readSpendInputDto.Page > 0 ? readSpendInputDto.Page : 1; - var pageSize = readSpendInputDto.PageSize > 0 ? readSpendInputDto.PageSize : 15; - spends = query.ToPageList(page, pageSize, ref count); - } - else - { - spends = query.ToList(); - count = spends.Count; - } - var result = EntityMapper.MapList(spends); - var useParallelProjection = readSpendInputDto.IgnorePaging && result.Count >= 200; - if (useParallelProjection) - { - System.Threading.Tasks.Parallel.For(0, result.Count, i => FillSpendDerivedFields(result[i])); - } - else - { - result.ForEach(FillSpendDerivedFields); - } + public ListOutputDto SelectSpendInfoAll(ReadSpendInputDto readSpendInputDto) => BuildSpendList(readSpendInputDto, nameof(Spend.ConsumptionTime)); - return new ListOutputDto - { - Data = new PagedData - { - Items = result, - TotalCount = count - } - }; - } - #endregion - - #region 查询消费的所有信息 - /// - /// 查询消费的所有信息 - /// - /// - public ListOutputDto SelectSpendInfoAll(ReadSpendInputDto readSpendInputDto) + public SingleOutputDto SumConsumptionAmount(ReadSpendInputDto readSpendInputDto) { readSpendInputDto ??= new ReadSpendInputDto(); - var where = SqlFilterBuilder.BuildExpression(readSpendInputDto, nameof(Spend.ConsumptionTime)); - var query = spendRepository.AsQueryable().Where(a => a.IsDelete != 1); - var whereExpression = where.ToExpression(); - if (whereExpression != null) - { - query = query.Where(whereExpression); - } + var query = spendRepository.AsQueryable() + .Where(a => a.IsDelete != 1 && a.CustomerNumber == readSpendInputDto.CustomerNumber && a.SettlementStatus == ConsumptionConstant.UnSettle.Code); - var count = 0; - List spends; - if (!readSpendInputDto.IgnorePaging) + if (readSpendInputDto.RoomId.HasValue && readSpendInputDto.RoomId.Value > 0) { - var page = readSpendInputDto.Page > 0 ? readSpendInputDto.Page : 1; - var pageSize = readSpendInputDto.PageSize > 0 ? readSpendInputDto.PageSize : 15; - spends = query.ToPageList(page, pageSize, ref count); - } - else - { - spends = query.ToList(); - count = spends.Count; - } - var result = EntityMapper.MapList(spends); - var useParallelProjection = readSpendInputDto.IgnorePaging && result.Count >= 200; - if (useParallelProjection) - { - System.Threading.Tasks.Parallel.For(0, result.Count, i => FillSpendDerivedFields(result[i])); - } - else - { - result.ForEach(FillSpendDerivedFields); + query = query.Where(a => a.RoomId == readSpendInputDto.RoomId); } - return new ListOutputDto + var totalCountAmount = query.ToList().Sum(a => a.ConsumptionAmount); + return new SingleOutputDto { - Data = new PagedData + Data = new ReadSpendInputDto { - Items = result, - TotalCount = count + RoomId = readSpendInputDto.RoomId, + RoomNumber = readSpendInputDto.RoomNumber, + CustomerNumber = readSpendInputDto.CustomerNumber, + ConsumptionAmount = totalCountAmount } }; } - #endregion - private static void FillSpendDerivedFields(ReadSpendOutputDto item) - { - item.SettlementStatusDescription = item.SettlementStatus.IsNullOrEmpty() ? "" - : item.SettlementStatus.Equals(ConsumptionConstant.Settled.Code) ? "已结算" : "未结算"; - - item.ProductPriceFormatted = item.ProductPrice.ToString("#,##0.00"); - item.ConsumptionAmountFormatted = item.ConsumptionAmount.ToString("#,##0.00"); - - item.ConsumptionTypeDescription = item.ConsumptionType == SpendTypeConstant.Product.Code ? SpendTypeConstant.Product.Description - : item.ConsumptionType == SpendTypeConstant.Room.Code ? SpendTypeConstant.Room.Description - : SpendTypeConstant.Other.Description; - } - - #region 根据房间编号、入住时间到当前时间查询消费总金额 - /// - /// 根据房间编号、入住时间到当前时间查询消费总金额 - /// - /// - /// - public SingleOutputDto SumConsumptionAmount(ReadSpendInputDto readSpendInputDto) - { - var TotalCountAmount = spendRepository.GetList(a => a.RoomNumber == readSpendInputDto.RoomNumber && a.CustomerNumber == readSpendInputDto.CustomerNumber && a.SettlementStatus == ConsumptionConstant.UnSettle.Code).Sum(a => a.ConsumptionAmount); - return new SingleOutputDto { Data = new ReadSpendInputDto { ConsumptionAmount = TotalCountAmount } }; - } - #endregion - - /// - /// 撤回客户消费信息 - /// - /// - /// public BaseResponse UndoCustomerSpend(UndoCustomerSpendInputDto undoCustomerSpendInputDto) { - var httpContext = _httpContextAccessor.HttpContext; + var httpContext = httpContextAccessor.HttpContext; using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); try @@ -288,29 +84,24 @@ namespace EOM.TSHotelManagement.Service var existingSpend = spendRepository.GetFirst(a => a.Id == undoCustomerSpendInputDto.Id && a.IsDelete != 1); if (existingSpend == null) { - return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Spend record not found", "消费记录不存在")); + return new BaseResponse(BusinessStatusCode.NotFound, "Spend record not found."); } if (existingSpend.ConsumptionType != SpendTypeConstant.Product.Code) { - return new BaseResponse(BusinessStatusCode.BadRequest, LocalizationHelper.GetLocalizedString("Cancellation of non-commodity consumption records is not allowed", "不允许撤销非商品消费记录")); + return new BaseResponse(BusinessStatusCode.BadRequest, "Only product spends can be canceled."); } - var isProductSpend = string.Equals(existingSpend.ConsumptionType, SpendTypeConstant.Product.Code, StringComparison.OrdinalIgnoreCase) - && !string.IsNullOrWhiteSpace(existingSpend.ProductNumber) - && existingSpend.ConsumptionQuantity > 0; - - if (isProductSpend) + if (!string.IsNullOrWhiteSpace(existingSpend.ProductNumber) && existingSpend.ConsumptionQuantity > 0) { var product = sellThingRepository.GetFirst(a => a.ProductNumber == existingSpend.ProductNumber && a.IsDelete != 1); if (product == null) { - return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Product not found", "商品不存在")); + return new BaseResponse(BusinessStatusCode.NotFound, "Product not found."); } product.Stock += existingSpend.ConsumptionQuantity; - var productUpdateResult = sellThingRepository.Update(product); - if (!productUpdateResult) + if (!sellThingRepository.Update(product)) { return BaseResponseFactory.ConcurrencyConflict(); } @@ -318,89 +109,68 @@ namespace EOM.TSHotelManagement.Service existingSpend.IsDelete = 1; existingSpend.RowVersion = undoCustomerSpendInputDto.RowVersion ?? 0; - var updateResult = spendRepository.Update(existingSpend); - if (!updateResult) + if (!spendRepository.Update(existingSpend)) { return BaseResponseFactory.ConcurrencyConflict(); } - var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} 撤销了消费记录: " + - $"房间 {existingSpend.RoomNumber}, " + - $"商品 {existingSpend.ProductName}, " + - $"数量 {existingSpend.ConsumptionQuantity}, " + - $"金额 {existingSpend.ConsumptionAmount.ToString("#,##0.00")}"; - - var context = _httpContextAccessor.HttpContext; - - var log = new OperationLog - { - OperationId = new UniqueCode().GetNewId("OP-"), - OperationTime = Convert.ToDateTime(DateTime.Now), - LogContent = logContent, - LoginIpAddress = context.Connection.RemoteIpAddress?.ToString() ?? string.Empty, - OperationAccount = ClaimsPrincipalExtensions.GetUserNumber(httpContext.User), - LogLevel = (int)Common.LogLevel.Warning, - SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), - }; - operationLogRepository.Insert(log); - + var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} canceled a spend record. Room {existingSpend.RoomNumber}, Product {existingSpend.ProductName}, Qty {existingSpend.ConsumptionQuantity}, Amount {existingSpend.ConsumptionAmount:#,##0.00}"; + operationLogRepository.Insert(BuildOperationLog(logContent)); scope.Complete(); + return new BaseResponse(); } catch (Exception ex) { - logger.LogError(ex, "撤回客户消费信息失败"); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + logger.LogError(ex, "Undo customer spend failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, ex.Message); } - return new BaseResponse(); } - /// - /// 添加客户消费信息 - /// - /// - /// public BaseResponse AddCustomerSpend(AddCustomerSpendInputDto addCustomerSpendInputDto) { - var httpContext = _httpContextAccessor.HttpContext; if (addCustomerSpendInputDto?.ConsumptionQuantity <= 0 || addCustomerSpendInputDto.ProductPrice <= 0) { - return new BaseResponse() { Message = "商品数量和价格必须大于零", Code = BusinessStatusCode.BadRequest }; + return new BaseResponse(BusinessStatusCode.BadRequest, "Product quantity and price must be greater than zero."); } using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); try { - var room = roomRepository.AsQueryable().Single(a => a.RoomNumber == addCustomerSpendInputDto.RoomNumber); - if (room == null) + var roomResult = RoomReferenceHelper.Resolve(roomRepository, addCustomerSpendInputDto?.RoomId, addCustomerSpendInputDto?.RoomNumber); + if (roomResult.Room == null) { - return new BaseResponse() { Message = $"房间 '{addCustomerSpendInputDto.RoomNumber}' 不存在", Code = BusinessStatusCode.BadRequest }; + return CreateRoomLookupFailure(roomResult, addCustomerSpendInputDto?.RoomId, addCustomerSpendInputDto?.RoomNumber); } - var customer = customerRepository.AsQueryable().Single(a => a.CustomerNumber == room.CustomerNumber); + var room = roomResult.Room; + var customer = customerRepository.GetFirst(a => a.CustomerNumber == room.CustomerNumber && a.IsDelete != 1); if (customer == null) { - return new BaseResponse() { Message = $"客户 '{room.CustomerNumber}' 不存在", Code = BusinessStatusCode.BadRequest }; + return new BaseResponse(BusinessStatusCode.BadRequest, $"Customer '{room.CustomerNumber}' was not found."); } - var customerType = custoTypeRepository.AsQueryable().Single(a => a.CustomerType == customer.CustomerType); - decimal discount = (customerType != null && customerType.Discount > 0 && customerType.Discount < 100) - ? customerType.Discount / 100M - : 1M; + var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType && a.IsDelete != 1); + var discount = customerType != null && customerType.Discount > 0 && customerType.Discount < 100 + ? customerType.Discount / 100M + : 1M; - decimal realAmount = addCustomerSpendInputDto.ProductPrice * addCustomerSpendInputDto.ConsumptionQuantity * discount; - - var existingSpend = spendRepository.AsQueryable().Single(a => a.RoomNumber == addCustomerSpendInputDto.RoomNumber && a.ProductNumber == addCustomerSpendInputDto.ProductNumber && a.IsDelete != 1 && a.SettlementStatus == ConsumptionConstant.UnSettle.Code); + var realAmount = addCustomerSpendInputDto.ProductPrice * addCustomerSpendInputDto.ConsumptionQuantity * discount; + var existingSpend = spendRepository.GetFirst(a => + a.IsDelete != 1 && + a.SettlementStatus == ConsumptionConstant.UnSettle.Code && + a.ProductNumber == addCustomerSpendInputDto.ProductNumber && + a.RoomId == room.Id); if (existingSpend != null) { + existingSpend.RoomId = room.Id; + existingSpend.RoomNumber = room.RoomNumber; existingSpend.ConsumptionType = SpendTypeConstant.Product.Code; existingSpend.ConsumptionQuantity += addCustomerSpendInputDto.ConsumptionQuantity; existingSpend.ConsumptionAmount += realAmount; - - var result = spendRepository.Update(existingSpend); - if (!result) + if (!spendRepository.Update(existingSpend)) { return BaseResponseFactory.ConcurrencyConflict(); } @@ -410,7 +180,8 @@ namespace EOM.TSHotelManagement.Service var newSpend = new Spend { SpendNumber = new UniqueCode().GetNewId("SP-"), - RoomNumber = addCustomerSpendInputDto.RoomNumber, + RoomId = room.Id, + RoomNumber = room.RoomNumber, ProductNumber = addCustomerSpendInputDto.ProductNumber, ProductName = addCustomerSpendInputDto.ProductName, ConsumptionQuantity = addCustomerSpendInputDto.ConsumptionQuantity, @@ -422,57 +193,39 @@ namespace EOM.TSHotelManagement.Service SettlementStatus = ConsumptionConstant.UnSettle.Code }; - var result = spendRepository.Insert(newSpend); - if (!result) + if (!spendRepository.Insert(newSpend)) { - return new BaseResponse() { Message = "添加消费记录失败", Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse(BusinessStatusCode.InternalServerError, "Failed to add spend record."); } } - var product = sellThingRepository.AsQueryable().Single(a => a.ProductNumber == addCustomerSpendInputDto.ProductNumber); - product.Stock = product.Stock - addCustomerSpendInputDto.ConsumptionQuantity; - var updateResult = sellThingRepository.Update(product); - if (!updateResult) + var product = sellThingRepository.GetFirst(a => a.ProductNumber == addCustomerSpendInputDto.ProductNumber && a.IsDelete != 1); + if (product == null) { - return BaseResponseFactory.ConcurrencyConflict(); + return new BaseResponse(BusinessStatusCode.BadRequest, $"Product '{addCustomerSpendInputDto.ProductNumber}' was not found."); } - var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} 添加了消费记录: " + - $"房间 {addCustomerSpendInputDto.RoomNumber}, " + - $"商品 {addCustomerSpendInputDto.ProductName}, " + - $"数量 {addCustomerSpendInputDto.ConsumptionQuantity}, " + - $"金额 {realAmount.ToString("#,##0.00")}"; - - var context = _httpContextAccessor.HttpContext; - - var log = new OperationLog + product.Stock -= addCustomerSpendInputDto.ConsumptionQuantity; + if (!sellThingRepository.Update(product)) { - OperationId = new UniqueCode().GetNewId("OP-"), - OperationTime = Convert.ToDateTime(DateTime.Now), - LogContent = logContent, - LoginIpAddress = context.Connection.RemoteIpAddress?.ToString() ?? string.Empty, - OperationAccount = ClaimsPrincipalExtensions.GetUserNumber(httpContext.User), - LogLevel = (int)Common.LogLevel.Warning, - SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), - }; - operationLogRepository.Insert(log); + return BaseResponseFactory.ConcurrencyConflict(); + } - scope.Complete(); + var roomLocator = RoomLocatorHelper.BuildLocator(room.RoomArea, room.RoomFloor, room.RoomNumber); + var currentUser = httpContextAccessor.HttpContext == null ? string.Empty : ClaimsPrincipalExtensions.GetUserNumber(httpContextAccessor.HttpContext.User); + var logContent = $"{currentUser} added a spend record. Room {roomLocator}, Product {addCustomerSpendInputDto.ProductName}, Qty {addCustomerSpendInputDto.ConsumptionQuantity}, Amount {realAmount:#,##0.00}"; + operationLogRepository.Insert(BuildOperationLog(logContent)); + scope.Complete(); return new BaseResponse(); } catch (Exception ex) { - logger.LogError(ex, "添加客户消费信息失败"); - return new BaseResponse() { Message = $"添加消费记录失败,请稍后重试。{ex.Message}", Code = BusinessStatusCode.InternalServerError }; + logger.LogError(ex, "Add customer spend failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, $"Failed to add spend record. {ex.Message}"); } } - /// - /// 更新消费信息 - /// - /// - /// public BaseResponse UpdSpendInfo(UpdateSpendInputDto spend) { try @@ -480,28 +233,190 @@ namespace EOM.TSHotelManagement.Service var dbSpend = spendRepository.GetFirst(a => a.SpendNumber == spend.SpendNumber && a.IsDelete != 1); if (dbSpend == null) { - return new BaseResponse(BusinessStatusCode.NotFound, LocalizationHelper.GetLocalizedString("Spend record not found", "消费记录不存在")); + return new BaseResponse(BusinessStatusCode.NotFound, "Spend record not found."); } + + Room room = null; + if (spend.RoomId.HasValue && spend.RoomId.Value > 0) + { + var roomResult = RoomReferenceHelper.Resolve(roomRepository, spend.RoomId, spend.RoomNumber); + if (roomResult.Room == null) + { + return CreateRoomLookupFailure(roomResult, spend.RoomId, spend.RoomNumber); + } + + room = roomResult.Room; + } + else if (!string.IsNullOrWhiteSpace(spend.RoomNumber)) + { + return new BaseResponse(BusinessStatusCode.BadRequest, "RoomId is required."); + } + dbSpend.SettlementStatus = spend.SettlementStatus; - dbSpend.RoomNumber = spend.RoomNumber; + dbSpend.RoomId = room?.Id ?? dbSpend.RoomId; + dbSpend.RoomNumber = room?.RoomNumber ?? dbSpend.RoomNumber; dbSpend.CustomerNumber = spend.CustomerNumber; dbSpend.ProductName = spend.ProductName; dbSpend.ConsumptionQuantity = spend.ConsumptionQuantity; + dbSpend.ProductPrice = spend.ProductPrice; dbSpend.ConsumptionAmount = spend.ConsumptionAmount; + dbSpend.ConsumptionTime = spend.ConsumptionTime; + dbSpend.ConsumptionType = spend.ConsumptionType; dbSpend.RowVersion = spend.RowVersion ?? 0; - var updateResult = spendRepository.Update(dbSpend); - if (!updateResult) + + return spendRepository.Update(dbSpend) ? new BaseResponse() : BaseResponseFactory.ConcurrencyConflict(); + } + catch (Exception ex) + { + logger.LogError(ex, "Update spend failed"); + return new BaseResponse(BusinessStatusCode.InternalServerError, ex.Message); + } + } + + private ListOutputDto BuildSpendList(ReadSpendInputDto readSpendInputDto, string dateFieldName = null) + { + readSpendInputDto ??= new ReadSpendInputDto(); + var filterInput = CreateSpendFilter(readSpendInputDto); + + var where = string.IsNullOrWhiteSpace(dateFieldName) + ? SqlFilterBuilder.BuildExpression(filterInput) + : SqlFilterBuilder.BuildExpression(filterInput, dateFieldName); + + var query = spendRepository.AsQueryable().Where(a => a.IsDelete != 1); + var whereExpression = where.ToExpression(); + if (whereExpression != null) + { + query = query.Where(whereExpression); + } + + if (readSpendInputDto.RoomId.HasValue && readSpendInputDto.RoomId.Value > 0) + { + query = query.Where(a => a.RoomId == readSpendInputDto.RoomId.Value); + } + + var count = 0; + List spends; + if (readSpendInputDto.IgnorePaging) + { + spends = query.ToList(); + count = spends.Count; + } + else + { + var page = readSpendInputDto.Page > 0 ? readSpendInputDto.Page : 1; + var pageSize = readSpendInputDto.PageSize > 0 ? readSpendInputDto.PageSize : 15; + spends = query.ToPageList(page, pageSize, ref count); + } + + var rooms = RoomReferenceHelper.LoadRooms(roomRepository, spends.Select(a => a.RoomId), spends.Select(a => a.RoomNumber)); + var result = spends.Select(a => MapSpendToOutput(a, RoomReferenceHelper.FindRoom(rooms, a.RoomId, a.RoomNumber))).ToList(); + + return new ListOutputDto + { + Data = new PagedData { - return BaseResponseFactory.ConcurrencyConflict(); + Items = result, + TotalCount = count } + }; + } + + private static ReadSpendOutputDto MapSpendToOutput(Spend source, Room room) + { + var output = new ReadSpendOutputDto + { + Id = source.Id, + RoomId = source.RoomId ?? room?.Id, + SpendNumber = source.SpendNumber, + RoomNumber = room?.RoomNumber ?? source.RoomNumber, + RoomArea = RoomReferenceHelper.GetRoomArea(room), + RoomFloor = RoomReferenceHelper.GetRoomFloor(room), + RoomLocator = RoomReferenceHelper.GetRoomLocator(room), + CustomerNumber = source.CustomerNumber, + ProductNumber = source.ProductNumber, + ProductName = source.ProductName, + ConsumptionQuantity = source.ConsumptionQuantity, + ProductPrice = source.ProductPrice, + ConsumptionAmount = source.ConsumptionAmount, + ConsumptionTime = source.ConsumptionTime, + SettlementStatus = source.SettlementStatus, + ConsumptionType = source.ConsumptionType, + DataInsUsr = source.DataInsUsr, + DataInsDate = source.DataInsDate, + DataChgUsr = source.DataChgUsr, + DataChgDate = source.DataChgDate, + RowVersion = source.RowVersion, + IsDelete = source.IsDelete + }; + + FillSpendDerivedFields(output); + return output; + } + + private static void FillSpendDerivedFields(ReadSpendOutputDto item) + { + item.SettlementStatusDescription = string.IsNullOrWhiteSpace(item.SettlementStatus) + ? string.Empty + : item.SettlementStatus.Equals(ConsumptionConstant.Settled.Code, StringComparison.OrdinalIgnoreCase) ? "Settled" : "Unsettled"; + + item.ProductPriceFormatted = item.ProductPrice.ToString("#,##0.00"); + item.ConsumptionAmountFormatted = item.ConsumptionAmount.ToString("#,##0.00"); + item.ConsumptionTypeDescription = item.ConsumptionType == SpendTypeConstant.Product.Code + ? SpendTypeConstant.Product.Description + : item.ConsumptionType == SpendTypeConstant.Room.Code + ? SpendTypeConstant.Room.Description + : SpendTypeConstant.Other.Description; + } + + private OperationLog BuildOperationLog(string logContent) + { + var context = httpContextAccessor.HttpContext; + var operationAccount = context == null ? string.Empty : ClaimsPrincipalExtensions.GetUserNumber(context.User); + return new OperationLog + { + OperationId = new UniqueCode().GetNewId("OP-"), + OperationTime = DateTime.Now, + LogContent = logContent, + LoginIpAddress = context?.Connection.RemoteIpAddress?.ToString() ?? string.Empty, + OperationAccount = operationAccount, + LogLevel = (int)Common.LogLevel.Warning, + SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion() + }; + } + + private static BaseResponse CreateRoomLookupFailure(RoomResolveResult result, int? roomId, string roomNumber) + { + if (!roomId.HasValue || roomId.Value <= 0) + { + return new BaseResponse(BusinessStatusCode.BadRequest, "RoomId is required."); } - catch (Exception ex) + + if (result?.IsAmbiguous == true) { - logger.LogError(ex, "更新消费信息失败"); - return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + return new BaseResponse(BusinessStatusCode.Conflict, $"Multiple rooms match room id '{roomId.Value}'."); } - return new BaseResponse(); + + return new BaseResponse(BusinessStatusCode.NotFound, $"RoomId '{roomId.Value}' was not found."); } + private static ReadSpendInputDto CreateSpendFilter(ReadSpendInputDto input) + { + return new ReadSpendInputDto + { + Page = input.Page, + PageSize = input.PageSize, + IgnorePaging = input.IgnorePaging, + SpendNumber = input.SpendNumber, + RoomId = null, + RoomNumber = null, + CustomerNumber = input.CustomerNumber, + ProductName = input.ProductName, + ConsumptionQuantity = input.ConsumptionQuantity, + ProductPrice = input.ProductPrice, + ConsumptionAmount = input.ConsumptionAmount, + SettlementStatus = input.SettlementStatus, + DateRangeDto = input.DateRangeDto + }; + } } } diff --git a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs index 5248f94..180c573 100644 --- a/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs +++ b/EOM.TSHotelManagement.Service/Dashboard/DashboardService.cs @@ -145,7 +145,7 @@ namespace EOM.TSHotelManagement.Service .Where(a => a.RoomStateId == (int)RoomState.Reserved) .Select(a => { - var reservation = resers.SingleOrDefault(b => b.ReservationRoomNumber == a.RoomNumber); + var reservation = resers.SingleOrDefault(b => b.RoomId.HasValue && b.RoomId.Value == a.Id); var roomType = roomTypes.SingleOrDefault(b => b.RoomTypeId == a.RoomTypeId); return new TempReservationAlert { -- Gitee From f0078e62e6c26bf6312916487ca85d156f9ab260 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 14 Mar 2026 18:34:07 +0800 Subject: [PATCH 15/20] =?UTF-8?q?=E6=88=BF=E9=97=B4=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=BA=94=E5=A2=9E=E5=8A=A0=E5=8C=BA=E5=9F=9F=E6=88=96=E6=A5=BC?= =?UTF-8?q?=E5=B1=82=EF=BC=8C=E4=B8=8D=E5=90=8C=E5=8C=BA=E5=9F=9F=E7=9A=84?= =?UTF-8?q?=E6=88=BF=E9=97=B4=E5=8F=B7=E5=8F=AF=E8=83=BD=E6=98=AF=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=EF=BC=8C=E6=88=BF=E6=80=81=E4=B8=AD=E5=BA=94?= =?UTF-8?q?=E6=8C=89=E5=8C=BA=E5=9F=9F=E6=88=96=E6=A5=BC=E5=B1=82=E5=8C=BA?= =?UTF-8?q?=E5=88=86=E6=8E=92=E5=88=97=EF=BC=8C=E5=89=8D=E5=8F=B0=E5=AE=A2?= =?UTF-8?q?=E6=9C=8D=E5=8F=AF=E9=AB=98=E6=95=88=E5=AE=9A=E4=BD=8D=E5=88=B0?= =?UTF-8?q?=E6=88=BF=E9=97=B4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DatabaseInitializer.cs | 133 ++++++++++++++++++ .../Business/Room/Room.cs | 12 +- .../Business/Room/RoomService.cs | 28 +++- 3 files changed, 163 insertions(+), 10 deletions(-) diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index 483431e..708631d 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -103,6 +103,8 @@ namespace EOM.TSHotelManagement.Data db.CodeFirst.InitTables(needCreateTableTypes); EnsureRoomSchema(db); + EnsureRoomLocationColumn(db); + EnsureRoomLocatorUniqueIndex(db); Console.WriteLine("Database schema initialized"); @@ -307,6 +309,59 @@ namespace EOM.TSHotelManagement.Data }); } + private void EnsureRoomLocationColumn(ISqlSugarClient db) + { + if (!ColumnExists(db, "room", "room_location")) + { + EnsureColumn(db, "room", "room_location", new Dictionary + { + [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_location` varchar(200) NULL", + [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_location` varchar(200) NULL", + [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_location\" varchar(200)", + [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_location] nvarchar(200) NULL", + [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_location TEXT NULL" + }); + } + + DropColumnIfExists(db, "room", "room_position"); + } + + private void EnsureRoomLocatorUniqueIndex(ISqlSugarClient db) + { + const string indexName = "UK_room_room_no_area_floor"; + if (IndexExists(db, "room", indexName)) + { + return; + } + + if (HasDuplicateRoomLocator(db)) + { + Console.WriteLine($"Skip creating unique index {indexName} because duplicate room locator data already exists."); + return; + } + + var sql = db.CurrentConnectionConfig.DbType switch + { + DbType.MySql or DbType.MySqlConnector => + $"CREATE UNIQUE INDEX `{indexName}` ON `room` (`room_no`, `room_area`, `room_floor`)", + DbType.PostgreSQL => + $"CREATE UNIQUE INDEX IF NOT EXISTS \"{indexName}\" ON \"room\" (\"room_no\", \"room_area\", \"room_floor\")", + DbType.SqlServer => + $"CREATE UNIQUE INDEX [{indexName}] ON [room] ([room_no], [room_area], [room_floor])", + DbType.Sqlite => + $"CREATE UNIQUE INDEX IF NOT EXISTS {indexName} ON room (room_no, room_area, room_floor)", + _ => string.Empty + }; + + if (string.IsNullOrWhiteSpace(sql)) + { + Console.WriteLine($"Skip unique index patch for unsupported DbType {db.CurrentConnectionConfig.DbType} on room locator."); + return; + } + + db.Ado.ExecuteCommand(sql); + } + private void EnsureColumn(ISqlSugarClient db, string tableName, string columnName, IReadOnlyDictionary sqlMap) { if (ColumnExists(db, tableName, columnName)) @@ -323,6 +378,84 @@ namespace EOM.TSHotelManagement.Data db.Ado.ExecuteCommand(sql); } + private bool IndexExists(ISqlSugarClient db, string tableName, string indexName) + { + var dbType = db.CurrentConnectionConfig.DbType; + string sql = dbType switch + { + DbType.MySql or DbType.MySqlConnector => + "SELECT COUNT(1) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = @tableName AND index_name = @indexName", + DbType.PostgreSQL => + "SELECT COUNT(1) FROM pg_indexes WHERE schemaname = current_schema() AND tablename = @tableName AND indexname = @indexName", + DbType.SqlServer => + "SELECT COUNT(1) FROM sys.indexes WHERE object_id = OBJECT_ID(@tableName) AND name = @indexName", + DbType.Sqlite => + $"SELECT COUNT(1) FROM pragma_index_list('{tableName}') WHERE name = @indexName", + _ => string.Empty + }; + + if (string.IsNullOrEmpty(sql)) + { + return true; + } + + return db.Ado.GetInt(sql, new List + { + new SugarParameter("@tableName", tableName), + new SugarParameter("@indexName", indexName) + }) > 0; + } + + private bool HasDuplicateRoomLocator(ISqlSugarClient db) + { + var sql = db.CurrentConnectionConfig.DbType switch + { + DbType.MySql or DbType.MySqlConnector => + "SELECT COUNT(1) FROM (SELECT `room_no`, COALESCE(`room_area`, ''), COALESCE(`room_floor`, -1) FROM `room` GROUP BY `room_no`, COALESCE(`room_area`, ''), COALESCE(`room_floor`, -1) HAVING COUNT(1) > 1) t", + DbType.PostgreSQL => + "SELECT COUNT(1) FROM (SELECT \"room_no\", COALESCE(\"room_area\", ''), COALESCE(\"room_floor\", -1) FROM \"room\" GROUP BY \"room_no\", COALESCE(\"room_area\", ''), COALESCE(\"room_floor\", -1) HAVING COUNT(1) > 1) t", + DbType.SqlServer => + "SELECT COUNT(1) FROM (SELECT [room_no], COALESCE([room_area], ''), COALESCE([room_floor], -1) FROM [room] GROUP BY [room_no], COALESCE([room_area], ''), COALESCE([room_floor], -1) HAVING COUNT(1) > 1) t", + DbType.Sqlite => + "SELECT COUNT(1) FROM (SELECT room_no, COALESCE(room_area, ''), COALESCE(room_floor, -1) FROM room GROUP BY room_no, COALESCE(room_area, ''), COALESCE(room_floor, -1) HAVING COUNT(1) > 1) t", + _ => string.Empty + }; + + if (string.IsNullOrWhiteSpace(sql)) + { + return false; + } + + return db.Ado.GetInt(sql) > 0; + } + + private void DropColumnIfExists(ISqlSugarClient db, string tableName, string columnName) + { + if (!ColumnExists(db, tableName, columnName)) + { + return; + } + + var sql = db.CurrentConnectionConfig.DbType switch + { + DbType.MySql or DbType.MySqlConnector => + $"ALTER TABLE `{tableName}` DROP COLUMN `{columnName}`", + DbType.PostgreSQL => + $"ALTER TABLE \"{tableName}\" DROP COLUMN IF EXISTS \"{columnName}\"", + DbType.SqlServer => + $"ALTER TABLE [{tableName}] DROP COLUMN [{columnName}]", + _ => string.Empty + }; + + if (string.IsNullOrWhiteSpace(sql)) + { + Console.WriteLine($"Skip dropping column {tableName}.{columnName} for unsupported DbType {db.CurrentConnectionConfig.DbType}."); + return; + } + + db.Ado.ExecuteCommand(sql); + } + private bool ColumnExists(ISqlSugarClient db, string tableName, string columnName) { var dbType = db.CurrentConnectionConfig.DbType; diff --git a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs index 6a91b14..286940d 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs @@ -11,10 +11,10 @@ namespace EOM.TSHotelManagement.Domain [SugarColumn( ColumnName = "room_no", - IsPrimaryKey = true, ColumnDescription = "Room number", IsNullable = false, - Length = 128 + Length = 128, + UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } )] public string RoomNumber { get; set; } @@ -22,14 +22,16 @@ namespace EOM.TSHotelManagement.Domain ColumnName = "room_area", ColumnDescription = "Room area", IsNullable = true, - Length = 128 + Length = 128, + UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } )] public string RoomArea { get; set; } [SugarColumn( ColumnName = "room_floor", ColumnDescription = "Room floor", - IsNullable = true + IsNullable = true, + UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } )] public int? RoomFloor { get; set; } @@ -93,7 +95,7 @@ namespace EOM.TSHotelManagement.Domain public decimal RoomDeposit { get; set; } [SugarColumn( - ColumnName = "room_position", + ColumnName = "room_location", ColumnDescription = "Room location", IsNullable = false, Length = 200 diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index 87dcdd6..dfab2fc 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -396,7 +396,7 @@ namespace EOM.TSHotelManagement.Service originalRoom.CustomerNumber = string.Empty; originalRoom.RoomStateId = (int)RoomState.Dirty; - originalRoom.LastCheckInTime = null; + originalRoom.LastCheckInTime = DateOnly.MinValue; originalRoom.LastCheckOutTime = DateOnly.MinValue; if (!roomRepository.Update(originalRoom)) { @@ -425,7 +425,7 @@ namespace EOM.TSHotelManagement.Service RoomNumber = targetRoom.RoomNumber, SpendNumber = uniqueCode.GetNewId("SP-"), ProductNumber = originalRoom.RoomNumber, - ProductName = "Stay " + originalRoom.RoomNumber + " " + stayDays + " days", + ProductName = "居住 " + string.Join("/", originalRoom.RoomArea, originalRoom.RoomFloor, originalRoom.RoomNumber) + " 共 " + stayDays + " 天", ProductPrice = originalRoom.RoomRent, ConsumptionTime = DateTime.Now, SettlementStatus = ConsumptionConstant.UnSettle.Code, @@ -473,7 +473,7 @@ namespace EOM.TSHotelManagement.Service var occupiedCustomerNumber = room.CustomerNumber; room.CustomerNumber = string.Empty; - room.LastCheckInTime = null; + room.LastCheckInTime = DateOnly.MinValue; room.LastCheckOutTime = DateOnly.MinValue; room.RoomStateId = (int)RoomState.Dirty; if (!roomRepository.Update(room)) @@ -524,7 +524,7 @@ namespace EOM.TSHotelManagement.Service spendRepository.Insert(new Spend { SpendNumber = uniqueCode.GetNewId("SP-"), - ProductName = "Stay " + room.RoomNumber + " " + stayDays + " days", + ProductName = "居住 " + string.Join("/", room.RoomArea, room.RoomFloor, room.RoomNumber) + " 共 " + stayDays + " 天", SettlementStatus = ConsumptionConstant.Settled.Code, ConsumptionType = SpendTypeConstant.Room.Code, ConsumptionQuantity = stayDays, @@ -627,7 +627,7 @@ namespace EOM.TSHotelManagement.Service query = query.Where(whereExpression); } - query = query.OrderBy($"{nameof(Room.RoomArea)} asc,{nameof(Room.RoomFloor)} asc,{nameof(Room.RoomNumber)} asc"); + query = query.OrderBy(BuildRoomListOrderByClause()); var count = 0; List rooms; @@ -733,6 +733,24 @@ namespace EOM.TSHotelManagement.Service return new SingleOutputDto { Code = response.Code, Message = response.Message, Data = new ReadRoomOutputDto() }; } + private string BuildRoomListOrderByClause() + { + var entityInfo = roomRepository.Context.EntityMaintenance.GetEntityInfo(); + var orderedColumns = new[] + { + nameof(Room.RoomArea), + nameof(Room.RoomFloor), + nameof(Room.RoomNumber) + }; + + return string.Join(", ", orderedColumns.Select(propertyName => + { + var columnInfo = entityInfo.Columns.FirstOrDefault(a => a.PropertyName == propertyName); + var columnName = columnInfo?.DbColumnName ?? propertyName; + return $"{columnName} asc"; + })); + } + private Dictionary BuildRoomTypeMap() { return roomTypeRepository.AsQueryable() -- Gitee From 965b4cf5fc8b6b3fe07bf0e13c6c869f9b12c0a8 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 21 Mar 2026 02:29:14 +0800 Subject: [PATCH 16/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=91=98=E5=B7=A5?= =?UTF-8?q?=E5=B1=A5=E5=8E=86=E6=96=B0=E5=A2=9E=E3=80=81=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../History/EmployeeHistoryController.cs | 12 +++++++ .../ReadEmployeeCheckOutputDto.cs | 12 +++++-- .../CreateEmployeeHistoryInputDto.cs | 31 +++++++++++++---- .../UpdateEmployeeHistoryInputDto.cs | 33 ++++++++++++------- .../Employee/EmployeeCheck.cs | 6 ---- .../EntityBuilder.cs | 1 + .../Employee/Check/EmployeeCheckService.cs | 7 ++-- .../History/EmployeeHistoryService.cs | 29 +++++++++++++++- .../History/IEmployeeHistoryService.cs | 11 +++++-- 9 files changed, 109 insertions(+), 33 deletions(-) diff --git a/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs b/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs index a74afed..616af7e 100644 --- a/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs @@ -29,6 +29,18 @@ namespace EOM.TSHotelManagement.WebApi.Controllers return workerHistoryService.AddHistoryByEmployeeId(workerHistory); } + /// + /// 根据工号更新员工履历 + /// + /// + /// + [RequirePermission("staffmanagement.uhbei")] + [HttpPost] + public BaseResponse UpdateHistoryByEmployeeId([FromBody] UpdateEmployeeHistoryInputDto workerHistory) + { + return workerHistoryService.UpdateHistoryByEmployeeId(workerHistory); + } + /// /// 根据工号查询履历信息 /// diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/ReadEmployeeCheckOutputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/ReadEmployeeCheckOutputDto.cs index 0b2ec8c..792fc39 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/ReadEmployeeCheckOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeCheck/ReadEmployeeCheckOutputDto.cs @@ -1,18 +1,26 @@ -namespace EOM.TSHotelManagement.Contract +using SqlSugar; + +namespace EOM.TSHotelManagement.Contract { public class ReadEmployeeCheckOutputDto : BaseOutputDto { public string EmployeeId { get; set; } public DateTime CheckTime { get; set; } - public string CheckStatus { get; set; } + public int CheckStatus { get; set; } public string CheckMethod { get; set; } + public string CheckMethodDescription { get; set; } public bool MorningChecked { get; set; } public bool EveningChecked { get; set; } public int CheckDay { get; set; } + + /// + /// 打卡状态描述 (Check-in/Check-out Status Description) + /// + public string CheckStatusDescription { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/CreateEmployeeHistoryInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/CreateEmployeeHistoryInputDto.cs index 5a6f6f4..ff36650 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/CreateEmployeeHistoryInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/CreateEmployeeHistoryInputDto.cs @@ -4,19 +4,36 @@ namespace EOM.TSHotelManagement.Contract { public class CreateEmployeeHistoryInputDto : BaseInputDto { + [Required(ErrorMessage = "履历编号为必填字段")] + public string HistoryNumber { get; set; } + [Required(ErrorMessage = "员工工号为必填字段")] [MaxLength(128, ErrorMessage = "员工工号长度不超过128字符")] public string EmployeeId { get; set; } - [Required(ErrorMessage = "变更日期为必填字段")] - public DateTime ChangeDate { get; set; } + /// + /// 开始时间 (Start Date) + /// + [Required(ErrorMessage = "开始时间为必填字段")] + public DateOnly StartDate { get; set; } + + /// + /// 结束时间 (End Date) + /// + [Required(ErrorMessage = "结束时间为必填字段")] + public DateOnly EndDate { get; set; } - [Required(ErrorMessage = "变更类型为必填字段")] - [MaxLength(128, ErrorMessage = "变更类型长度不超过128字符")] - public string ChangeType { get; set; } + /// + /// 职位 (Position) + /// + [Required(ErrorMessage = "职位为必填字段")] + public string Position { get; set; } - [MaxLength(500, ErrorMessage = "变更描述长度不超过500字符")] - public string ChangeDescription { get; set; } + /// + /// 公司 (Company) + /// + [Required(ErrorMessage = "公司为必填字段")] + public string Company { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/UpdateEmployeeHistoryInputDto.cs b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/UpdateEmployeeHistoryInputDto.cs index 84c425b..94db020 100644 --- a/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/UpdateEmployeeHistoryInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Employee/Dto/EmployeeHistory/UpdateEmployeeHistoryInputDto.cs @@ -1,24 +1,33 @@ +using SqlSugar; using System.ComponentModel.DataAnnotations; namespace EOM.TSHotelManagement.Contract { public class UpdateEmployeeHistoryInputDto : BaseInputDto { - [Required(ErrorMessage = "履历ID为必填字段")] - public int HistoryId { get; set; } + /// + /// 开始时间 (Start Date) + /// + [Required(ErrorMessage = "开始时间为必填字段")] + public DateOnly StartDate { get; set; } - [Required(ErrorMessage = "员工工号为必填字段")] - [MaxLength(128, ErrorMessage = "员工工号长度不超过128字符")] - public string EmployeeId { get; set; } + /// + /// 结束时间 (End Date) + /// + [Required(ErrorMessage = "结束时间为必填字段")] + public DateOnly EndDate { get; set; } - [Required(ErrorMessage = "变更日期为必填字段")] - public DateTime ChangeDate { get; set; } + /// + /// 职位 (Position) + /// + [Required(ErrorMessage = "职位为必填字段")] + public string Position { get; set; } - [MaxLength(128, ErrorMessage = "变更类型长度不超过128字符")] - public string ChangeType { get; set; } - - [MaxLength(500, ErrorMessage = "变更描述长度不超过500字符")] - public string ChangeDescription { get; set; } + /// + /// 公司 (Company) + /// + [Required(ErrorMessage = "公司为必填字段")] + public string Company { get; set; } } } diff --git a/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs b/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs index 89e567b..dcb79fc 100644 --- a/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs +++ b/EOM.TSHotelManagement.Domain/Employee/EmployeeCheck.cs @@ -67,11 +67,5 @@ namespace EOM.TSHotelManagement.Domain ///
[SugarColumn(ColumnName = "check_state", ColumnDescription = "打卡状态 (Check-in/Check-out Status)", IsNullable = false)] public int CheckStatus { get; set; } - - /// - /// 打卡状态描述 (Check-in/Check-out Status Description) - /// - [SugarColumn(IsIgnore = true)] - public string CheckStatusDescription { get; set; } } } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 4393fad..0b666c7 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -866,6 +866,7 @@ namespace EOM.TSHotelManagement.Migration // 员工履历管理 new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "humanresource", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "humanresource", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.uhbei", PermissionName = "根据工号更新员工履历", Module = "humanresource", Description = "根据工号更新员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工打卡管理 new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "humanresource", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "humanresource", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, diff --git a/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs b/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs index 13f6eae..4d69711 100644 --- a/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs +++ b/EOM.TSHotelManagement.Service/Employee/Check/EmployeeCheckService.cs @@ -78,12 +78,13 @@ namespace EOM.TSHotelManagement.Service count = workerChecks.Count; } - workerChecks.ForEach(source => + var source = EntityMapper.MapList(workerChecks); + + source.ForEach(source => { source.CheckStatusDescription = source.CheckStatus == 0 ? "早班" : "晚班"; + source.CheckMethodDescription = source.CheckMethod == CheckTypeConstant.Web.Code ? CheckTypeConstant.Web.Description : CheckTypeConstant.Client.Description; }); - var source = EntityMapper.MapList(workerChecks); - return new ListOutputDto { Data = new PagedData diff --git a/EOM.TSHotelManagement.Service/Employee/History/EmployeeHistoryService.cs b/EOM.TSHotelManagement.Service/Employee/History/EmployeeHistoryService.cs index de93a8e..15edd02 100644 --- a/EOM.TSHotelManagement.Service/Employee/History/EmployeeHistoryService.cs +++ b/EOM.TSHotelManagement.Service/Employee/History/EmployeeHistoryService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -65,6 +65,33 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse(); } + /// + /// 根据工号更新员工履历 + /// + /// + /// + public BaseResponse UpdateHistoryByEmployeeId(UpdateEmployeeHistoryInputDto workerHistory) + { + try + { + var existingHistory = workerHistoryRepository.GetSingle(a => a.Id == workerHistory.Id); + if (existingHistory == null) + { + return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Cannot found Employee History", "找不到员工履历"), Code = BusinessStatusCode.NotFound }; + } + existingHistory.StartDate = workerHistory.StartDate; + existingHistory.EndDate = workerHistory.EndDate; + existingHistory.Company = workerHistory.Company; + existingHistory.Position = workerHistory.Position; + workerHistoryRepository.Update(existingHistory); + } + catch (Exception ex) + { + return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError }; + } + return new BaseResponse(); + } + /// /// 根据工号查询履历信息 /// diff --git a/EOM.TSHotelManagement.Service/Employee/History/IEmployeeHistoryService.cs b/EOM.TSHotelManagement.Service/Employee/History/IEmployeeHistoryService.cs index bbcc6f5..6f3fced 100644 --- a/EOM.TSHotelManagement.Service/Employee/History/IEmployeeHistoryService.cs +++ b/EOM.TSHotelManagement.Service/Employee/History/IEmployeeHistoryService.cs @@ -1,4 +1,4 @@ -/* +/* * MIT License *Copyright (c) 2021 易开元(Easy-Open-Meta) @@ -37,6 +37,13 @@ namespace EOM.TSHotelManagement.Service /// BaseResponse AddHistoryByEmployeeId(CreateEmployeeHistoryInputDto workerHistory); + /// + /// 根据工号更新员工履历 + /// + /// + /// + BaseResponse UpdateHistoryByEmployeeId(UpdateEmployeeHistoryInputDto workerHistory); + /// /// 根据工号查询履历信息 /// @@ -44,4 +51,4 @@ namespace EOM.TSHotelManagement.Service /// ListOutputDto SelectHistoryByEmployeeId(ReadEmployeeHistoryInputDto wid); } -} \ No newline at end of file +} -- Gitee From 9fe8a3fc8e6a4d2f69c6d2f90261bb717cee2584 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 21 Mar 2026 17:16:00 +0800 Subject: [PATCH 17/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0swagger=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=A0=87=E7=AD=BE=E8=BF=9B=E8=A1=8C=E5=8C=BA=E5=88=86?= =?UTF-8?q?=E3=80=82=20=E6=B7=BB=E5=8A=A0=E7=BB=9F=E4=B8=80=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=AE=A1=E8=AE=A1=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Customer/CustomerAccountController.cs | 1 + .../Business/News/NewsController.cs | 1 + .../Business/Room/RoomController.cs | 7 + .../History/EmployeeHistoryController.cs | 3 +- .../Extensions/ApplicationExtensions.cs | 1 + .../Extensions/ClientApiGroupConvention.cs | 110 +++++ .../Extensions/ServiceExtensions.cs | 71 +++ .../Filters/BusinessOperationAuditFilter.cs | 410 ++++++++++++++++++ .../Dto/ReadEnergyManagementInputDto.cs | 5 +- .../Room/Dto/CheckinRoomByReservationDto.cs | 1 + .../Room/Dto/Room/ReadRoomInputDto.cs | 3 +- .../Room/Dto/Room/ReadRoomOutputDto.cs | 12 + .../Room/Dto/Room/ReadRoomPricingOutputDto.cs | 21 + .../Room/Dto/Room/UpdateRoomInputDto.cs | 7 +- .../Dto/RoomType/CreateRoomTypeInputDto.cs | 1 + .../Dto/RoomType/ReadRoomTypeOutputDto.cs | 1 + .../Dto/RoomType/RoomTypePricingItemDto.cs | 13 + .../Dto/RoomType/UpdateRoomTypeInputDto.cs | 1 + .../DatabaseInitializer.cs | 226 ---------- .../EnergyManagement/EnergyManagement.cs | 4 +- .../Business/Room/Room.cs | 58 ++- .../Business/Room/RoomType.cs | 8 + .../Constant/CodeConstantBase.cs | 53 ++- .../EntityBuilder.cs | 2 +- .../EnergyManagementService.cs | 12 +- .../Business/Room/IRoomService.cs | 9 +- .../Business/Room/RoomPricingEvaluation.cs | 14 + .../Business/Room/RoomPricingHelper.cs | 117 +++++ .../Business/Room/RoomService.cs | 349 +++++++++++++-- .../Business/Room/RoomTypeService.cs | 76 +++- .../Business/Spend/SpendService.cs | 38 +- 31 files changed, 1299 insertions(+), 336 deletions(-) create mode 100644 EOM.TSHotelManagement.API/Extensions/ClientApiGroupConvention.cs create mode 100644 EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs create mode 100644 EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomPricingOutputDto.cs create mode 100644 EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/RoomTypePricingItemDto.cs create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomPricingEvaluation.cs create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomPricingHelper.cs diff --git a/EOM.TSHotelManagement.API/Controllers/Business/Customer/CustomerAccountController.cs b/EOM.TSHotelManagement.API/Controllers/Business/Customer/CustomerAccountController.cs index 15b12f0..dbe5e2f 100644 --- a/EOM.TSHotelManagement.API/Controllers/Business/Customer/CustomerAccountController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Business/Customer/CustomerAccountController.cs @@ -6,6 +6,7 @@ using System.Security.Claims; namespace EOM.TSHotelManagement.WebApi.Controllers { + [ApiExplorerSettings(GroupName = "v1_Mobile")] public class CustomerAccountController : ControllerBase { private readonly ICustomerAccountService _customerAccountService; diff --git a/EOM.TSHotelManagement.API/Controllers/Business/News/NewsController.cs b/EOM.TSHotelManagement.API/Controllers/Business/News/NewsController.cs index 072e3e3..6eecfe0 100644 --- a/EOM.TSHotelManagement.API/Controllers/Business/News/NewsController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Business/News/NewsController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; namespace EOM.TSHotelManagement.WebApi { + [ApiExplorerSettings(GroupName = "v1_Mobile")] public class NewsController : ControllerBase { private readonly INewsService newsService; diff --git a/EOM.TSHotelManagement.API/Controllers/Business/Room/RoomController.cs b/EOM.TSHotelManagement.API/Controllers/Business/Room/RoomController.cs index e2530ce..c9adfd3 100644 --- a/EOM.TSHotelManagement.API/Controllers/Business/Room/RoomController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Business/Room/RoomController.cs @@ -145,6 +145,13 @@ namespace EOM.TSHotelManagement.WebApi.Controllers return roomService.SelectRoomByRoomPrice(inputDto); } + [RequirePermission("roommanagement.srbrp")] + [HttpGet] + public SingleOutputDto SelectRoomPricingOptions([FromQuery] ReadRoomInputDto inputDto) + { + return roomService.SelectRoomPricingOptions(inputDto); + } + /// /// 查询脏房数量 /// diff --git a/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs b/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs index 616af7e..d8e0890 100644 --- a/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs +++ b/EOM.TSHotelManagement.API/Controllers/Employee/History/EmployeeHistoryController.cs @@ -34,7 +34,7 @@ namespace EOM.TSHotelManagement.WebApi.Controllers ///
/// /// - [RequirePermission("staffmanagement.uhbei")] + [RequirePermission("staffmanagement.update")] [HttpPost] public BaseResponse UpdateHistoryByEmployeeId([FromBody] UpdateEmployeeHistoryInputDto workerHistory) { @@ -55,4 +55,3 @@ namespace EOM.TSHotelManagement.WebApi.Controllers } } - diff --git a/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs index c08e4fc..66972cb 100644 --- a/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ApplicationExtensions.cs @@ -101,6 +101,7 @@ namespace EOM.TSHotelManagement.WebApi app.UseReDoc(config => { config.Path = "/redoc"; + config.DocumentPath = "/swagger/v1/swagger.json"; }); } } diff --git a/EOM.TSHotelManagement.API/Extensions/ClientApiGroupConvention.cs b/EOM.TSHotelManagement.API/Extensions/ClientApiGroupConvention.cs new file mode 100644 index 0000000..53cdafe --- /dev/null +++ b/EOM.TSHotelManagement.API/Extensions/ClientApiGroupConvention.cs @@ -0,0 +1,110 @@ +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using System; +using System.Collections.Generic; + +namespace EOM.TSHotelManagement.WebApi +{ + internal static class ClientApiGroups + { + public const string Web = "v1_Web"; + public const string Desktop = "v1_Desktop"; + public const string Mobile = "v1_Mobile"; + + public static readonly string[] All = new[] { Web, Desktop, Mobile }; + } + + internal sealed class ClientApiGroupConvention : IApplicationModelConvention + { + private static readonly HashSet MobileControllers = new(StringComparer.OrdinalIgnoreCase) + { + "CustomerAccount", + "News" + }; + + private static readonly HashSet DesktopEndpoints = new(StringComparer.OrdinalIgnoreCase) + { + "/Base/DeleteRewardPunishmentType", + "/Base/InsertRewardPunishmentType", + "/Base/SelectCustoTypeByTypeId", + "/Base/SelectDept", + "/Base/SelectDeptAllCanUse", + "/Base/SelectEducation", + "/Base/SelectGenderTypeAll", + "/Base/SelectNation", + "/Base/SelectPassPortTypeByTypeId", + "/Base/SelectPosition", + "/Base/SelectReserTypeAll", + "/Base/SelectRewardPunishmentTypeAll", + "/Base/SelectRewardPunishmentTypeAllCanUse", + "/Base/SelectRewardPunishmentTypeByTypeId", + "/Base/UpdateRewardPunishmentType", + "/Customer/UpdCustomerTypeByCustoNo", + "/CustomerAccount/Login", + "/CustomerAccount/Register", + "/Employee/UpdateEmployeeAccountPassword", + "/EmployeeCheck/SelectWorkerCheckDaySumByEmployeeId", + "/EmployeePhoto/DeleteWorkerPhoto", + "/EmployeePhoto/EmployeePhoto", + "/EmployeePhoto/UpdateWorkerPhoto", + "/EnergyManagement/InsertEnergyManagementInfo", + "/Login/RefreshCSRFToken", + "/NavBar/AddNavBar", + "/NavBar/DeleteNavBar", + "/NavBar/NavBarList", + "/NavBar/UpdateNavBar", + "/News/AddNews", + "/News/DeleteNews", + "/News/News", + "/News/SelectNews", + "/News/UpdateNews", + "/Notice/InsertNotice", + "/Notice/SelectNoticeAll", + "/Notice/SelectNoticeByNoticeNo", + "/PromotionContent/SelectPromotionContents", + "/RewardPunishment/AddRewardPunishment", + "/Role/ReadRolePermissions", + "/Room/DayByRoomNo", + "/Room/SelectCanUseRoomAllByRoomState", + "/Room/SelectFixingRoomAllByRoomState", + "/Room/SelectNotClearRoomAllByRoomState", + "/Room/SelectNotUseRoomAllByRoomState", + "/Room/SelectReservedRoomAllByRoomState", + "/Room/SelectRoomByRoomNo", + "/Room/SelectRoomByRoomPrice", + "/Room/SelectRoomByRoomState", + "/Room/SelectRoomByTypeName", + "/Room/UpdateRoomInfoWithReser", + "/Room/UpdateRoomStateByRoomNo", + "/RoomType/SelectRoomTypeByRoomNo", + "/Sellthing/SelectSellThingByNameAndPrice", + "/Spend/SelectSpendByRoomNo", + "/Spend/SeletHistorySpendInfoAll", + "/Spend/SumConsumptionAmount", + "/Utility/AddLog", + "/Utility/DeleteRequestlogByRange", + "/VipRule/SelectVipRule" + }; + + public void Apply(ApplicationModel application) + { + foreach (var controller in application.Controllers) + { + foreach (var action in controller.Actions) + { + action.ApiExplorer.GroupName = ResolveGroupName(controller.ControllerName, action.ActionName); + } + } + } + + private static string ResolveGroupName(string controllerName, string actionName) + { + if (MobileControllers.Contains(controllerName)) + { + return ClientApiGroups.Mobile; + } + + var endpoint = $"/{controllerName}/{actionName}"; + return DesktopEndpoints.Contains(endpoint) ? ClientApiGroups.Desktop : ClientApiGroups.Web; + } + } +} diff --git a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs index 083b0c1..0a79b85 100644 --- a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs @@ -255,10 +255,14 @@ namespace EOM.TSHotelManagement.WebApi public static void ConfigureControllers(this IServiceCollection services) { + services.AddScoped(); + services.AddControllers(options => { options.Filters.Add(); + options.Filters.Add(); options.Conventions.Add(new AuthorizeAllControllersConvention()); + options.Conventions.Add(new ClientApiGroupConvention()); options.RespectBrowserAcceptHeader = true; options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true; }).AddJsonOptions(options => @@ -302,6 +306,73 @@ namespace EOM.TSHotelManagement.WebApi config.Title = "TS酒店管理系统API说明文档"; config.Version = "v1"; config.DocumentName = "v1"; + config.ApiGroupNames = ClientApiGroups.All; + + config.OperationProcessors.Add(new CSRFTokenOperationProcessor()); + + config.AddSecurity("JWT", new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.Http, + In = OpenApiSecurityApiKeyLocation.Header, + Name = "Authorization", + Description = "Type into the textbox: your JWT token", + Scheme = "bearer", + BearerFormat = "JWT" + }); + + config.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); + }); + + services.AddOpenApiDocument(config => + { + config.Title = "TS Hotel Management System API - Web"; + config.Version = ClientApiGroups.Web; + config.DocumentName = ClientApiGroups.Web; + config.ApiGroupNames = new[] { ClientApiGroups.Web }; + + config.OperationProcessors.Add(new CSRFTokenOperationProcessor()); + + config.AddSecurity("JWT", new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.Http, + In = OpenApiSecurityApiKeyLocation.Header, + Name = "Authorization", + Description = "Type into the textbox: your JWT token", + Scheme = "bearer", + BearerFormat = "JWT" + }); + + config.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); + }); + + services.AddOpenApiDocument(config => + { + config.Title = "TS Hotel Management System API - Desktop"; + config.Version = ClientApiGroups.Desktop; + config.DocumentName = ClientApiGroups.Desktop; + config.ApiGroupNames = new[] { ClientApiGroups.Desktop }; + + config.OperationProcessors.Add(new CSRFTokenOperationProcessor()); + + config.AddSecurity("JWT", new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.Http, + In = OpenApiSecurityApiKeyLocation.Header, + Name = "Authorization", + Description = "Type into the textbox: your JWT token", + Scheme = "bearer", + BearerFormat = "JWT" + }); + + config.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); + }); + + services.AddOpenApiDocument(config => + { + config.Title = "TS Hotel Management System API - Mobile"; + config.Version = ClientApiGroups.Mobile; + config.DocumentName = ClientApiGroups.Mobile; + config.ApiGroupNames = new[] { ClientApiGroups.Mobile }; config.OperationProcessors.Add(new CSRFTokenOperationProcessor()); diff --git a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs new file mode 100644 index 0000000..4b0a211 --- /dev/null +++ b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs @@ -0,0 +1,410 @@ +using EOM.TSHotelManagement.Common; +using EOM.TSHotelManagement.Contract; +using EOM.TSHotelManagement.Data; +using EOM.TSHotelManagement.Domain; +using jvncorelib.CodeLib; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace EOM.TSHotelManagement.WebApi.Filters +{ + public class BusinessOperationAuditFilter : IAsyncActionFilter + { + private static readonly HashSet ExcludedControllers = new(StringComparer.OrdinalIgnoreCase) + { + "Login", + "Utility", + "CustomerAccount", + "News" + }; + + private static readonly string[] ReadOnlyActionPrefixes = + { + "Select", + "Read", + "Get", + "Build" + }; + + private static readonly string[] SensitivePropertyKeywords = + { + "password", + "token", + "secret", + "recoverycode", + "verificationcode", + "otp" + }; + + private readonly GenericRepository operationLogRepository; + private readonly ILogger logger; + + public BusinessOperationAuditFilter( + GenericRepository operationLogRepository, + ILogger logger) + { + this.operationLogRepository = operationLogRepository; + this.logger = logger; + } + + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + if (!ShouldAudit(context)) + { + await next(); + return; + } + + var executedContext = await next(); + await TryWriteAuditLogAsync(context, executedContext); + } + + private static bool ShouldAudit(ActionExecutingContext context) + { + if (context.ActionDescriptor is not ControllerActionDescriptor actionDescriptor) + { + return false; + } + + if (!IsBusinessController(actionDescriptor)) + { + return false; + } + + if (ExcludedControllers.Contains(actionDescriptor.ControllerName)) + { + return false; + } + + if (HttpMethods.IsGet(context.HttpContext.Request.Method) + || HttpMethods.IsHead(context.HttpContext.Request.Method) + || HttpMethods.IsOptions(context.HttpContext.Request.Method)) + { + return false; + } + + return !ReadOnlyActionPrefixes.Any(prefix => + actionDescriptor.ActionName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)); + } + + private static bool IsBusinessController(ControllerActionDescriptor actionDescriptor) + { + var controllerNamespace = actionDescriptor.ControllerTypeInfo.Namespace ?? string.Empty; + return controllerNamespace.Contains(".Controllers.Business.", StringComparison.OrdinalIgnoreCase); + } + + private async Task TryWriteAuditLogAsync(ActionExecutingContext context, ActionExecutedContext executedContext) + { + try + { + var request = context.HttpContext.Request; + var path = request.Path.HasValue ? request.Path.Value! : string.Empty; + var isChinese = IsChineseLanguage(context.HttpContext); + var operationAccount = ClaimsPrincipalExtensions.GetUserNumber(context.HttpContext.User); + if (string.IsNullOrWhiteSpace(operationAccount)) + { + operationAccount = Localize(isChinese, "Anonymous", "匿名用户"); + } + + var (isSuccess, responseCode, responseMessage) = ResolveExecutionResult(executedContext); + var argumentSummary = BuildArgumentSummary(context.ActionArguments, isChinese); + var statusText = Localize(isChinese, isSuccess ? "Success" : "Failed", isSuccess ? "成功" : "失败"); + var logContent = BuildLogContent( + isChinese, + statusText, + request.Method, + path, + operationAccount, + argumentSummary, + responseCode, + responseMessage); + + var operationLog = new OperationLog + { + OperationId = new UniqueCode().GetNewId("OP-"), + OperationTime = DateTime.Now, + LogContent = logContent, + LoginIpAddress = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty, + OperationAccount = operationAccount, + LogLevel = isSuccess ? (int)Common.LogLevel.Normal : (int)Common.LogLevel.Warning, + SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), + DataInsUsr = operationAccount, + DataInsDate = DateTime.Now + }; + + operationLogRepository.Insert(operationLog); + } + catch (Exception ex) + { + logger.LogWarning(ex, "Failed to write business operation audit log for {Path}", context.HttpContext.Request.Path); + } + + await Task.CompletedTask; + } + + private static string BuildLogContent( + bool isChinese, + string statusText, + string method, + string path, + string operationAccount, + string argumentSummary, + int responseCode, + string responseMessage) + { + var localizedResponseMessage = string.IsNullOrWhiteSpace(responseMessage) + ? Localize(isChinese, "None", "无") + : responseMessage; + + var content = Localize( + isChinese, + $"{statusText} {method} {path} | User={operationAccount} | Args={argumentSummary} | ResponseCode={responseCode} | Message={localizedResponseMessage}", + $"{statusText} {method} {path} | 操作人={operationAccount} | 参数={argumentSummary} | 响应码={responseCode} | 响应信息={localizedResponseMessage}"); + + return TrimLogContent(content, isChinese); + } + + private static (bool IsSuccess, int ResponseCode, string ResponseMessage) ResolveExecutionResult(ActionExecutedContext executedContext) + { + if (executedContext.Exception != null && !executedContext.ExceptionHandled) + { + return (false, BusinessStatusCode.InternalServerError, executedContext.Exception.Message); + } + + var baseResponse = ExtractBaseResponse(executedContext.Result); + if (baseResponse != null) + { + return (baseResponse.Success, baseResponse.Code, baseResponse.Message ?? string.Empty); + } + + if (executedContext.Result is StatusCodeResult statusCodeResult) + { + return (statusCodeResult.StatusCode < 400, statusCodeResult.StatusCode, string.Empty); + } + + return (true, 0, string.Empty); + } + + private static BaseResponse ExtractBaseResponse(IActionResult result) + { + return result switch + { + ObjectResult objectResult when objectResult.Value is BaseResponse baseResponse => baseResponse, + JsonResult jsonResult when jsonResult.Value is BaseResponse baseResponse => baseResponse, + _ => null + }; + } + + private static string BuildArgumentSummary(IDictionary arguments, bool isChinese) + { + if (arguments == null || arguments.Count == 0) + { + return Localize(isChinese, "None", "无"); + } + + var items = arguments + .Where(a => a.Value != null) + .Select(a => $"{a.Key}={SummarizeValue(a.Key, a.Value, isChinese)}") + .Where(a => !string.IsNullOrWhiteSpace(a)) + .ToList(); + + return items.Count == 0 ? Localize(isChinese, "None", "无") : string.Join("; ", items); + } + + private static string SummarizeValue(string name, object value, bool isChinese) + { + if (value == null) + { + return Localize(isChinese, "null", "空"); + } + + if (IsSensitive(name)) + { + return "***"; + } + + if (value is IFormFile file) + { + return Localize( + isChinese, + $"File({file.FileName}, {file.Length} bytes)", + $"文件({file.FileName}, {file.Length} 字节)"); + } + + if (IsSimpleValue(value.GetType())) + { + return FormatSimpleValue(value); + } + + if (value is IEnumerable enumerable && value is not string) + { + return SummarizeEnumerable(enumerable, isChinese); + } + + return SummarizeComplexObject(value, isChinese); + } + + private static string SummarizeEnumerable(IEnumerable enumerable, bool isChinese) + { + var count = 0; + var previews = new List(); + + foreach (var item in enumerable) + { + count++; + if (previews.Count >= 3) + { + continue; + } + + previews.Add(item == null ? "null" : FormatSimpleValue(item)); + } + + return previews.Count == 0 + ? "[]" + : Localize( + isChinese, + $"[{string.Join(", ", previews)}{(count > previews.Count ? ", ..." : string.Empty)}] (Count={count})", + $"[{string.Join(", ", previews)}{(count > previews.Count ? ", ..." : string.Empty)}](数量={count})"); + } + + private static string SummarizeComplexObject(object value, bool isChinese) + { + var properties = value.GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public) + .Where(p => p.CanRead && p.GetIndexParameters().Length == 0) + .Take(8) + .Select(p => + { + object propertyValue; + try + { + propertyValue = p.GetValue(value); + } + catch + { + return null; + } + + if (propertyValue == null) + { + return null; + } + + if (IsSensitive(p.Name)) + { + return $"{p.Name}=***"; + } + + if (propertyValue is IFormFile file) + { + return Localize( + isChinese, + $"{p.Name}=File({file.FileName}, {file.Length} bytes)", + $"{p.Name}=文件({file.FileName}, {file.Length} 字节)"); + } + + if (IsSimpleValue(propertyValue.GetType())) + { + return $"{p.Name}={FormatSimpleValue(propertyValue)}"; + } + + if (propertyValue is IEnumerable enumerable && propertyValue is not string) + { + return $"{p.Name}={SummarizeEnumerable(enumerable, isChinese)}"; + } + + return null; + }) + .Where(s => !string.IsNullOrWhiteSpace(s)) + .ToList(); + + return properties.Count == 0 + ? value.GetType().Name + : $"{value.GetType().Name}({string.Join(", ", properties)})"; + } + + private static bool IsSimpleValue(Type type) + { + var actualType = Nullable.GetUnderlyingType(type) ?? type; + return actualType.IsPrimitive + || actualType.IsEnum + || actualType == typeof(string) + || actualType == typeof(decimal) + || actualType == typeof(Guid) + || actualType == typeof(DateTime) + || actualType == typeof(DateTimeOffset) + || actualType == typeof(TimeSpan); + } + + private static bool IsSensitive(string name) + { + var normalized = name?.Replace("_", string.Empty, StringComparison.OrdinalIgnoreCase) ?? string.Empty; + return SensitivePropertyKeywords.Any(keyword => + normalized.Contains(keyword, StringComparison.OrdinalIgnoreCase)); + } + + private static string FormatSimpleValue(object value) + { + var formatted = value switch + { + DateTime dateTime => dateTime.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), + DateTimeOffset dateTimeOffset => dateTimeOffset.ToString("yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture), + string text => text, + _ => Convert.ToString(value, CultureInfo.InvariantCulture) ?? value.ToString() ?? string.Empty + }; + + return formatted.Length <= 120 ? formatted : formatted[..117] + "..."; + } + + private static string TrimLogContent(string content, bool isChinese) + { + if (string.IsNullOrWhiteSpace(content)) + { + return Localize(isChinese, "Operation audit log", "业务操作审计日志"); + } + + return content.Length <= 1900 ? content : content[..1897] + "..."; + } + + private static bool IsChineseLanguage(HttpContext httpContext) + { + var acceptLanguage = httpContext.Request.Headers.AcceptLanguage.ToString(); + if (!string.IsNullOrWhiteSpace(acceptLanguage)) + { + var firstLanguage = acceptLanguage + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(item => item.Split(';', 2, StringSplitOptions.TrimEntries)[0]) + .FirstOrDefault(); + + if (!string.IsNullOrWhiteSpace(firstLanguage)) + { + return firstLanguage.StartsWith("zh", StringComparison.OrdinalIgnoreCase); + } + } + + var cultureName = CultureInfo.CurrentUICulture?.Name; + if (!string.IsNullOrWhiteSpace(cultureName)) + { + return cultureName.StartsWith("zh", StringComparison.OrdinalIgnoreCase); + } + + return false; + } + + private static string Localize(bool isChinese, string englishText, string chineseText) + { + return isChinese ? chineseText : englishText; + } + } +} diff --git a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs index 78f317f..a23f97f 100644 --- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs @@ -8,9 +8,8 @@ namespace EOM.TSHotelManagement.Contract public int? RoomId { get; set; } public string? RoomNumber { get; set; } - public DateOnly? StartDate { get; set; } + public DateTime? StartDate { get; set; } - public DateOnly? EndDate { get; set; } + public DateTime? EndDate { get; set; } } } - diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs index 8f328fe..2c634c6 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs @@ -37,6 +37,7 @@ namespace EOM.TSHotelManagement.Contract public string RoomNumber { get; set; } public string? RoomArea { get; set; } public int? RoomFloor { get; set; } + public string? PricingCode { get; set; } [Required(ErrorMessage = "预约编号为必填字段"), MaxLength(128, ErrorMessage = "预约编号长度不超过128字符")] public string ReservationId { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs index 47a131f..d7fc935 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs @@ -9,7 +9,8 @@ public int? RoomTypeId { get; set; } public int? RoomStateId { get; set; } public string? RoomName { get; set; } - public DateOnly? LastCheckInTime { get; set; } + public DateTime? LastCheckInTime { get; set; } public string? CustomerNumber { get; set; } + public string? PricingCode { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs index 5e8c8ae..1d7a3da 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomOutputDto.cs @@ -17,6 +17,18 @@ public string RoomState { get; set; } public decimal RoomRent { get; set; } public decimal RoomDeposit { get; set; } + public decimal StandardRoomRent { get; set; } + public decimal StandardRoomDeposit { get; set; } + public decimal AppliedRoomRent { get; set; } + public decimal AppliedRoomDeposit { get; set; } + public decimal EffectiveRoomRent { get; set; } + public decimal EffectiveRoomDeposit { get; set; } + public string EffectivePricingCode { get; set; } + public string EffectivePricingName { get; set; } + public string PricingCode { get; set; } + public string PricingName { get; set; } + public int? PricingStayHours { get; set; } + public bool IsPricingTimedOut { get; set; } public string RoomLocation { get; set; } public int StayDays { get; set; } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomPricingOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomPricingOutputDto.cs new file mode 100644 index 0000000..3175e3a --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomPricingOutputDto.cs @@ -0,0 +1,21 @@ +namespace EOM.TSHotelManagement.Contract +{ + public class ReadRoomPricingOutputDto + { + public int? RoomId { get; set; } + public string RoomNumber { get; set; } + public string RoomLocator { get; set; } + public int RoomTypeId { get; set; } + public string RoomTypeName { get; set; } + public string CurrentPricingCode { get; set; } + public string CurrentPricingName { get; set; } + public int? PricingStayHours { get; set; } + public bool IsPricingTimedOut { get; set; } + public string EffectivePricingCode { get; set; } + public string EffectivePricingName { get; set; } + public DateTime? LastCheckInTime { get; set; } + public decimal EffectiveRoomRent { get; set; } + public decimal EffectiveRoomDeposit { get; set; } + public List PricingItems { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs index 3bb5273..a9e3142 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs @@ -8,13 +8,12 @@ namespace EOM.TSHotelManagement.Contract public int? RoomFloor { get; set; } public int RoomTypeId { get; set; } public string CustomerNumber { get; set; } - public DateOnly? LastCheckInTime { get; set; } - public DateOnly? LastCheckOutTime { get; set; } + public DateTime? LastCheckInTime { get; set; } + public DateTime? LastCheckOutTime { get; set; } public int RoomStateId { get; set; } public decimal RoomRent { get; set; } public decimal RoomDeposit { get; set; } public string RoomLocation { get; set; } + public string? PricingCode { get; set; } } } - - diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/CreateRoomTypeInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/CreateRoomTypeInputDto.cs index 0b43976..51c33bb 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/CreateRoomTypeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/CreateRoomTypeInputDto.cs @@ -6,6 +6,7 @@ namespace EOM.TSHotelManagement.Contract public string RoomTypeName { get; set; } public decimal RoomRent { get; set; } public decimal RoomDeposit { get; set; } + public List? PricingItems { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeOutputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeOutputDto.cs index cdf0356..cb72734 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeOutputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/ReadRoomTypeOutputDto.cs @@ -7,6 +7,7 @@ public string RoomTypeName { get; set; } public decimal RoomRent { get; set; } public decimal RoomDeposit { get; set; } + public List? PricingItems { get; set; } } } diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/RoomTypePricingItemDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/RoomTypePricingItemDto.cs new file mode 100644 index 0000000..d30fb97 --- /dev/null +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/RoomTypePricingItemDto.cs @@ -0,0 +1,13 @@ +namespace EOM.TSHotelManagement.Contract +{ + public class RoomTypePricingItemDto + { + public string PricingCode { get; set; } + public string PricingName { get; set; } + public decimal RoomRent { get; set; } + public decimal RoomDeposit { get; set; } + public int? StayHours { get; set; } + public int Sort { get; set; } + public bool IsDefault { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/UpdateRoomTypeInputDto.cs b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/UpdateRoomTypeInputDto.cs index 075b67d..18896fd 100644 --- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/UpdateRoomTypeInputDto.cs +++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/RoomType/UpdateRoomTypeInputDto.cs @@ -6,6 +6,7 @@ namespace EOM.TSHotelManagement.Contract public string RoomTypeName { get; set; } public decimal RoomRent { get; set; } public decimal RoomDeposit { get; set; } + public List? PricingItems { get; set; } } } diff --git a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs index 708631d..5e931f8 100644 --- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs +++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs @@ -102,9 +102,6 @@ namespace EOM.TSHotelManagement.Data .ToArray(); db.CodeFirst.InitTables(needCreateTableTypes); - EnsureRoomSchema(db); - EnsureRoomLocationColumn(db); - EnsureRoomLocatorUniqueIndex(db); Console.WriteLine("Database schema initialized"); @@ -261,229 +258,6 @@ namespace EOM.TSHotelManagement.Data return configString; } - private void EnsureRoomSchema(ISqlSugarClient db) - { - EnsureColumn(db, "room", "room_area", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_area` varchar(128) NULL", - [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_area` varchar(128) NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_area\" varchar(128)", - [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_area] nvarchar(128) NULL", - [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_area TEXT NULL" - }); - - EnsureColumn(db, "room", "room_floor", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_floor` int NULL", - [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_floor` int NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_floor\" integer", - [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_floor] int NULL", - [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_floor INTEGER NULL" - }); - - EnsureColumn(db, "reser", "room_id", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `reser` ADD COLUMN `room_id` int NULL", - [DbType.MySqlConnector] = "ALTER TABLE `reser` ADD COLUMN `room_id` int NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"reser\" ADD COLUMN \"room_id\" integer", - [DbType.SqlServer] = "ALTER TABLE [reser] ADD [room_id] int NULL", - [DbType.Sqlite] = "ALTER TABLE reser ADD COLUMN room_id INTEGER NULL" - }); - - EnsureColumn(db, "customer_spend", "room_id", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `customer_spend` ADD COLUMN `room_id` int NULL", - [DbType.MySqlConnector] = "ALTER TABLE `customer_spend` ADD COLUMN `room_id` int NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"customer_spend\" ADD COLUMN \"room_id\" integer", - [DbType.SqlServer] = "ALTER TABLE [customer_spend] ADD [room_id] int NULL", - [DbType.Sqlite] = "ALTER TABLE customer_spend ADD COLUMN room_id INTEGER NULL" - }); - - EnsureColumn(db, "energy_management", "room_id", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `energy_management` ADD COLUMN `room_id` int NULL", - [DbType.MySqlConnector] = "ALTER TABLE `energy_management` ADD COLUMN `room_id` int NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"energy_management\" ADD COLUMN \"room_id\" integer", - [DbType.SqlServer] = "ALTER TABLE [energy_management] ADD [room_id] int NULL", - [DbType.Sqlite] = "ALTER TABLE energy_management ADD COLUMN room_id INTEGER NULL" - }); - } - - private void EnsureRoomLocationColumn(ISqlSugarClient db) - { - if (!ColumnExists(db, "room", "room_location")) - { - EnsureColumn(db, "room", "room_location", new Dictionary - { - [DbType.MySql] = "ALTER TABLE `room` ADD COLUMN `room_location` varchar(200) NULL", - [DbType.MySqlConnector] = "ALTER TABLE `room` ADD COLUMN `room_location` varchar(200) NULL", - [DbType.PostgreSQL] = "ALTER TABLE \"room\" ADD COLUMN \"room_location\" varchar(200)", - [DbType.SqlServer] = "ALTER TABLE [room] ADD [room_location] nvarchar(200) NULL", - [DbType.Sqlite] = "ALTER TABLE room ADD COLUMN room_location TEXT NULL" - }); - } - - DropColumnIfExists(db, "room", "room_position"); - } - - private void EnsureRoomLocatorUniqueIndex(ISqlSugarClient db) - { - const string indexName = "UK_room_room_no_area_floor"; - if (IndexExists(db, "room", indexName)) - { - return; - } - - if (HasDuplicateRoomLocator(db)) - { - Console.WriteLine($"Skip creating unique index {indexName} because duplicate room locator data already exists."); - return; - } - - var sql = db.CurrentConnectionConfig.DbType switch - { - DbType.MySql or DbType.MySqlConnector => - $"CREATE UNIQUE INDEX `{indexName}` ON `room` (`room_no`, `room_area`, `room_floor`)", - DbType.PostgreSQL => - $"CREATE UNIQUE INDEX IF NOT EXISTS \"{indexName}\" ON \"room\" (\"room_no\", \"room_area\", \"room_floor\")", - DbType.SqlServer => - $"CREATE UNIQUE INDEX [{indexName}] ON [room] ([room_no], [room_area], [room_floor])", - DbType.Sqlite => - $"CREATE UNIQUE INDEX IF NOT EXISTS {indexName} ON room (room_no, room_area, room_floor)", - _ => string.Empty - }; - - if (string.IsNullOrWhiteSpace(sql)) - { - Console.WriteLine($"Skip unique index patch for unsupported DbType {db.CurrentConnectionConfig.DbType} on room locator."); - return; - } - - db.Ado.ExecuteCommand(sql); - } - - private void EnsureColumn(ISqlSugarClient db, string tableName, string columnName, IReadOnlyDictionary sqlMap) - { - if (ColumnExists(db, tableName, columnName)) - { - return; - } - - if (!sqlMap.TryGetValue(db.CurrentConnectionConfig.DbType, out var sql)) - { - Console.WriteLine($"Skip schema patch for unsupported DbType {db.CurrentConnectionConfig.DbType} on {tableName}.{columnName}"); - return; - } - - db.Ado.ExecuteCommand(sql); - } - - private bool IndexExists(ISqlSugarClient db, string tableName, string indexName) - { - var dbType = db.CurrentConnectionConfig.DbType; - string sql = dbType switch - { - DbType.MySql or DbType.MySqlConnector => - "SELECT COUNT(1) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = @tableName AND index_name = @indexName", - DbType.PostgreSQL => - "SELECT COUNT(1) FROM pg_indexes WHERE schemaname = current_schema() AND tablename = @tableName AND indexname = @indexName", - DbType.SqlServer => - "SELECT COUNT(1) FROM sys.indexes WHERE object_id = OBJECT_ID(@tableName) AND name = @indexName", - DbType.Sqlite => - $"SELECT COUNT(1) FROM pragma_index_list('{tableName}') WHERE name = @indexName", - _ => string.Empty - }; - - if (string.IsNullOrEmpty(sql)) - { - return true; - } - - return db.Ado.GetInt(sql, new List - { - new SugarParameter("@tableName", tableName), - new SugarParameter("@indexName", indexName) - }) > 0; - } - - private bool HasDuplicateRoomLocator(ISqlSugarClient db) - { - var sql = db.CurrentConnectionConfig.DbType switch - { - DbType.MySql or DbType.MySqlConnector => - "SELECT COUNT(1) FROM (SELECT `room_no`, COALESCE(`room_area`, ''), COALESCE(`room_floor`, -1) FROM `room` GROUP BY `room_no`, COALESCE(`room_area`, ''), COALESCE(`room_floor`, -1) HAVING COUNT(1) > 1) t", - DbType.PostgreSQL => - "SELECT COUNT(1) FROM (SELECT \"room_no\", COALESCE(\"room_area\", ''), COALESCE(\"room_floor\", -1) FROM \"room\" GROUP BY \"room_no\", COALESCE(\"room_area\", ''), COALESCE(\"room_floor\", -1) HAVING COUNT(1) > 1) t", - DbType.SqlServer => - "SELECT COUNT(1) FROM (SELECT [room_no], COALESCE([room_area], ''), COALESCE([room_floor], -1) FROM [room] GROUP BY [room_no], COALESCE([room_area], ''), COALESCE([room_floor], -1) HAVING COUNT(1) > 1) t", - DbType.Sqlite => - "SELECT COUNT(1) FROM (SELECT room_no, COALESCE(room_area, ''), COALESCE(room_floor, -1) FROM room GROUP BY room_no, COALESCE(room_area, ''), COALESCE(room_floor, -1) HAVING COUNT(1) > 1) t", - _ => string.Empty - }; - - if (string.IsNullOrWhiteSpace(sql)) - { - return false; - } - - return db.Ado.GetInt(sql) > 0; - } - - private void DropColumnIfExists(ISqlSugarClient db, string tableName, string columnName) - { - if (!ColumnExists(db, tableName, columnName)) - { - return; - } - - var sql = db.CurrentConnectionConfig.DbType switch - { - DbType.MySql or DbType.MySqlConnector => - $"ALTER TABLE `{tableName}` DROP COLUMN `{columnName}`", - DbType.PostgreSQL => - $"ALTER TABLE \"{tableName}\" DROP COLUMN IF EXISTS \"{columnName}\"", - DbType.SqlServer => - $"ALTER TABLE [{tableName}] DROP COLUMN [{columnName}]", - _ => string.Empty - }; - - if (string.IsNullOrWhiteSpace(sql)) - { - Console.WriteLine($"Skip dropping column {tableName}.{columnName} for unsupported DbType {db.CurrentConnectionConfig.DbType}."); - return; - } - - db.Ado.ExecuteCommand(sql); - } - - private bool ColumnExists(ISqlSugarClient db, string tableName, string columnName) - { - var dbType = db.CurrentConnectionConfig.DbType; - string sql = dbType switch - { - DbType.MySql or DbType.MySqlConnector => - "SELECT COUNT(1) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = @tableName AND column_name = @columnName", - DbType.PostgreSQL => - "SELECT COUNT(1) FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = @tableName AND column_name = @columnName", - DbType.SqlServer => - "SELECT COUNT(1) FROM information_schema.columns WHERE table_name = @tableName AND column_name = @columnName", - DbType.Sqlite => - $"SELECT COUNT(1) FROM pragma_table_info('{tableName}') WHERE name = @columnName", - _ => string.Empty - }; - - if (string.IsNullOrEmpty(sql)) - { - return true; - } - - return db.Ado.GetInt(sql, new List - { - new SugarParameter("@tableName", tableName), - new SugarParameter("@columnName", columnName) - }) > 0; - } - private void SeedInitialData(ISqlSugarClient db) { Console.WriteLine("Initializing database data..."); diff --git a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs index 78062a0..32c2891 100644 --- a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs +++ b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs @@ -58,13 +58,13 @@ namespace EOM.TSHotelManagement.Domain /// 开始使用时间 (Start Date) ///
[SqlSugar.SugarColumn(ColumnName = "use_date", IsNullable = false, ColumnDescription = "开始使用时间 (Start Date)")] - public DateOnly StartDate { get; set; } + public DateTime StartDate { get; set; } /// /// 结束使用时间 (End Date) /// [SqlSugar.SugarColumn(ColumnName = "end_date", IsNullable = false, ColumnDescription = "结束使用时间 (End Date)")] - public DateOnly EndDate { get; set; } + public DateTime EndDate { get; set; } /// /// 水费 (Water Usage) diff --git a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs index 286940d..00ca7b2 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs @@ -14,7 +14,7 @@ namespace EOM.TSHotelManagement.Domain ColumnDescription = "Room number", IsNullable = false, Length = 128, - UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } + UniqueGroupNameList = new[] { "UK_room_number_area_floor" } )] public string RoomNumber { get; set; } @@ -23,7 +23,7 @@ namespace EOM.TSHotelManagement.Domain ColumnDescription = "Room area", IsNullable = true, Length = 128, - UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } + UniqueGroupNameList = new[] { "UK_room_number_area_floor" } )] public string RoomArea { get; set; } @@ -31,7 +31,7 @@ namespace EOM.TSHotelManagement.Domain ColumnName = "room_floor", ColumnDescription = "Room floor", IsNullable = true, - UniqueGroupNameList = new[] { "UK_room_room_no_area_floor" } + UniqueGroupNameList = new[] { "UK_room_number_area_floor" } )] public int? RoomFloor { get; set; } @@ -58,14 +58,14 @@ namespace EOM.TSHotelManagement.Domain ColumnDescription = "Last check-in time", IsNullable = true )] - public DateOnly? LastCheckInTime { get; set; } + public DateTime? LastCheckInTime { get; set; } [SugarColumn( ColumnName = "check_out_time", ColumnDescription = "Last check-out time", IsNullable = true )] - public DateOnly LastCheckOutTime { get; set; } + public DateTime? LastCheckOutTime { get; set; } [SugarColumn( ColumnName = "room_state_id", @@ -94,6 +94,54 @@ namespace EOM.TSHotelManagement.Domain )] public decimal RoomDeposit { get; set; } + [SugarColumn( + ColumnName = "applied_room_rent", + ColumnDescription = "Applied room rent for current stay", + IsNullable = false, + DecimalDigits = 2, + DefaultValue = "0.00" + )] + public decimal AppliedRoomRent { get; set; } + + [SugarColumn( + ColumnName = "applied_room_deposit", + ColumnDescription = "Applied room deposit for current stay", + IsNullable = false, + DecimalDigits = 2, + DefaultValue = "0.00" + )] + public decimal AppliedRoomDeposit { get; set; } + + [SugarColumn( + ColumnName = "pricing_code", + ColumnDescription = "Applied pricing code", + IsNullable = true, + Length = 64 + )] + public string RoomPricingCode { get; set; } + + [SugarColumn( + ColumnName = "pricing_name", + ColumnDescription = "Applied pricing name", + IsNullable = true, + Length = 128 + )] + public string RoomPricingName { get; set; } + + [SugarColumn( + ColumnName = "pricing_stay_hours", + ColumnDescription = "Applied pricing allowed stay hours", + IsNullable = true + )] + public int? PricingStayHours { get; set; } + + [SugarColumn( + ColumnName = "pricing_start_time", + ColumnDescription = "Applied pricing timing start time", + IsNullable = true + )] + public DateTime? PricingStartTime { get; set; } + [SugarColumn( ColumnName = "room_location", ColumnDescription = "Room location", diff --git a/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs b/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs index 95c2f32..3812a5f 100644 --- a/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs +++ b/EOM.TSHotelManagement.Domain/Business/Room/RoomType.cs @@ -90,6 +90,14 @@ namespace EOM.TSHotelManagement.Domain public decimal RoomDeposit { get; set; } + [SugarColumn( + ColumnName = "pricing_items_json", + ColumnDataType = "text", + IsNullable = true, + ColumnDescription = "Additional Pricing Items JSON" + )] + public string PricingItemsJson { get; set; } + /// /// 删除标记描述 (Delete Mark Description)(不存储到数据库) /// diff --git a/EOM.TSHotelManagement.Infrastructure/Constant/CodeConstantBase.cs b/EOM.TSHotelManagement.Infrastructure/Constant/CodeConstantBase.cs index 9da8006..f9e2bd6 100644 --- a/EOM.TSHotelManagement.Infrastructure/Constant/CodeConstantBase.cs +++ b/EOM.TSHotelManagement.Infrastructure/Constant/CodeConstantBase.cs @@ -5,7 +5,7 @@ public string Code { get; } public string Description { get; } - private static List _constants = new List(); + private static readonly List _constants = new List(); protected CodeConstantBase(string code, string description) { @@ -16,25 +16,64 @@ public static IEnumerable GetAll() { + EnsureInitialized(); return _constants; } public static string GetDescriptionByCode(string code) { - var constant = _constants.SingleOrDefault(c => c.Code == code); - return constant?.Description ?? string.Empty; + return GetConstantByCode(code)?.Description ?? string.Empty; } public static string GetCodeByDescription(string description) { - var constant = _constants.SingleOrDefault(c => c.Description == description); - return constant?.Code ?? string.Empty; + return GetConstantByDescription(description)?.Code ?? string.Empty; } public static T? GetConstantByCode(string code) { - var constant = _constants.FirstOrDefault(c => c.Code == code); - return constant ?? null; + EnsureInitialized(); + var normalizedCode = NormalizeValue(code); + if (string.IsNullOrWhiteSpace(normalizedCode)) + { + return null; + } + + return _constants.FirstOrDefault(c => string.Equals(c.Code, normalizedCode, StringComparison.OrdinalIgnoreCase)); + } + + public static T? GetConstantByDescription(string description) + { + EnsureInitialized(); + var normalizedDescription = NormalizeValue(description); + if (string.IsNullOrWhiteSpace(normalizedDescription)) + { + return null; + } + + return _constants.FirstOrDefault(c => string.Equals(c.Description, normalizedDescription, StringComparison.OrdinalIgnoreCase)); + } + + public static bool TryGetDescriptionByCode(string code, out string description) + { + description = GetDescriptionByCode(code); + return !string.IsNullOrWhiteSpace(description); + } + + public static bool TryGetCodeByDescription(string description, out string code) + { + code = GetCodeByDescription(description); + return !string.IsNullOrWhiteSpace(code); + } + + private static string NormalizeValue(string value) + { + return value?.Trim() ?? string.Empty; + } + + private static void EnsureInitialized() + { + System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); } } } diff --git a/EOM.TSHotelManagement.Migration/EntityBuilder.cs b/EOM.TSHotelManagement.Migration/EntityBuilder.cs index 0b666c7..01aa42a 100644 --- a/EOM.TSHotelManagement.Migration/EntityBuilder.cs +++ b/EOM.TSHotelManagement.Migration/EntityBuilder.cs @@ -866,7 +866,7 @@ namespace EOM.TSHotelManagement.Migration // 员工履历管理 new Permission { PermissionNumber = "staffmanagement.shbei", PermissionName = "根据工号查询履历信息", Module = "humanresource", Description = "根据工号查询履历信息", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.ahbei", PermissionName = "根据工号添加员工履历", Module = "humanresource", Description = "根据工号添加员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, - new Permission { PermissionNumber = "staffmanagement.uhbei", PermissionName = "根据工号更新员工履历", Module = "humanresource", Description = "根据工号更新员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, + new Permission { PermissionNumber = "staffmanagement.update", PermissionName = "根据工号更新员工履历", Module = "humanresource", Description = "根据工号更新员工履历", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, // 员工打卡管理 new Permission { PermissionNumber = "staffmanagement.stcfobwn", PermissionName = "查询今天员工是否已签到", Module = "humanresource", Description = "查询今天员工是否已签到", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, new Permission { PermissionNumber = "staffmanagement.swcdsbei", PermissionName = "查询员工签到天数", Module = "humanresource", Description = "查询员工签到天数", MenuKey = "staffmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now }, diff --git a/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs b/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs index 72a8467..f01101f 100644 --- a/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs +++ b/EOM.TSHotelManagement.Service/Business/EnergyManagement/EnergyManagementService.cs @@ -90,8 +90,8 @@ namespace EOM.TSHotelManagement.Service entity.InformationId = input.InformationNumber; entity.RoomId = roomResult.Room.Id; entity.RoomNumber = roomResult.Room.RoomNumber; - entity.StartDate = DateOnly.FromDateTime(input.StartDate); - entity.EndDate = DateOnly.FromDateTime(input.EndDate); + entity.StartDate = input.StartDate; + entity.EndDate = input.EndDate; wtiRepository.Insert(entity); return new BaseResponse(BusinessStatusCode.Success, "Insert energy management success."); @@ -122,8 +122,8 @@ namespace EOM.TSHotelManagement.Service entity.RoomId = roomResult.Room.Id; entity.RoomNumber = roomResult.Room.RoomNumber; entity.CustomerNumber = input.CustomerNumber; - entity.StartDate = DateOnly.FromDateTime(input.StartDate); - entity.EndDate = DateOnly.FromDateTime(input.EndDate); + entity.StartDate = input.StartDate; + entity.EndDate = input.EndDate; entity.PowerUsage = input.PowerUsage; entity.WaterUsage = input.WaterUsage; entity.Recorder = input.Recorder; @@ -186,8 +186,8 @@ namespace EOM.TSHotelManagement.Service RoomFloor = RoomReferenceHelper.GetRoomFloor(room), RoomLocator = RoomReferenceHelper.GetRoomLocator(room), CustomerNumber = source.CustomerNumber, - StartDate = source.StartDate.ToDateTime(TimeOnly.MinValue), - EndDate = source.EndDate.ToDateTime(TimeOnly.MinValue), + StartDate = source.StartDate, + EndDate = source.EndDate, PowerUsage = source.PowerUsage, WaterUsage = source.WaterUsage, Recorder = source.Recorder, diff --git a/EOM.TSHotelManagement.Service/Business/Room/IRoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/IRoomService.cs index 8930b2a..9ec1546 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/IRoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/IRoomService.cs @@ -123,6 +123,13 @@ namespace EOM.TSHotelManagement.Service object SelectRoomByRoomPrice(ReadRoomInputDto readRoomInputDto); #endregion + /// + /// 查询房间可用计价项 + /// + /// + /// + SingleOutputDto SelectRoomPricingOptions(ReadRoomInputDto readRoomInputDto); + #region 查询脏房数量 /// /// 查询脏房数量 @@ -205,4 +212,4 @@ namespace EOM.TSHotelManagement.Service #endregion } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomPricingEvaluation.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomPricingEvaluation.cs new file mode 100644 index 0000000..210b138 --- /dev/null +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomPricingEvaluation.cs @@ -0,0 +1,14 @@ +namespace EOM.TSHotelManagement.Service +{ + internal sealed class RoomPricingEvaluation + { + public string SelectedPricingCode { get; init; } + public string SelectedPricingName { get; init; } + public string EffectivePricingCode { get; init; } + public string EffectivePricingName { get; init; } + public decimal EffectiveRoomRent { get; init; } + public decimal EffectiveRoomDeposit { get; init; } + public int? PricingStayHours { get; init; } + public bool IsPricingTimedOut { get; init; } + } +} diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomPricingHelper.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomPricingHelper.cs new file mode 100644 index 0000000..bbb8b3d --- /dev/null +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomPricingHelper.cs @@ -0,0 +1,117 @@ +using EOM.TSHotelManagement.Contract; +using System.Text.Json; + +namespace EOM.TSHotelManagement.Service +{ + internal static class RoomPricingHelper + { + public const string DefaultPricingCode = "STANDARD"; + public const string DefaultPricingName = "标准价"; + + public static List BuildPricingItems(decimal roomRent, decimal roomDeposit, string pricingItemsJson) + { + var items = new List + { + CreateDefaultPricingItem(roomRent, roomDeposit) + }; + + items.AddRange(DeserializeAdditionalPricingItems(pricingItemsJson)); + return items; + } + + public static RoomTypePricingItemDto CreateDefaultPricingItem(decimal roomRent, decimal roomDeposit) + { + return new RoomTypePricingItemDto + { + PricingCode = DefaultPricingCode, + PricingName = DefaultPricingName, + RoomRent = roomRent, + RoomDeposit = roomDeposit, + Sort = 0, + IsDefault = true + }; + } + + public static string SerializeAdditionalPricingItems(IEnumerable? pricingItems) + { + var normalized = NormalizeAdditionalPricingItems(pricingItems).ToList(); + return normalized.Count == 0 ? "[]" : JsonSerializer.Serialize(normalized); + } + + public static RoomTypePricingItemDto? ResolvePricingItem(decimal roomRent, decimal roomDeposit, string pricingItemsJson, string? pricingCode) + { + var normalizedCode = NormalizePricingCode(pricingCode); + var items = BuildPricingItems(roomRent, roomDeposit, pricingItemsJson); + if (string.IsNullOrWhiteSpace(normalizedCode)) + { + return items.FirstOrDefault(); + } + + return items.FirstOrDefault(a => string.Equals(a.PricingCode, normalizedCode, StringComparison.OrdinalIgnoreCase)); + } + + public static string NormalizePricingCode(string? pricingCode) + { + return string.IsNullOrWhiteSpace(pricingCode) + ? string.Empty + : pricingCode.Trim().ToUpperInvariant(); + } + + private static List DeserializeAdditionalPricingItems(string pricingItemsJson) + { + if (string.IsNullOrWhiteSpace(pricingItemsJson)) + { + return new List(); + } + + try + { + var items = JsonSerializer.Deserialize>(pricingItemsJson) ?? new List(); + return NormalizeAdditionalPricingItems(items).ToList(); + } + catch + { + return new List(); + } + } + + private static IEnumerable NormalizeAdditionalPricingItems(IEnumerable? pricingItems) + { + if (pricingItems == null) + { + yield break; + } + + var seenCodes = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var item in pricingItems.OrderBy(a => a?.Sort ?? 0)) + { + if (item == null) + { + continue; + } + + var code = NormalizePricingCode(item.PricingCode); + if (string.IsNullOrWhiteSpace(code) || string.Equals(code, DefaultPricingCode, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + if (!seenCodes.Add(code)) + { + continue; + } + + yield return new RoomTypePricingItemDto + { + PricingCode = code, + PricingName = string.IsNullOrWhiteSpace(item.PricingName) ? code : item.PricingName.Trim(), + RoomRent = item.RoomRent, + RoomDeposit = item.RoomDeposit, + StayHours = item.StayHours > 0 ? item.StayHours : null, + Sort = item.Sort, + IsDefault = false + }; + } + } + } +} diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index dfab2fc..fee2f3c 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -88,9 +88,10 @@ namespace EOM.TSHotelManagement.Service return CreateRoomLookupFailureOutput(roomResult, roomInputDto?.RoomNumber, roomInputDto?.RoomArea, roomInputDto?.RoomFloor); } - if (roomResult.Room.LastCheckInTime.HasValue && roomResult.Room.LastCheckInTime.Value != DateOnly.MinValue) + var lastCheckInTime = NormalizeStayDateTime(roomResult.Room.LastCheckInTime); + if (lastCheckInTime.HasValue) { - var days = Math.Abs((roomResult.Room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - DateTime.Now).Days); + var days = CalculateStayDays(lastCheckInTime.Value, DateTime.Now); return new SingleOutputDto { Data = new ReadRoomOutputDto { StayDays = days } }; } @@ -110,7 +111,12 @@ namespace EOM.TSHotelManagement.Service var room = roomResult.Room; room.RoomStateId = r.RoomStateId; room.CustomerNumber = r.CustomerNumber; - room.LastCheckInTime = r.LastCheckInTime; + room.LastCheckInTime = NormalizeStayDateTime(r.LastCheckInTime); + var pricingResponse = ApplyPricingSelection(room, r.PricingCode); + if (pricingResponse != null) + { + return pricingResponse; + } room.DataChgDate = r.DataChgDate; room.DataChgUsr = r.DataChgUsr; room.RowVersion = r.RowVersion ?? 0; @@ -154,7 +160,111 @@ namespace EOM.TSHotelManagement.Service public object SelectRoomByRoomPrice(ReadRoomInputDto readRoomInputDto) { var roomResult = ResolveRoom(readRoomInputDto); - return roomResult.Room?.RoomRent ?? 0M; + if (roomResult.Room == null) + { + return 0M; + } + + if (string.IsNullOrWhiteSpace(readRoomInputDto?.PricingCode)) + { + return GetEffectiveRoomRent(roomResult.Room); + } + + var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == roomResult.Room.RoomTypeId && a.IsDelete != 1); + if (roomType == null) + { + return 0M; + } + + var pricingItem = RoomPricingHelper.ResolvePricingItem(roomType.RoomRent, roomType.RoomDeposit, roomType.PricingItemsJson, readRoomInputDto.PricingCode); + return pricingItem?.RoomRent ?? 0M; + } + + public SingleOutputDto SelectRoomPricingOptions(ReadRoomInputDto readRoomInputDto) + { + var roomResult = ResolveRoom(readRoomInputDto); + Room room = null; + RoomType roomType = null; + + if (roomResult.Room != null) + { + room = roomResult.Room; + roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId && a.IsDelete != 1); + } + else if (readRoomInputDto?.RoomTypeId > 0) + { + roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == readRoomInputDto.RoomTypeId && a.IsDelete != 1); + } + + if (roomType == null) + { + if (roomResult.IsAmbiguous) + { + return new SingleOutputDto + { + Code = BusinessStatusCode.Conflict, + Message = "Multiple rooms match the current room number.", + Data = new ReadRoomPricingOutputDto { PricingItems = new List() } + }; + } + + return new SingleOutputDto + { + Code = BusinessStatusCode.NotFound, + Message = "Room type pricing not found.", + Data = new ReadRoomPricingOutputDto { PricingItems = new List() } + }; + } + + var pricingItems = RoomPricingHelper.BuildPricingItems(roomType.RoomRent, roomType.RoomDeposit, roomType.PricingItemsJson); + if (room != null + && !string.IsNullOrWhiteSpace(room.RoomPricingCode) + && pricingItems.All(a => !string.Equals(a.PricingCode, room.RoomPricingCode, StringComparison.OrdinalIgnoreCase))) + { + pricingItems.Add(new RoomTypePricingItemDto + { + PricingCode = room.RoomPricingCode, + PricingName = string.IsNullOrWhiteSpace(room.RoomPricingName) ? room.RoomPricingCode : room.RoomPricingName, + RoomRent = room.AppliedRoomRent, + RoomDeposit = room.AppliedRoomDeposit, + StayHours = room.PricingStayHours, + IsDefault = false + }); + } + + var pricingEvaluation = room == null + ? new RoomPricingEvaluation + { + SelectedPricingCode = RoomPricingHelper.DefaultPricingCode, + SelectedPricingName = RoomPricingHelper.DefaultPricingName, + EffectivePricingCode = RoomPricingHelper.DefaultPricingCode, + EffectivePricingName = RoomPricingHelper.DefaultPricingName, + EffectiveRoomRent = roomType.RoomRent, + EffectiveRoomDeposit = roomType.RoomDeposit + } + : EvaluateRoomPricing(room); + + return new SingleOutputDto + { + Data = new ReadRoomPricingOutputDto + { + RoomId = room?.Id, + RoomNumber = room?.RoomNumber ?? string.Empty, + RoomLocator = room == null ? string.Empty : RoomLocatorHelper.BuildLocator(room.RoomArea, room.RoomFloor, room.RoomNumber), + RoomTypeId = roomType.RoomTypeId, + RoomTypeName = roomType.RoomTypeName, + CurrentPricingCode = pricingEvaluation.SelectedPricingCode, + CurrentPricingName = pricingEvaluation.SelectedPricingName, + PricingStayHours = pricingEvaluation.PricingStayHours, + IsPricingTimedOut = pricingEvaluation.IsPricingTimedOut, + EffectivePricingCode = pricingEvaluation.EffectivePricingCode, + EffectivePricingName = pricingEvaluation.EffectivePricingName, + LastCheckInTime = NormalizeStayDateTime(room?.LastCheckInTime), + EffectiveRoomRent = pricingEvaluation.EffectiveRoomRent, + EffectiveRoomDeposit = pricingEvaluation.EffectiveRoomDeposit, + PricingItems = pricingItems.OrderBy(a => a.Sort).ThenBy(a => a.PricingCode).ToList() + } + }; } public SingleOutputDto SelectNotClearRoomAllByRoomState() => CountByState(RoomState.Dirty, count => new ReadRoomOutputDto { Dirty = count }); @@ -204,7 +314,13 @@ namespace EOM.TSHotelManagement.Service entity.RoomNumber = normalizedRoomNumber; entity.RoomArea = string.IsNullOrWhiteSpace(normalizedRoomArea) ? null : normalizedRoomArea; entity.LastCheckInTime = null; - entity.LastCheckOutTime = DateOnly.MinValue; + entity.LastCheckOutTime = null; + entity.AppliedRoomRent = 0M; + entity.AppliedRoomDeposit = 0M; + entity.RoomPricingCode = string.Empty; + entity.RoomPricingName = string.Empty; + entity.PricingStayHours = null; + entity.PricingStartTime = null; NormalizeRoom(entity); roomRepository.Insert(entity); return new BaseResponse(); @@ -245,8 +361,8 @@ namespace EOM.TSHotelManagement.Service room.RoomFloor = rn.RoomFloor; room.RoomTypeId = rn.RoomTypeId; room.CustomerNumber = rn.CustomerNumber; - room.LastCheckInTime = rn.LastCheckInTime; - room.LastCheckOutTime = rn.LastCheckOutTime ?? DateOnly.MinValue; + room.LastCheckInTime = NormalizeStayDateTime(rn.LastCheckInTime); + room.LastCheckOutTime = NormalizeStayDateTime(rn.LastCheckOutTime); room.RoomStateId = rn.RoomStateId; room.RoomRent = rn.RoomRent; room.RoomDeposit = rn.RoomDeposit; @@ -346,7 +462,9 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse { Message = "The customer does not match the original room", Code = BusinessStatusCode.InternalServerError }; } - if (!originalRoom.LastCheckInTime.HasValue) + var now = DateTime.Now; + var originalCheckInTime = NormalizeStayDateTime(originalRoom.LastCheckInTime); + if (!originalCheckInTime.HasValue) { return new BaseResponse { Message = "The original room lacks check-in time", Code = BusinessStatusCode.InternalServerError }; } @@ -362,8 +480,7 @@ namespace EOM.TSHotelManagement.Service && a.SettlementStatus == ConsumptionConstant.UnSettle.Code && a.IsDelete == 0); - var staySpan = DateTime.Now - originalRoom.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue); - var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + var stayDays = CalculateStayDays(originalCheckInTime.Value, now); var totalSpent = originalSpends.Sum(a => a.ConsumptionAmount); var vipRules = vipLevelRuleRepository.GetList(a => a.IsDelete != 1); var newLevelId = vipRules @@ -384,11 +501,19 @@ namespace EOM.TSHotelManagement.Service } var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M; - var originalRoomBill = originalRoom.RoomRent * stayDays * discount; + var originalPricingEvaluation = EvaluateRoomPricing(originalRoom, now); + var originalEffectiveRent = originalPricingEvaluation.EffectiveRoomRent; + var originalRoomBill = originalEffectiveRent * stayDays * discount; targetRoom.CustomerNumber = originalRoom.CustomerNumber; targetRoom.RoomStateId = (int)RoomState.Occupied; - targetRoom.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); + targetRoom.LastCheckInTime = now; + targetRoom.AppliedRoomRent = originalRoom.AppliedRoomRent; + targetRoom.AppliedRoomDeposit = originalRoom.AppliedRoomDeposit; + targetRoom.RoomPricingCode = originalRoom.RoomPricingCode; + targetRoom.RoomPricingName = originalRoom.RoomPricingName; + targetRoom.PricingStayHours = originalRoom.PricingStayHours; + targetRoom.PricingStartTime = NormalizeStayDateTime(originalRoom.PricingStartTime) ?? originalCheckInTime; if (!roomRepository.Update(targetRoom)) { return BaseResponseFactory.ConcurrencyConflict(); @@ -396,8 +521,14 @@ namespace EOM.TSHotelManagement.Service originalRoom.CustomerNumber = string.Empty; originalRoom.RoomStateId = (int)RoomState.Dirty; - originalRoom.LastCheckInTime = DateOnly.MinValue; - originalRoom.LastCheckOutTime = DateOnly.MinValue; + originalRoom.LastCheckInTime = null; + originalRoom.LastCheckOutTime = now; + originalRoom.AppliedRoomRent = 0M; + originalRoom.AppliedRoomDeposit = 0M; + originalRoom.RoomPricingCode = string.Empty; + originalRoom.RoomPricingName = string.Empty; + originalRoom.PricingStayHours = null; + originalRoom.PricingStartTime = null; if (!roomRepository.Update(originalRoom)) { return BaseResponseFactory.ConcurrencyConflict(); @@ -426,8 +557,8 @@ namespace EOM.TSHotelManagement.Service SpendNumber = uniqueCode.GetNewId("SP-"), ProductNumber = originalRoom.RoomNumber, ProductName = "居住 " + string.Join("/", originalRoom.RoomArea, originalRoom.RoomFloor, originalRoom.RoomNumber) + " 共 " + stayDays + " 天", - ProductPrice = originalRoom.RoomRent, - ConsumptionTime = DateTime.Now, + ProductPrice = originalEffectiveRent, + ConsumptionTime = now, SettlementStatus = ConsumptionConstant.UnSettle.Code, ConsumptionQuantity = stayDays, ConsumptionAmount = originalRoomBill, @@ -469,13 +600,22 @@ namespace EOM.TSHotelManagement.Service } var room = roomResult.Room; - var checkinDate = room.LastCheckInTime; + var now = DateTime.Now; + var checkinDate = NormalizeStayDateTime(room.LastCheckInTime); var occupiedCustomerNumber = room.CustomerNumber; + var pricingEvaluation = EvaluateRoomPricing(room, now); + var effectiveRoomRent = pricingEvaluation.EffectiveRoomRent; room.CustomerNumber = string.Empty; - room.LastCheckInTime = DateOnly.MinValue; - room.LastCheckOutTime = DateOnly.MinValue; + room.LastCheckInTime = null; + room.LastCheckOutTime = now; room.RoomStateId = (int)RoomState.Dirty; + room.AppliedRoomRent = 0M; + room.AppliedRoomDeposit = 0M; + room.RoomPricingCode = string.Empty; + room.RoomPricingName = string.Empty; + room.PricingStayHours = null; + room.PricingStartTime = null; if (!roomRepository.Update(room)) { return BaseResponseFactory.ConcurrencyConflict(); @@ -484,8 +624,8 @@ namespace EOM.TSHotelManagement.Service energyRepository.Insert(new EnergyManagement { InformationId = uniqueCode.GetNewId("EM-"), - StartDate = checkinDate ?? DateOnly.MinValue, - EndDate = DateOnly.FromDateTime(DateTime.Today), + StartDate = checkinDate ?? now, + EndDate = now, WaterUsage = checkoutRoomDto.WaterUsage, PowerUsage = checkoutRoomDto.ElectricityUsage, Recorder = "System", @@ -510,8 +650,7 @@ namespace EOM.TSHotelManagement.Service } } - var staySpan = DateTime.Now - (checkinDate ?? DateOnly.FromDateTime(DateTime.Now)).ToDateTime(TimeOnly.MinValue); - var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + var stayDays = CalculateStayDays(checkinDate ?? now, now); var customerType = custoTypeRepository.GetSingle(a => a.CustomerType == customer.First().CustomerType && a.IsDelete != 1); if (customerType.IsNullOrEmpty()) { @@ -519,7 +658,7 @@ namespace EOM.TSHotelManagement.Service } var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M; - var roomBill = room.RoomRent * stayDays * discount; + var roomBill = effectiveRoomRent * stayDays * discount; spendRepository.Insert(new Spend { @@ -528,9 +667,9 @@ namespace EOM.TSHotelManagement.Service SettlementStatus = ConsumptionConstant.Settled.Code, ConsumptionType = SpendTypeConstant.Room.Code, ConsumptionQuantity = stayDays, - ConsumptionTime = (checkinDate ?? DateOnly.FromDateTime(DateTime.Now)).ToDateTime(TimeOnly.MinValue), + ConsumptionTime = now, ProductNumber = room.RoomNumber, - ProductPrice = room.RoomRent, + ProductPrice = effectiveRoomRent, ConsumptionAmount = roomBill, CustomerNumber = occupiedCustomerNumber, RoomId = room.Id, @@ -589,9 +728,14 @@ namespace EOM.TSHotelManagement.Service } var room = roomResult.Room; - room.LastCheckInTime = DateOnly.FromDateTime(DateTime.Now); + room.LastCheckInTime = DateTime.Now; room.CustomerNumber = customer.CustomerNumber; room.RoomStateId = new EnumHelper().GetEnumValue(RoomState.Occupied); + var pricingResponse = ApplyPricingSelection(room, checkinRoomByReservationDto.PricingCode); + if (pricingResponse != null) + { + return pricingResponse; + } if (!roomRepository.Update(room)) { return BaseResponseFactory.ConcurrencyConflict(); @@ -788,6 +932,7 @@ namespace EOM.TSHotelManagement.Service private static ReadRoomOutputDto MapRoomToOutput(Room source, Dictionary roomTypeMap, Dictionary customerMap, Dictionary roomStateMap) { + var pricingEvaluation = EvaluateRoomPricing(source); return new ReadRoomOutputDto { Id = source.Id, @@ -799,14 +944,24 @@ namespace EOM.TSHotelManagement.Service RoomName = roomTypeMap.TryGetValue(source.RoomTypeId, out var roomTypeName) ? roomTypeName : "", CustomerNumber = source.CustomerNumber ?? "", CustomerName = customerMap.TryGetValue(source.CustomerNumber ?? "", out var customerName) ? customerName : "", - LastCheckInTime = source.LastCheckInTime.HasValue && source.LastCheckInTime.Value != DateOnly.MinValue - ? source.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - : null, - LastCheckOutTime = source.LastCheckOutTime == DateOnly.MinValue ? null : source.LastCheckOutTime.ToDateTime(TimeOnly.MinValue), + LastCheckInTime = NormalizeStayDateTime(source.LastCheckInTime), + LastCheckOutTime = NormalizeStayDateTime(source.LastCheckOutTime), RoomStateId = source.RoomStateId, RoomState = roomStateMap.TryGetValue(source.RoomStateId, out var roomStateName) ? roomStateName : "", - RoomRent = source.RoomRent, - RoomDeposit = source.RoomDeposit, + RoomRent = pricingEvaluation.EffectiveRoomRent, + RoomDeposit = pricingEvaluation.EffectiveRoomDeposit, + StandardRoomRent = source.RoomRent, + StandardRoomDeposit = source.RoomDeposit, + AppliedRoomRent = source.AppliedRoomRent, + AppliedRoomDeposit = source.AppliedRoomDeposit, + EffectiveRoomRent = pricingEvaluation.EffectiveRoomRent, + EffectiveRoomDeposit = pricingEvaluation.EffectiveRoomDeposit, + EffectivePricingCode = pricingEvaluation.EffectivePricingCode, + EffectivePricingName = pricingEvaluation.EffectivePricingName, + PricingCode = pricingEvaluation.SelectedPricingCode, + PricingName = pricingEvaluation.SelectedPricingName, + PricingStayHours = pricingEvaluation.PricingStayHours, + IsPricingTimedOut = pricingEvaluation.IsPricingTimedOut, RoomLocation = source.RoomLocation, DataInsUsr = source.DataInsUsr, DataInsDate = source.DataInsDate, @@ -821,5 +976,133 @@ namespace EOM.TSHotelManagement.Service { return new BaseResponse { Message = ex.Message, Code = BusinessStatusCode.InternalServerError }; } + + private BaseResponse ApplyPricingSelection(Room room, string pricingCode) + { + if (room == null || string.IsNullOrWhiteSpace(pricingCode)) + { + return null; + } + + var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId && a.IsDelete != 1); + if (roomType == null) + { + return new BaseResponse { Message = "Room type pricing not found", Code = BusinessStatusCode.NotFound }; + } + + var pricingItem = RoomPricingHelper.ResolvePricingItem(roomType.RoomRent, roomType.RoomDeposit, roomType.PricingItemsJson, pricingCode); + if (pricingItem == null) + { + return new BaseResponse { Message = "Pricing code not found", Code = BusinessStatusCode.BadRequest }; + } + + if (pricingItem.IsDefault) + { + room.AppliedRoomRent = 0M; + room.AppliedRoomDeposit = 0M; + room.RoomPricingCode = string.Empty; + room.RoomPricingName = string.Empty; + room.PricingStayHours = null; + room.PricingStartTime = null; + return null; + } + + room.AppliedRoomRent = pricingItem.RoomRent; + room.AppliedRoomDeposit = pricingItem.RoomDeposit; + room.RoomPricingCode = pricingItem.PricingCode; + room.RoomPricingName = pricingItem.PricingName; + room.PricingStayHours = pricingItem.StayHours > 0 ? pricingItem.StayHours : null; + room.PricingStartTime = room.PricingStayHours.HasValue + ? NormalizeStayDateTime(room.LastCheckInTime) ?? DateTime.Now + : null; + return null; + } + + private static decimal GetEffectiveRoomRent(Room room) + { + return EvaluateRoomPricing(room).EffectiveRoomRent; + } + + private static decimal GetEffectiveRoomDeposit(Room room) + { + return EvaluateRoomPricing(room).EffectiveRoomDeposit; + } + + private static RoomPricingEvaluation EvaluateRoomPricing(Room room, DateTime? referenceTime = null) + { + if (room == null) + { + return new RoomPricingEvaluation + { + SelectedPricingCode = RoomPricingHelper.DefaultPricingCode, + SelectedPricingName = RoomPricingHelper.DefaultPricingName, + EffectivePricingCode = RoomPricingHelper.DefaultPricingCode, + EffectivePricingName = RoomPricingHelper.DefaultPricingName, + EffectiveRoomRent = 0M, + EffectiveRoomDeposit = 0M + }; + } + + var selectedPricingCode = string.IsNullOrWhiteSpace(room.RoomPricingCode) ? RoomPricingHelper.DefaultPricingCode : room.RoomPricingCode; + var selectedPricingName = string.IsNullOrWhiteSpace(room.RoomPricingName) ? RoomPricingHelper.DefaultPricingName : room.RoomPricingName; + var effectivePricingCode = RoomPricingHelper.DefaultPricingCode; + var effectivePricingName = RoomPricingHelper.DefaultPricingName; + var effectiveRoomRent = room.RoomRent; + var effectiveRoomDeposit = room.RoomDeposit; + var isPricingTimedOut = false; + + if (room.AppliedRoomRent > 0 || room.AppliedRoomDeposit > 0 || !string.IsNullOrWhiteSpace(room.RoomPricingCode)) + { + isPricingTimedOut = IsPricingTimedOut(room, referenceTime); + if (!isPricingTimedOut) + { + effectivePricingCode = selectedPricingCode; + effectivePricingName = selectedPricingName; + effectiveRoomRent = room.AppliedRoomRent > 0 ? room.AppliedRoomRent : room.RoomRent; + effectiveRoomDeposit = room.AppliedRoomDeposit > 0 ? room.AppliedRoomDeposit : room.RoomDeposit; + } + } + + return new RoomPricingEvaluation + { + SelectedPricingCode = selectedPricingCode, + SelectedPricingName = selectedPricingName, + EffectivePricingCode = effectivePricingCode, + EffectivePricingName = effectivePricingName, + EffectiveRoomRent = effectiveRoomRent, + EffectiveRoomDeposit = effectiveRoomDeposit, + PricingStayHours = room.PricingStayHours > 0 ? room.PricingStayHours : null, + IsPricingTimedOut = isPricingTimedOut + }; + } + + private static bool IsPricingTimedOut(Room room, DateTime? referenceTime = null) + { + if (room?.PricingStayHours is not > 0) + { + return false; + } + + var pricingStartTime = NormalizeStayDateTime(room.PricingStartTime) + ?? NormalizeStayDateTime(room.LastCheckInTime); + if (!pricingStartTime.HasValue) + { + return false; + } + + var now = referenceTime ?? DateTime.Now; + return now > pricingStartTime.Value.AddHours(room.PricingStayHours.Value); + } + + private static int CalculateStayDays(DateTime checkInTime, DateTime referenceTime) + { + var staySpan = referenceTime - checkInTime; + return Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1); + } + + private static DateTime? NormalizeStayDateTime(DateTime? value) + { + return value.HasValue && value.Value > DateTime.MinValue ? value : null; + } } } diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs index 536c15a..a304bee 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomTypeService.cs @@ -99,6 +99,7 @@ namespace EOM.TSHotelManagement.Service RoomTypeName = source.RoomTypeName, RoomRent = source.RoomRent, RoomDeposit = source.RoomDeposit, + PricingItems = RoomPricingHelper.BuildPricingItems(source.RoomRent, source.RoomDeposit, source.PricingItemsJson), DataInsUsr = source.DataInsUsr, DataInsDate = source.DataInsDate, DataChgUsr = source.DataChgUsr, @@ -121,6 +122,7 @@ namespace EOM.TSHotelManagement.Service RoomTypeName = source.RoomTypeName, RoomRent = source.RoomRent, RoomDeposit = source.RoomDeposit, + PricingItems = RoomPricingHelper.BuildPricingItems(source.RoomRent, source.RoomDeposit, source.PricingItemsJson), DataInsUsr = source.DataInsUsr, DataInsDate = source.DataInsDate, DataChgUsr = source.DataChgUsr, @@ -162,7 +164,7 @@ namespace EOM.TSHotelManagement.Service } var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == roomResult.Room.RoomTypeId && a.IsDelete != 1) ?? new RoomType(); - var source = EntityMapper.Map(roomType); + var source = MapRoomTypeToOutput(roomType); return new SingleOutputDto { Data = source }; } #endregion @@ -179,7 +181,17 @@ namespace EOM.TSHotelManagement.Service var existRoomType = roomTypeRepository.IsAny(a => a.RoomTypeId == roomType.RoomTypeId); if (existRoomType) return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room type already exists.", "房间类型已存在。"), Code = BusinessStatusCode.InternalServerError }; - roomTypeRepository.Insert(EntityMapper.Map(roomType)); + roomTypeRepository.Insert(new RoomType + { + RoomTypeId = roomType.RoomTypeId, + RoomTypeName = roomType.RoomTypeName, + RoomRent = roomType.RoomRent, + RoomDeposit = roomType.RoomDeposit, + PricingItemsJson = RoomPricingHelper.SerializeAdditionalPricingItems(roomType.PricingItems), + IsDelete = roomType.IsDelete ?? 0, + DataInsUsr = roomType.DataInsUsr, + DataInsDate = roomType.DataInsDate + }); } catch (Exception ex) { @@ -198,18 +210,29 @@ namespace EOM.TSHotelManagement.Service { try { - var result = roomTypeRepository.Update(new RoomType + var targetRoomType = roomTypeRepository.GetFirst(a => a.Id == (roomType.Id ?? 0) && a.IsDelete != 1); + if (targetRoomType == null) { - RoomTypeId = roomType.RoomTypeId, - Id = roomType.Id ?? 0, - RoomTypeName = roomType.RoomTypeName, - RoomRent = roomType.RoomRent, - RoomDeposit = roomType.RoomDeposit, - IsDelete = roomType.IsDelete, - DataChgUsr = roomType.DataChgUsr, - DataChgDate = roomType.DataChgDate, - RowVersion = roomType.RowVersion ?? 0 - }); + return new BaseResponse + { + Code = BusinessStatusCode.NotFound, + Message = LocalizationHelper.GetLocalizedString("Room Type Information Not Found", "房间类型信息未找到") + }; + } + + targetRoomType.RoomTypeId = roomType.RoomTypeId; + targetRoomType.RoomTypeName = roomType.RoomTypeName; + targetRoomType.RoomRent = roomType.RoomRent; + targetRoomType.RoomDeposit = roomType.RoomDeposit; + targetRoomType.PricingItemsJson = roomType.PricingItems == null + ? targetRoomType.PricingItemsJson + : RoomPricingHelper.SerializeAdditionalPricingItems(roomType.PricingItems); + targetRoomType.IsDelete = roomType.IsDelete; + targetRoomType.DataChgUsr = roomType.DataChgUsr; + targetRoomType.DataChgDate = roomType.DataChgDate; + targetRoomType.RowVersion = roomType.RowVersion ?? 0; + + var result = roomTypeRepository.Update(targetRoomType); if (!result) { return BaseResponseFactory.ConcurrencyConflict(); @@ -280,5 +303,32 @@ namespace EOM.TSHotelManagement.Service } return new BaseResponse(); } + + private static ReadRoomTypeOutputDto MapRoomTypeToOutput(RoomType source) + { + if (source == null) + { + return new ReadRoomTypeOutputDto + { + PricingItems = new List() + }; + } + + return new ReadRoomTypeOutputDto + { + Id = source.Id, + RoomTypeId = source.RoomTypeId, + RoomTypeName = source.RoomTypeName, + RoomRent = source.RoomRent, + RoomDeposit = source.RoomDeposit, + PricingItems = RoomPricingHelper.BuildPricingItems(source.RoomRent, source.RoomDeposit, source.PricingItemsJson), + DataInsUsr = source.DataInsUsr, + DataInsDate = source.DataInsDate, + DataChgUsr = source.DataChgUsr, + DataChgDate = source.DataChgDate, + RowVersion = source.RowVersion, + IsDelete = source.IsDelete + }; + } } } diff --git a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs index 351509f..c0d1fa0 100644 --- a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs +++ b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs @@ -3,7 +3,6 @@ using EOM.TSHotelManagement.Contract; using EOM.TSHotelManagement.Data; using EOM.TSHotelManagement.Domain; using jvncorelib.CodeLib; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -19,8 +18,6 @@ namespace EOM.TSHotelManagement.Service private readonly GenericRepository roomRepository; private readonly GenericRepository customerRepository; private readonly GenericRepository custoTypeRepository; - private readonly GenericRepository operationLogRepository; - private readonly IHttpContextAccessor httpContextAccessor; private readonly ILogger logger; public SpendService( @@ -29,8 +26,6 @@ namespace EOM.TSHotelManagement.Service GenericRepository roomRepository, GenericRepository customerRepository, GenericRepository custoTypeRepository, - GenericRepository operationLogRepository, - IHttpContextAccessor httpContextAccessor, ILogger logger) { this.spendRepository = spendRepository; @@ -38,8 +33,6 @@ namespace EOM.TSHotelManagement.Service this.roomRepository = roomRepository; this.customerRepository = customerRepository; this.custoTypeRepository = custoTypeRepository; - this.operationLogRepository = operationLogRepository; - this.httpContextAccessor = httpContextAccessor; this.logger = logger; } @@ -76,7 +69,6 @@ namespace EOM.TSHotelManagement.Service public BaseResponse UndoCustomerSpend(UndoCustomerSpendInputDto undoCustomerSpendInputDto) { - var httpContext = httpContextAccessor.HttpContext; using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); try @@ -114,9 +106,6 @@ namespace EOM.TSHotelManagement.Service return BaseResponseFactory.ConcurrencyConflict(); } - var logContent = $"{ClaimsPrincipalExtensions.GetUserNumber(httpContext.User)} canceled a spend record. Room {existingSpend.RoomNumber}, Product {existingSpend.ProductName}, Qty {existingSpend.ConsumptionQuantity}, Amount {existingSpend.ConsumptionAmount:#,##0.00}"; - operationLogRepository.Insert(BuildOperationLog(logContent)); - scope.Complete(); return new BaseResponse(); } @@ -211,11 +200,6 @@ namespace EOM.TSHotelManagement.Service return BaseResponseFactory.ConcurrencyConflict(); } - var roomLocator = RoomLocatorHelper.BuildLocator(room.RoomArea, room.RoomFloor, room.RoomNumber); - var currentUser = httpContextAccessor.HttpContext == null ? string.Empty : ClaimsPrincipalExtensions.GetUserNumber(httpContextAccessor.HttpContext.User); - var logContent = $"{currentUser} added a spend record. Room {roomLocator}, Product {addCustomerSpendInputDto.ProductName}, Qty {addCustomerSpendInputDto.ConsumptionQuantity}, Amount {realAmount:#,##0.00}"; - operationLogRepository.Insert(BuildOperationLog(logContent)); - scope.Complete(); return new BaseResponse(); } @@ -311,6 +295,12 @@ namespace EOM.TSHotelManagement.Service var rooms = RoomReferenceHelper.LoadRooms(roomRepository, spends.Select(a => a.RoomId), spends.Select(a => a.RoomNumber)); var result = spends.Select(a => MapSpendToOutput(a, RoomReferenceHelper.FindRoom(rooms, a.RoomId, a.RoomNumber))).ToList(); + result.ForEach(r => + { + r.SettlementStatusDescription = ConsumptionConstant.GetDescriptionByCode(r.SettlementStatus) ?? r.SettlementStatus; + r.ConsumptionTypeDescription = SpendTypeConstant.GetDescriptionByCode(r.ConsumptionType) ?? r.ConsumptionType; + }); + return new ListOutputDto { Data = new PagedData @@ -368,22 +358,6 @@ namespace EOM.TSHotelManagement.Service : SpendTypeConstant.Other.Description; } - private OperationLog BuildOperationLog(string logContent) - { - var context = httpContextAccessor.HttpContext; - var operationAccount = context == null ? string.Empty : ClaimsPrincipalExtensions.GetUserNumber(context.User); - return new OperationLog - { - OperationId = new UniqueCode().GetNewId("OP-"), - OperationTime = DateTime.Now, - LogContent = logContent, - LoginIpAddress = context?.Connection.RemoteIpAddress?.ToString() ?? string.Empty, - OperationAccount = operationAccount, - LogLevel = (int)Common.LogLevel.Warning, - SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion() - }; - } - private static BaseResponse CreateRoomLookupFailure(RoomResolveResult result, int? roomId, string roomNumber) { if (!roomId.HasValue || roomId.Value <= 0) -- Gitee From f8124670085faebffc2b579e5436ac513332ce68 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 21 Mar 2026 18:32:35 +0800 Subject: [PATCH 18/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=98=BB=E6=96=AD?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Filters/BusinessOperationAuditFilter.cs | 66 +++++++++++++------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs index 4b0a211..6aad870 100644 --- a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs +++ b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs @@ -10,16 +10,21 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace EOM.TSHotelManagement.WebApi.Filters { public class BusinessOperationAuditFilter : IAsyncActionFilter { + private static readonly ConcurrentDictionary PropertyCache = new(); + private static readonly Regex LogControlCharsRegex = new(@"[\p{Cc}\p{Cf}]+", RegexOptions.Compiled | RegexOptions.CultureInvariant); + private static readonly HashSet ExcludedControllers = new(StringComparer.OrdinalIgnoreCase) { "Login", @@ -162,18 +167,29 @@ namespace EOM.TSHotelManagement.WebApi.Filters int responseCode, string responseMessage) { + var safeStatusText = SanitizeForLog(statusText, 32); + var safeMethod = SanitizeForLog(method, 16); + var safePath = SanitizeForLog(path, 240); + var safeOperationAccount = SanitizeForLog(operationAccount, 80); + var safeArgumentSummary = SanitizeForLog(argumentSummary, 900); var localizedResponseMessage = string.IsNullOrWhiteSpace(responseMessage) ? Localize(isChinese, "None", "无") - : responseMessage; + : SanitizeForLog(responseMessage, 300); var content = Localize( isChinese, - $"{statusText} {method} {path} | User={operationAccount} | Args={argumentSummary} | ResponseCode={responseCode} | Message={localizedResponseMessage}", - $"{statusText} {method} {path} | 操作人={operationAccount} | 参数={argumentSummary} | 响应码={responseCode} | 响应信息={localizedResponseMessage}"); + $"{safeStatusText} {safeMethod} {safePath} | User={safeOperationAccount} | Args={safeArgumentSummary} | ResponseCode={responseCode} | Message={localizedResponseMessage}", + $"{safeStatusText} {safeMethod} {safePath} | 操作人={safeOperationAccount} | 参数={safeArgumentSummary} | 响应码={responseCode} | 响应信息={localizedResponseMessage}"); return TrimLogContent(content, isChinese); } + private static string SanitizeForLog(string value, int maxLength = 300) + { + var sanitized = LogControlCharsRegex.Replace(value ?? string.Empty, " ").Trim(); + return sanitized.Length <= maxLength ? sanitized : sanitized[..(maxLength - 3)] + "..."; + } + private static (bool IsSuccess, int ResponseCode, string ResponseMessage) ResolveExecutionResult(ActionExecutedContext executedContext) { if (executedContext.Exception != null && !executedContext.ExceptionHandled) @@ -214,7 +230,7 @@ namespace EOM.TSHotelManagement.WebApi.Filters var items = arguments .Where(a => a.Value != null) - .Select(a => $"{a.Key}={SummarizeValue(a.Key, a.Value, isChinese)}") + .Select(a => $"{SanitizeForLog(a.Key, 60)}={SummarizeValue(a.Key, a.Value, isChinese)}") .Where(a => !string.IsNullOrWhiteSpace(a)) .ToList(); @@ -235,10 +251,11 @@ namespace EOM.TSHotelManagement.WebApi.Filters if (value is IFormFile file) { + var safeFileName = SanitizeForLog(file.FileName, 120); return Localize( isChinese, - $"File({file.FileName}, {file.Length} bytes)", - $"文件({file.FileName}, {file.Length} 字节)"); + $"File({safeFileName}, {file.Length} bytes)", + $"文件({safeFileName}, {file.Length} 字节)"); } if (IsSimpleValue(value.GetType())) @@ -267,7 +284,7 @@ namespace EOM.TSHotelManagement.WebApi.Filters continue; } - previews.Add(item == null ? "null" : FormatSimpleValue(item)); + previews.Add(item == null ? Localize(isChinese, "null", "空") : FormatSimpleValue(item)); } return previews.Count == 0 @@ -280,9 +297,8 @@ namespace EOM.TSHotelManagement.WebApi.Filters private static string SummarizeComplexObject(object value, bool isChinese) { - var properties = value.GetType() - .GetProperties(BindingFlags.Instance | BindingFlags.Public) - .Where(p => p.CanRead && p.GetIndexParameters().Length == 0) + var type = value.GetType(); + var properties = GetCachedProperties(type) .Take(8) .Select(p => { @@ -301,27 +317,30 @@ namespace EOM.TSHotelManagement.WebApi.Filters return null; } + var safePropertyName = SanitizeForLog(p.Name, 60); + if (IsSensitive(p.Name)) { - return $"{p.Name}=***"; + return $"{safePropertyName}=***"; } if (propertyValue is IFormFile file) { + var safeFileName = SanitizeForLog(file.FileName, 120); return Localize( isChinese, - $"{p.Name}=File({file.FileName}, {file.Length} bytes)", - $"{p.Name}=文件({file.FileName}, {file.Length} 字节)"); + $"{safePropertyName}=File({safeFileName}, {file.Length} bytes)", + $"{safePropertyName}=文件({safeFileName}, {file.Length} 字节)"); } if (IsSimpleValue(propertyValue.GetType())) { - return $"{p.Name}={FormatSimpleValue(propertyValue)}"; + return $"{safePropertyName}={FormatSimpleValue(propertyValue)}"; } if (propertyValue is IEnumerable enumerable && propertyValue is not string) { - return $"{p.Name}={SummarizeEnumerable(enumerable, isChinese)}"; + return $"{safePropertyName}={SummarizeEnumerable(enumerable, isChinese)}"; } return null; @@ -329,9 +348,18 @@ namespace EOM.TSHotelManagement.WebApi.Filters .Where(s => !string.IsNullOrWhiteSpace(s)) .ToList(); + var safeTypeName = SanitizeForLog(type.Name, 80); return properties.Count == 0 - ? value.GetType().Name - : $"{value.GetType().Name}({string.Join(", ", properties)})"; + ? safeTypeName + : $"{safeTypeName}({string.Join(", ", properties)})"; + } + + private static PropertyInfo[] GetCachedProperties(Type type) + { + return PropertyCache.GetOrAdd(type, static currentType => currentType + .GetProperties(BindingFlags.Instance | BindingFlags.Public) + .Where(p => p.CanRead && p.GetIndexParameters().Length == 0) + .ToArray()); } private static bool IsSimpleValue(Type type) @@ -364,7 +392,7 @@ namespace EOM.TSHotelManagement.WebApi.Filters _ => Convert.ToString(value, CultureInfo.InvariantCulture) ?? value.ToString() ?? string.Empty }; - return formatted.Length <= 120 ? formatted : formatted[..117] + "..."; + return SanitizeForLog(formatted, 120); } private static string TrimLogContent(string content, bool isChinese) @@ -374,7 +402,7 @@ namespace EOM.TSHotelManagement.WebApi.Filters return Localize(isChinese, "Operation audit log", "业务操作审计日志"); } - return content.Length <= 1900 ? content : content[..1897] + "..."; + return SanitizeForLog(content, 1900); } private static bool IsChineseLanguage(HttpContext httpContext) -- Gitee From 795b69530ba3a81dcf334e98856a8a0af916aba5 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 21 Mar 2026 18:42:09 +0800 Subject: [PATCH 19/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=98=BB=E6=96=AD?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Filters/BusinessOperationAuditFilter.cs | 18 +++++++--- .../Business/Room/RoomService.cs | 33 ++++++++++++------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs index 6aad870..a8fcd67 100644 --- a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs +++ b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs @@ -112,10 +112,17 @@ namespace EOM.TSHotelManagement.WebApi.Filters { try { - var request = context.HttpContext.Request; + var httpContext = context?.HttpContext; + if (httpContext == null) + { + logger.LogWarning("HttpContext is null, skipping audit log."); + return; + } + + var request = httpContext.Request; var path = request.Path.HasValue ? request.Path.Value! : string.Empty; - var isChinese = IsChineseLanguage(context.HttpContext); - var operationAccount = ClaimsPrincipalExtensions.GetUserNumber(context.HttpContext.User); + var isChinese = IsChineseLanguage(httpContext); + var operationAccount = ClaimsPrincipalExtensions.GetUserNumber(httpContext.User); if (string.IsNullOrWhiteSpace(operationAccount)) { operationAccount = Localize(isChinese, "Anonymous", "匿名用户"); @@ -139,7 +146,7 @@ namespace EOM.TSHotelManagement.WebApi.Filters OperationId = new UniqueCode().GetNewId("OP-"), OperationTime = DateTime.Now, LogContent = logContent, - LoginIpAddress = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty, + LoginIpAddress = httpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty, OperationAccount = operationAccount, LogLevel = isSuccess ? (int)Common.LogLevel.Normal : (int)Common.LogLevel.Warning, SoftwareVersion = SoftwareVersionHelper.GetSoftwareVersion(), @@ -151,7 +158,8 @@ namespace EOM.TSHotelManagement.WebApi.Filters } catch (Exception ex) { - logger.LogWarning(ex, "Failed to write business operation audit log for {Path}", context.HttpContext.Request.Path); + var path = context?.HttpContext?.Request?.Path.Value ?? string.Empty; + logger.LogWarning(ex, "Failed to write business operation audit log for {Path}", path); } await Task.CompletedTask; diff --git a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs index fee2f3c..7694296 100644 --- a/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs +++ b/EOM.TSHotelManagement.Service/Business/Room/RoomService.cs @@ -435,7 +435,7 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse { Message = "OriginalRoomId and TargetRoomId are required", Code = BusinessStatusCode.BadRequest }; } - using var scope = new TransactionScope(); + using var scope = CreateTransactionScope(); var customer = custoRepository.GetFirst(a => a.CustomerNumber == transferRoomDto.CustomerNumber && a.IsDelete != 1); if (customer.IsNullOrEmpty()) @@ -501,7 +501,7 @@ namespace EOM.TSHotelManagement.Service } var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M; - var originalPricingEvaluation = EvaluateRoomPricing(originalRoom, now); + var originalPricingEvaluation = EvaluateRoomPricing(originalRoom); var originalEffectiveRent = originalPricingEvaluation.EffectiveRoomRent; var originalRoomBill = originalEffectiveRent * stayDays * discount; @@ -556,7 +556,7 @@ namespace EOM.TSHotelManagement.Service RoomNumber = targetRoom.RoomNumber, SpendNumber = uniqueCode.GetNewId("SP-"), ProductNumber = originalRoom.RoomNumber, - ProductName = "居住 " + string.Join("/", originalRoom.RoomArea, originalRoom.RoomFloor, originalRoom.RoomNumber) + " 共 " + stayDays + " 天", + ProductName = $"居住 {string.Join("/", originalRoom.RoomArea, originalRoom.RoomFloor, originalRoom.RoomNumber)} 共 {stayDays} 天", ProductPrice = originalEffectiveRent, ConsumptionTime = now, SettlementStatus = ConsumptionConstant.UnSettle.Code, @@ -585,7 +585,7 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse { Message = "RoomId is required", Code = BusinessStatusCode.BadRequest }; } - using var scope = new TransactionScope(); + using var scope = CreateTransactionScope(); var customer = custoRepository.AsQueryable().Where(a => a.CustomerNumber == checkoutRoomDto.CustomerNumber && a.IsDelete != 1); if (!customer.Any()) @@ -603,7 +603,7 @@ namespace EOM.TSHotelManagement.Service var now = DateTime.Now; var checkinDate = NormalizeStayDateTime(room.LastCheckInTime); var occupiedCustomerNumber = room.CustomerNumber; - var pricingEvaluation = EvaluateRoomPricing(room, now); + var pricingEvaluation = EvaluateRoomPricing(room); var effectiveRoomRent = pricingEvaluation.EffectiveRoomRent; room.CustomerNumber = string.Empty; @@ -663,7 +663,7 @@ namespace EOM.TSHotelManagement.Service spendRepository.Insert(new Spend { SpendNumber = uniqueCode.GetNewId("SP-"), - ProductName = "居住 " + string.Join("/", room.RoomArea, room.RoomFloor, room.RoomNumber) + " 共 " + stayDays + " 天", + ProductName = $"居住 {string.Join("/", room.RoomArea, room.RoomFloor, room.RoomNumber)} 共 {stayDays} 天", SettlementStatus = ConsumptionConstant.Settled.Code, ConsumptionType = SpendTypeConstant.Room.Code, ConsumptionQuantity = stayDays, @@ -698,7 +698,7 @@ namespace EOM.TSHotelManagement.Service return new BaseResponse { Message = "RoomId is required", Code = BusinessStatusCode.BadRequest }; } - using var scope = new TransactionScope(); + using var scope = CreateTransactionScope(); var customer = new Customer { @@ -1028,7 +1028,7 @@ namespace EOM.TSHotelManagement.Service return EvaluateRoomPricing(room).EffectiveRoomDeposit; } - private static RoomPricingEvaluation EvaluateRoomPricing(Room room, DateTime? referenceTime = null) + private static RoomPricingEvaluation EvaluateRoomPricing(Room room) { if (room == null) { @@ -1053,7 +1053,7 @@ namespace EOM.TSHotelManagement.Service if (room.AppliedRoomRent > 0 || room.AppliedRoomDeposit > 0 || !string.IsNullOrWhiteSpace(room.RoomPricingCode)) { - isPricingTimedOut = IsPricingTimedOut(room, referenceTime); + isPricingTimedOut = IsPricingTimedOut(room); if (!isPricingTimedOut) { effectivePricingCode = selectedPricingCode; @@ -1076,7 +1076,7 @@ namespace EOM.TSHotelManagement.Service }; } - private static bool IsPricingTimedOut(Room room, DateTime? referenceTime = null) + private static bool IsPricingTimedOut(Room room) { if (room?.PricingStayHours is not > 0) { @@ -1090,10 +1090,21 @@ namespace EOM.TSHotelManagement.Service return false; } - var now = referenceTime ?? DateTime.Now; + var now = DateTime.Now; return now > pricingStartTime.Value.AddHours(room.PricingStayHours.Value); } + private static TransactionScope CreateTransactionScope() + { + return new TransactionScope( + TransactionScopeOption.Required, + new TransactionOptions + { + IsolationLevel = IsolationLevel.ReadCommitted, + Timeout = TimeSpan.FromSeconds(30) + }); + } + private static int CalculateStayDays(DateTime checkInTime, DateTime referenceTime) { var staySpan = referenceTime - checkInTime; -- Gitee From bbc5ae7715067fbfea26d8edc6137c9f3d96f956 Mon Sep 17 00:00:00 2001 From: ck_yeun9 Date: Sat, 21 Mar 2026 18:50:04 +0800 Subject: [PATCH 20/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=98=BB=E6=96=AD?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Filters/BusinessOperationAuditFilter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs index a8fcd67..d357abf 100644 --- a/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs +++ b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs @@ -48,7 +48,11 @@ namespace EOM.TSHotelManagement.WebApi.Filters "secret", "recoverycode", "verificationcode", - "otp" + "otp", + "creditcard", + "ssn", + "bankaccount", + "phonenumber" }; private readonly GenericRepository operationLogRepository; -- Gitee