From 76ca46ccb07538b706ca1bf42daa5eb1f4572426 Mon Sep 17 00:00:00 2001
From: ck_yeun9
Date: Sat, 14 Mar 2026 07:29:07 +0000
Subject: [PATCH 1/7] =?UTF-8?q?!58=20=E6=96=B0=E5=A2=9E=E9=A1=B9=E7=9B=AE?=
=?UTF-8?q?=20Wiki=20=E9=93=BE=E6=8E=A5=E8=87=B3=E4=B8=AD=E8=8B=B1?=
=?UTF-8?q?=E6=96=87=20README=20=E9=A1=B6=E9=83=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 头像上传接口及服务异步化,优化图片格式检测
* !59 收藏夹快照支持乐观锁,增强图片上传安全性
* 收藏夹快照支持乐观锁,增强图片上传安全性
* 新增项目 Wiki 链接至中英文 README 顶部
* 重构客户消费DTO与接口,统一版本号获取方式
* 统一人员字段抽象为Personnel基类,重构相关代码
* 新增个人中心功能及相关底层优化
* 新增职位导出权限配置
* 导出权限、分页优化及员工打卡业务重构
* 实现收藏夹功能,包括保存和获取用户收藏夹快照的接口及服务
* 添加定时任务列表接口。
* 增强Redis配置与定时任务,新增会员等级自动升级
* 优化预约房间业务流程。
* 修改表结构
* 将权限分配的数据,从软删除改为硬删除,节省表空间
* 剥离菜单与权限代码授权逻辑。
---
.env.example | 15 +-
.gitignore | 1 +
.../Authorization/PermissionsAuthorization.cs | 5 +-
.../FavoriteCollectionController.cs | 44 ++
.../Application/Profile/ProfileController.cs | 78 +++
.../Business/Spend/SpendController.cs | 6 +-
.../Quartz/QuartzController.cs | 27 +
.../SystemManagement/Role/RoleController.cs | 10 +
.../EOM.TSHotelManagement.API.csproj | 2 +-
.../Extensions/ApplicationExtensions.cs | 2 +-
.../Extensions/PermissionSyncExtensions.cs | 9 +-
.../Extensions/ServiceExtensions.cs | 112 ++--
.../Filters/RequestLoggingMiddleware.cs | 30 +-
.../appsettings.Application.json | 14 +-
.../appsettings.Database.json | 10 +-
.../Constant/CheckTypeConstant.cs | 22 +
.../Constant/SpendTypeConstant.cs | 4 +-
.../EOM.TSHotelManagement.Common.csproj | 10 +-
.../Helper/ClaimsPrincipalExtensions.cs | 15 +
.../Helper/DataProtectionHelper.cs | 6 +-
.../Helper/EntityMapper.cs | 141 +++--
.../Helper/JwtTokenRevocationService.cs | 114 +++-
.../Helper/LskyHelper.cs | 4 +-
.../Helper/RedisHelper.cs | 66 +-
.../Helper/SoftwareVersionHelper.cs | 51 ++
.../AutomaticallyUpgradeMembershipLevelJob.cs | 199 ++++++
.../ReservationExpirationCheckJob.cs | 7 +-
.../Dto/ReadFavoriteCollectionOutputDto.cs | 23 +
.../Dto/SaveFavoriteCollectionInputDto.cs | 44 ++
.../Dto/SaveFavoriteCollectionOutputDto.cs | 28 +
.../Profile/Dto/ChangePasswordInputDto.cs | 19 +
.../Profile/Dto/CurrentProfileOutputDto.cs | 57 ++
.../Profile/Dto/UploadAvatarInputDto.cs | 10 +
.../Profile/Dto/UploadAvatarOutputDto.cs | 7 +
.../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 +-
.../Business/Reser/Dto/CreateReserInputDto.cs | 1 +
.../Dto/Spend/AddCustomerSpendInputDto.cs | 11 +-
.../Dto/Spend/UndoCustomerSpendInputDto.cs | 9 +
.../Dto/Employee/CreateEmployeeInputDto.cs | 2 +-
.../Dto/Employee/ReadEmployeeInputDto.cs | 4 +-
.../Dto/Employee/ReadEmployeeOutputDto.cs | 4 +-
.../Dto/Employee/UpdateEmployeeInputDto.cs | 2 +-
.../CreateEmployeeCheckInputDto.cs | 24 -
.../GrantRolePermissionsInputDto.cs | 4 +-
.../Dto/Permission/ReadRoleGrantOutputDto.cs | 14 +
.../Permission/UserRolePermissionOutputDto.cs | 4 +-
.../Dto/Quartz/ReadQuartzJobOutputDto.cs | 26 +
.../DatabaseInitializer.cs | 79 +--
.../EOM.TSHotelManagement.Data.csproj | 4 +-
.../Repository/GenericRepository.cs | 16 +-
.../UserFavoriteCollection.cs | 94 +++
.../Application/NavBar/NavBar.cs | 4 +-
EOM.TSHotelManagement.Domain/BaseEntity.cs | 43 --
.../Business/Asset/Asset.cs | 6 +-
.../Business/Customer/CustoSpend.cs | 42 --
.../Business/Customer/CustoType.cs | 4 +-
.../Business/Customer/Customer.cs | 64 +-
.../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/Personnel.cs | 30 +
.../Common/SoftDeleteEntity.cs | 14 +
.../EOM.TSHotelManagement.Domain.csproj | 2 +-
.../Employee/Employee.cs | 106 +---
.../Employee/EmployeeCheck.cs | 4 +-
.../Employee/EmployeeHistory.cs | 4 +-
.../Employee/EmployeePhoto.cs | 4 +-
.../Employee/EmployeeRewardPunishment.cs | 4 +-
.../Employee/RewardPunishmentType.cs | 6 +-
.../SystemManagement/Administrator.cs | 29 +-
.../SystemManagement/AdministratorPhoto.cs | 20 +
.../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 | 23 +-
.../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 +-
.../Config/MailConfig.cs | 3 +-
.../Config/RedisConfig.cs | 8 +
...OM.TSHotelManagement.Infrastructure.csproj | 4 +-
.../Factory/LskyConfigFactory.cs | 5 +-
.../Factory/MailConfigFactory.cs | 5 +-
.../Factory/RedisConfigFactory.cs | 11 +-
.../EntityBuilder.cs | 507 ++++++++-------
.../FavoriteCollectionService.cs | 433 +++++++++++++
.../IFavoriteCollectionService.cs | 23 +
.../Application/Profile/IProfileService.cs | 15 +
.../Application/Profile/ProfileService.cs | 586 ++++++++++++++++++
.../Business/Asset/AssetService.cs | 4 +-
.../Account/CustomerAccountService.cs | 15 +-
.../Business/Customer/CustomerService.cs | 59 +-
.../Permission/CustomerPermissionService.cs | 95 ++-
.../Business/Reser/ReserService.cs | 2 +-
.../Business/Room/RoomService.cs | 58 +-
.../Business/Spend/ISpendService.cs | 8 +-
.../Business/Spend/SpendService.cs | 92 ++-
.../Dashboard/DashboardService.cs | 8 +-
.../EOM.TSHotelManagement.Service.csproj | 2 +-
.../Employee/Check/EmployeeCheckService.cs | 89 ++-
.../Employee/EmployeeService.cs | 61 +-
.../Permission/EmployeePermissionService.cs | 91 ++-
.../RewardPunishmentService.cs | 4 +-
.../Administrator/AdminService.cs | 110 ++--
.../SystemManagement/Base/BaseService.cs | 12 +-
.../SystemManagement/Menu/MenuService.cs | 213 ++++---
.../SystemManagement/Notice/NoticeService.cs | 12 +-
.../Quartz/IQuartzAppService.cs | 10 +
.../Quartz/QuartzAppService.cs | 100 +++
.../SystemManagement/Role/IRoleAppService.cs | 7 +
.../SystemManagement/Role/RoleAppService.cs | 159 ++++-
.../SupervisionStatisticsService.cs | 11 +-
.../VipRule/VipRuleAppService.cs | 14 +-
.../Util/UtilService.cs | 4 +-
README.en.md | 15 +-
README.md | 15 +-
141 files changed, 3712 insertions(+), 1309 deletions(-)
create mode 100644 EOM.TSHotelManagement.API/Controllers/Application/FavoriteCollection/FavoriteCollectionController.cs
create mode 100644 EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs
create mode 100644 EOM.TSHotelManagement.API/Controllers/SystemManagement/Quartz/QuartzController.cs
create mode 100644 EOM.TSHotelManagement.Common/Constant/CheckTypeConstant.cs
create mode 100644 EOM.TSHotelManagement.Common/Helper/ClaimsPrincipalExtensions.cs
create mode 100644 EOM.TSHotelManagement.Common/Helper/SoftwareVersionHelper.cs
create mode 100644 EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/AutomaticallyUpgradeMembershipLevelJob.cs
rename EOM.TSHotelManagement.Common/QuartzWorkspace/{Job => BusinessJob}/ReservationExpirationCheckJob.cs (94%)
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.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.Contract/Business/Spend/Dto/Spend/UndoCustomerSpendInputDto.cs
create mode 100644 EOM.TSHotelManagement.Contract/SystemManagement/Dto/Permission/ReadRoleGrantOutputDto.cs
create mode 100644 EOM.TSHotelManagement.Contract/SystemManagement/Dto/Quartz/ReadQuartzJobOutputDto.cs
create mode 100644 EOM.TSHotelManagement.Domain/Application/FavoriteCollection/UserFavoriteCollection.cs
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/Personnel.cs
create mode 100644 EOM.TSHotelManagement.Domain/Common/SoftDeleteEntity.cs
create mode 100644 EOM.TSHotelManagement.Domain/SystemManagement/AdministratorPhoto.cs
delete mode 100644 EOM.TSHotelManagement.Domain/SystemManagement/SystemInformation.cs
create mode 100644 EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs
create mode 100644 EOM.TSHotelManagement.Service/Application/FavoriteCollection/IFavoriteCollectionService.cs
create mode 100644 EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs
create mode 100644 EOM.TSHotelManagement.Service/Application/Profile/ProfileService.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 9920f34..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
@@ -52,6 +53,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/.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/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/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.API/Controllers/Application/Profile/ProfileController.cs b/EOM.TSHotelManagement.API/Controllers/Application/Profile/ProfileController.cs
new file mode 100644
index 0000000..02db303
--- /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 async Task> UploadAvatar([FromForm] UploadAvatarInputDto inputDto, IFormFile file)
+ {
+ return await _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/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/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/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/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.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/Extensions/PermissionSyncExtensions.cs b/EOM.TSHotelManagement.API/Extensions/PermissionSyncExtensions.cs
index 53b4718..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();
@@ -104,7 +102,9 @@ namespace EOM.TSHotelManagement.WebApi
// 默认将所有扫描到的权限与超级管理员角色关联
// 如角色不存在,DatabaseInitializer 已负责创建;此处仅做映射补齐
var existingRolePerms = db.Queryable()
- .Where(rp => rp.RoleNumber == AdminRoleNumber && rp.IsDelete != 1)
+ .Where(rp => rp.RoleNumber == AdminRoleNumber
+ && rp.PermissionNumber != null
+ && rp.PermissionNumber != "")
.Select(rp => rp.PermissionNumber)
.ToList();
@@ -121,7 +121,6 @@ namespace EOM.TSHotelManagement.WebApi
{
RoleNumber = AdminRoleNumber,
PermissionNumber = p,
- IsDelete = 0,
DataInsUsr = "System",
DataInsDate = now
}).ToList();
@@ -161,4 +160,4 @@ namespace EOM.TSHotelManagement.WebApi
return "api";
}
}
-}
\ No newline at end of file
+}
diff --git a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs
index 14b066a..083b0c1 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,35 @@ namespace EOM.TSHotelManagement.WebApi
services.AddQuartz(q =>
{
var jobs = configuration.GetSection(SystemConstant.JobKeys.Code).Get() ?? Array.Empty();
+ var jobRegistrations = new Dictionary>(StringComparer.OrdinalIgnoreCase)
+ {
+ [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)
+ foreach (var job in jobs.Where(a => !string.IsNullOrWhiteSpace(a)).Distinct(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} 定时作业"));
-
- q.AddTrigger(opts => opts
- .ForJob(redisJobKey)
- .WithIdentity($"{redisJobKey}-Trigger")
- //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次
- .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次
+ var (jobName, cronExpression) = ParseJobRegistration(job);
+ if (!registeredJobs.Add(jobName))
+ {
+ 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);
}
});
@@ -121,6 +100,41 @@ 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));
+ }
+
+ 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/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.API/appsettings.Application.json b/EOM.TSHotelManagement.API/appsettings.Application.json
index b77796a..f5f5b47 100644
--- a/EOM.TSHotelManagement.API/appsettings.Application.json
+++ b/EOM.TSHotelManagement.API/appsettings.Application.json
@@ -12,9 +12,17 @@
],
"AllowedHosts": "*",
"JobKeys": [
- "ReservationExpirationCheckJob",
- "MailServiceCheckJob",
- "RedisServiceCheckJob"
+ // 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.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/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.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/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/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/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/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/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.Common/Helper/RedisHelper.cs b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs
index 1238879..52b26ca 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,13 +75,27 @@ 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()
{
+ 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();
@@ -86,12 +117,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 +171,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/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.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 94%
rename from EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs
rename to EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/ReservationExpirationCheckJob.cs
index 6431906..04f1299 100644
--- a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs
+++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/BusinessJob/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/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs
new file mode 100644
index 0000000..36e670c
--- /dev/null
+++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/ReadFavoriteCollectionOutputDto.cs
@@ -0,0 +1,23 @@
+namespace EOM.TSHotelManagement.Contract
+{
+ ///
+ /// 读取收藏夹响应 DTO
+ ///
+ public class ReadFavoriteCollectionOutputDto
+ {
+ ///
+ /// 收藏路由列表
+ ///
+ public List FavoriteRoutes { get; set; } = new();
+
+ ///
+ /// 收藏夹最后更新时间
+ ///
+ public DateTime? UpdatedAt { get; set; }
+
+ ///
+ /// 当前快照版本号
+ ///
+ public long? RowVersion { get; set; }
+ }
+}
\ No newline at end of file
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..55ec5b6
--- /dev/null
+++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionInputDto.cs
@@ -0,0 +1,44 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace EOM.TSHotelManagement.Contract
+{
+ ///
+ /// 保存收藏夹请求 DTO
+ ///
+ public class SaveFavoriteCollectionInputDto
+ {
+ ///
+ /// 乐观锁版本号,更新已有快照时必填
+ ///
+ public long? RowVersion { get; set; }
+
+ ///
+ /// 登录类型,前端可能传 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; }
+ }
+}
\ No newline at end of file
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..eaceb54
--- /dev/null
+++ b/EOM.TSHotelManagement.Contract/Application/FavoriteCollection/Dto/SaveFavoriteCollectionOutputDto.cs
@@ -0,0 +1,28 @@
+namespace EOM.TSHotelManagement.Contract
+{
+ ///
+ /// 保存收藏夹响应 DTO
+ ///
+ public class SaveFavoriteCollectionOutputDto
+ {
+ ///
+ /// 是否保存成功
+ ///
+ public bool Saved { get; set; }
+
+ ///
+ /// 保存后的收藏数量
+ ///
+ public int RouteCount { get; set; }
+
+ ///
+ /// 最终生效的更新时间
+ ///
+ public DateTime UpdatedAt { get; set; }
+
+ ///
+ /// 保存成功后的最新版本号
+ ///
+ public long RowVersion { get; set; }
+ }
+}
\ No newline at end of file
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..ea9e96d
--- /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 Name { 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.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/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.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.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.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.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.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.Data/DatabaseInitializer/DatabaseInitializer.cs b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs
index e86d9cf..5e931f8 100644
--- a/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs
+++ b/EOM.TSHotelManagement.Data/DatabaseInitializer/DatabaseInitializer.cs
@@ -102,7 +102,6 @@ namespace EOM.TSHotelManagement.Data
.ToArray();
db.CodeFirst.InitTables(needCreateTableTypes);
- EnsureTwoFactorForeignKeys(db, dbSettings.DbType);
Console.WriteLine("Database schema initialized");
@@ -259,58 +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 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 void SeedInitialData(ISqlSugarClient db)
{
Console.WriteLine("Initializing database data...");
@@ -333,10 +280,10 @@ namespace EOM.TSHotelManagement.Data
PassportType _ => 6,
Menu _ => 7,
NavBar _ => 8,
- SystemInformation _ => 9,
- PromotionContent _ => 10,
- Administrator _ => 11,
- Employee _ => 12,
+ PromotionContent _ => 9,
+ Administrator _ => 10,
+ Employee _ => 11,
+ UserFavoriteCollection _ => 12,
_ => 99
})
.ToList();
@@ -373,10 +320,6 @@ namespace EOM.TSHotelManagement.Data
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;
@@ -401,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;
@@ -511,7 +458,7 @@ namespace EOM.TSHotelManagement.Data
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)
{
@@ -519,7 +466,6 @@ namespace EOM.TSHotelManagement.Data
{
UserNumber = adminUser.Number,
RoleNumber = adminRoleNumber,
- IsDelete = 0,
DataInsUsr = "System",
DataInsDate = DateTime.Now
}).ExecuteCommand();
@@ -533,12 +479,13 @@ namespace EOM.TSHotelManagement.Data
// 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)
+ .Where(rp => rp.RoleNumber == adminRoleNumber
+ && rp.PermissionNumber != null
+ && rp.PermissionNumber != "")
.Select(rp => rp.PermissionNumber)
.ToList();
@@ -554,7 +501,6 @@ namespace EOM.TSHotelManagement.Data
{
RoleNumber = adminRoleNumber,
PermissionNumber = p!,
- IsDelete = 0,
DataInsUsr = "System",
DataInsDate = DateTime.Now
}).ToList();
@@ -650,4 +596,3 @@ namespace EOM.TSHotelManagement.Data
#endregion
}
}
-
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.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/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.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..4435c37 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)
@@ -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/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..6c49b2e 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 : 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/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/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/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/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/Employee/Employee.cs b/EOM.TSHotelManagement.Domain/Employee/Employee.cs
index 77db185..1b16746 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 : 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/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..1b52c3d 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 : 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.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.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 b2737df..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)
@@ -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.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.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/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.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 97c460d..4393fad 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),
@@ -52,6 +53,7 @@ namespace EOM.TSHotelManagement.Migration
typeof(Menu),
typeof(Nation),
typeof(NavBar),
+ typeof(UserFavoriteCollection),
typeof(OperationLog),
typeof(Position),
typeof(PromotionContent),
@@ -65,7 +67,6 @@ namespace EOM.TSHotelManagement.Migration
typeof(SellThing),
typeof(Spend),
typeof(SupervisionStatistics),
- typeof(SystemInformation),
typeof(UserRole),
typeof(VipLevelRule),
typeof(RequestLog),
@@ -87,11 +88,20 @@ namespace EOM.TSHotelManagement.Migration
},
new Administrator
{
- Number = "1263785187301658678",
+ Number = "AD-202005060001",
Account = "admin",
Password = string.Empty,
- Name = "Administrator",
+ 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",
@@ -483,6 +493,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 = "我的",
@@ -493,7 +514,7 @@ namespace EOM.TSHotelManagement.Migration
DataInsUsr = "System",
DataInsDate = DateTime.Now,
},
- new Menu // 37
+ new Menu // 38
{
Key = "dashboard",
Title = "仪表盘",
@@ -504,7 +525,7 @@ namespace EOM.TSHotelManagement.Migration
DataInsUsr = "System",
DataInsDate = DateTime.Now,
},
- new Menu // 38
+ new Menu // 39
{
Key = "promotioncontent",
Title = "宣传联动内容",
@@ -515,7 +536,7 @@ namespace EOM.TSHotelManagement.Migration
DataInsUsr = "System",
DataInsDate = DateTime.Now,
},
- new Menu // 39
+ new Menu // 40
{
Key = "requestlog",
Title = "请求日志",
@@ -530,7 +551,7 @@ namespace EOM.TSHotelManagement.Migration
{
NavigationBarName = "客房管理",
NavigationBarOrder = 1,
- NavigationBarImage = null,
+ NavigationBarImage = string.Empty,
NavigationBarEvent = "RoomManager_Event",
IsDelete = 0,
MarginLeft = 0,
@@ -541,7 +562,7 @@ namespace EOM.TSHotelManagement.Migration
{
NavigationBarName = "客户管理",
NavigationBarOrder = 2,
- NavigationBarImage = null,
+ NavigationBarImage = string.Empty,
NavigationBarEvent = "CustomerManager_Event",
IsDelete = 0,
MarginLeft = 120,
@@ -552,7 +573,7 @@ namespace EOM.TSHotelManagement.Migration
{
NavigationBarName = "商品消费",
NavigationBarOrder = 3,
- NavigationBarImage = null,
+ NavigationBarImage = string.Empty,
NavigationBarEvent = "SellManager_Event",
IsDelete = 0,
MarginLeft = 120,
@@ -605,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",
@@ -625,10 +646,17 @@ namespace EOM.TSHotelManagement.Migration
DataInsUsr = "System",
DataInsDate = DateTime.Now
},
- new SystemInformation
+ new UserFavoriteCollection
{
- UrlNumber = 1,
- UrlAddress = "https://gitee.com/java-and-net/TopskyHotelManagerSystem/releases",
+ UserNumber = "WK010",
+ LoginType = "employee",
+ Account = "WK010",
+ FavoriteRoutesJson = "[\"/roommap\"]",
+ RouteCount = 1,
+ UpdatedAt = DateTime.UtcNow,
+ TriggeredBy = "seed",
+ DataInsUsr = "System",
+ DataInsDate = DateTime.Now
},
new PromotionContent
{
@@ -666,251 +694,288 @@ 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, 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 = "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, 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 = "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, 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 },
// 职位
- 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, 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 },
// 学历
- 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, 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 = "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, 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 },
+
+ // 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 },
+ 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 },
+ // 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, 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 },
- // 公告类型
- 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, 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 },
- // 宣传联动内容
- 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, 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 },
+
+ // Room information (客房信息管理)
+ // 房间管理
+ 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.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 },
+ 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, 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 = "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, 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 },
+ 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 },
- // 房间配置管理
- 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, 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 },
+ 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, 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 },
+ 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, 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 },
+
+ // 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, 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 },
+ 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 = "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, 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 = "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, 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 = "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, 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 = "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, 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 },
- // 监管统计信息管理
- 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, 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 },
+ new Permission { PermissionNumber = "goodsmanagement.ust", PermissionName = "修改商品", Module = "material", Description = "修改商品", MenuKey = "goodsmanagement", ParentNumber = null, DataInsUsr = "System", DataInsDate = DateTime.Now },
- // 管理员管理
- 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 },
+ // 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 },
+
+ // System management (系统管理)
+ // 管理员管理
+ 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 },
// 管理员两步验证管理
- 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: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: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 },
+ 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, 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 },
- // 管理员-角色权限管理(网页端)
- 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: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 = "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, 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, 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/Application/FavoriteCollection/FavoriteCollectionService.cs b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs
new file mode 100644
index 0000000..b78b673
--- /dev/null
+++ b/EOM.TSHotelManagement.Service/Application/FavoriteCollection/FavoriteCollectionService.cs
@@ -0,0 +1,433 @@
+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();
+ if (currentUser == null)
+ {
+ return new SingleOutputDto
+ {
+ Code = BusinessStatusCode.Unauthorized,
+ Message = LocalizationHelper.GetLocalizedString("Unauthorized.", "Unauthorized."),
+ Data = null
+ };
+ }
+
+ if (!TryValidateRequestedIdentity(currentUser, input, out var forbiddenResponse))
+ {
+ return forbiddenResponse!;
+ }
+
+ var normalizedRoutes = NormalizeRoutes(input.FavoriteRoutes);
+ var normalizedUpdatedAt = NormalizeUpdatedAt(input.UpdatedAt);
+ var normalizedTriggeredBy = NormalizeText(input.TriggeredBy, 32);
+ var favoriteRoutesJson = JsonSerializer.Serialize(normalizedRoutes, JsonSerializerOptions);
+ var saveResult = TrySaveSnapshot(currentUser, input.RowVersion, favoriteRoutesJson, normalizedRoutes.Count, normalizedUpdatedAt, normalizedTriggeredBy);
+
+ if (saveResult.Outcome == SaveSnapshotOutcome.Conflict)
+ {
+ return new SingleOutputDto
+ {
+ Code = BusinessStatusCode.Conflict,
+ Message = LocalizationHelper.GetLocalizedString(
+ "Data has been modified by another user. Please refresh and retry.",
+ "数据已被其他用户修改,请刷新后重试。"),
+ Data = null
+ };
+ }
+
+ if (saveResult.Outcome == SaveSnapshotOutcome.Failed)
+ {
+ 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,
+ RowVersion = saveResult.RowVersion
+ }
+ };
+ }
+ 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),
+ RowVersion = collection.RowVersion
+ }
+ };
+ }
+ 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 SaveSnapshotResult TrySaveSnapshot(
+ CurrentUserSnapshot currentUser,
+ long? rowVersion,
+ string favoriteRoutesJson,
+ int routeCount,
+ DateTime updatedAt,
+ string? triggeredBy)
+ {
+ const int maxInsertRetryCount = 2;
+
+ for (var attempt = 1; attempt <= maxInsertRetryCount; attempt++)
+ {
+ var existing = _favoriteCollectionRepository.GetFirst(x => x.UserNumber == currentUser.UserNumber);
+
+ if (existing == null)
+ {
+ if (rowVersion.HasValue && rowVersion.Value > 0)
+ {
+ _logger.LogWarning(
+ "Favorite collection insert rejected because client provided stale row version {RowVersion} for user {UserNumber}.",
+ rowVersion.Value,
+ currentUser.UserNumber);
+ return new SaveSnapshotResult(SaveSnapshotOutcome.Conflict);
+ }
+
+ 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 new SaveSnapshotResult(SaveSnapshotOutcome.Saved, entity.RowVersion);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(
+ ex,
+ "Insert favorite collection snapshot failed on attempt {Attempt} for user {UserNumber}.",
+ attempt,
+ currentUser.UserNumber);
+ }
+
+ continue;
+ }
+
+ if (!rowVersion.HasValue || rowVersion.Value <= 0)
+ {
+ _logger.LogWarning(
+ "Favorite collection update rejected because row version is missing for user {UserNumber}. CurrentRowVersion={CurrentRowVersion}.",
+ currentUser.UserNumber,
+ existing.RowVersion);
+ return new SaveSnapshotResult(SaveSnapshotOutcome.Conflict);
+ }
+
+ existing.RowVersion = rowVersion.Value;
+ 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 new SaveSnapshotResult(SaveSnapshotOutcome.Saved, existing.RowVersion);
+ }
+
+ _logger.LogWarning(
+ "Favorite collection update hit a concurrency conflict for user {UserNumber}. ExpectedRowVersion={ExpectedRowVersion}.",
+ currentUser.UserNumber,
+ rowVersion.Value);
+ return new SaveSnapshotResult(SaveSnapshotOutcome.Conflict);
+ }
+
+ return new SaveSnapshotResult(SaveSnapshotOutcome.Failed);
+ }
+
+ private bool TryValidateRequestedIdentity(
+ CurrentUserSnapshot currentUser,
+ SaveFavoriteCollectionInputDto input,
+ out SingleOutputDto? forbiddenResponse)
+ {
+ forbiddenResponse = null;
+
+ var requestAccount = NormalizeText(input.Account, 128);
+ if (!string.IsNullOrWhiteSpace(requestAccount) && !IsCurrentAccount(currentUser, requestAccount))
+ {
+ _logger.LogWarning(
+ "Favorite collection request account mismatch. UserNumber={UserNumber}, RequestAccount={RequestAccount}, ResolvedAccount={ResolvedAccount}.",
+ currentUser.UserNumber,
+ requestAccount,
+ currentUser.Account);
+
+ forbiddenResponse = new SingleOutputDto
+ {
+ Code = BusinessStatusCode.Forbidden,
+ Message = LocalizationHelper.GetLocalizedString(
+ "Requested identity does not match current user.",
+ "请求身份与当前登录用户不一致。"),
+ Data = null
+ };
+
+ return false;
+ }
+
+ var requestLoginType = NormalizeText(input.LoginType, 32);
+ if (!string.IsNullOrWhiteSpace(requestLoginType)
+ && !string.Equals(requestLoginType, currentUser.LoginType, StringComparison.OrdinalIgnoreCase))
+ {
+ _logger.LogWarning(
+ "Favorite collection request login type mismatch. UserNumber={UserNumber}, RequestLoginType={RequestLoginType}, ResolvedLoginType={ResolvedLoginType}.",
+ currentUser.UserNumber,
+ requestLoginType,
+ currentUser.LoginType);
+
+ forbiddenResponse = new SingleOutputDto
+ {
+ Code = BusinessStatusCode.Forbidden,
+ Message = LocalizationHelper.GetLocalizedString(
+ "Requested identity does not match current user.",
+ "请求身份与当前登录用户不一致。"),
+ Data = null
+ };
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private CurrentUserSnapshot? ResolveCurrentUser()
+ {
+ 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 fallbackAccount = NormalizeText(
+ principal?.FindFirst("account")?.Value ?? principal?.Identity?.Name,
+ 128);
+ var loginType = NormalizeText(
+ principal?.FindFirst("login_type")?.Value ?? principal?.FindFirst("logintype")?.Value,
+ 32) ?? "unknown";
+
+ return new CurrentUserSnapshot(userNumber, loginType, fallbackAccount);
+ }
+
+ private static bool IsCurrentAccount(CurrentUserSnapshot currentUser, string requestAccount)
+ {
+ return string.Equals(requestAccount, currentUser.Account, StringComparison.OrdinalIgnoreCase)
+ || string.Equals(requestAccount, currentUser.UserNumber, StringComparison.OrdinalIgnoreCase);
+ }
+
+ 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);
+ private sealed record SaveSnapshotResult(SaveSnapshotOutcome Outcome, long RowVersion = 0);
+
+ private enum SaveSnapshotOutcome
+ {
+ Saved,
+ Conflict,
+ Failed
+ }
+ }
+}
\ No newline at end of file
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();
+ }
+}
diff --git a/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs b/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs
new file mode 100644
index 0000000..13c277d
--- /dev/null
+++ b/EOM.TSHotelManagement.Service/Application/Profile/IProfileService.cs
@@ -0,0 +1,15 @@
+using EOM.TSHotelManagement.Contract;
+using Microsoft.AspNetCore.Http;
+using System.Threading.Tasks;
+
+namespace EOM.TSHotelManagement.Service
+{
+ public interface IProfileService
+ {
+ SingleOutputDto GetCurrentProfile(string serialNumber);
+
+ Task> 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..6ce6888
--- /dev/null
+++ b/EOM.TSHotelManagement.Service/Application/Profile/ProfileService.cs
@@ -0,0 +1,586 @@
+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;
+using System.Threading.Tasks;
+
+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 async Task> 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 = await UploadImageAsync(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
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;
}
@@ -78,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
@@ -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 })
+ .Where(x => x.RoleNumber == input.RoleNumber)
.ToList();
-
- foreach (var rp in existing)
+ if (existing.Count > 0)
{
- rolePermissionRepository.SoftDelete(rp);
+ rolePermissionRepository.Delete(existing);
}
// 过滤去重并忽略空白权限码
@@ -233,14 +249,52 @@ 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 => 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,
- IsDelete = 0
+ MenuId = null
+ };
+ rolePermissionRepository.Insert(entity);
+ }
+
+ // 写入角色-菜单映射
+ foreach (var menuId in validMenuIds)
+ {
+ var entity = new RolePermission
+ {
+ RoleNumber = input.RoleNumber,
+ MenuId = menuId,
+ PermissionNumber = null
};
rolePermissionRepository.Insert(entity);
}
@@ -272,7 +326,9 @@ namespace EOM.TSHotelManagement.Service
try
{
var list = rolePermissionRepository.AsQueryable()
- .Where(rp => rp.RoleNumber == roleNumber && rp.IsDelete != 1)
+ .Where(rp => rp.RoleNumber == roleNumber
+ && rp.PermissionNumber != null
+ && rp.PermissionNumber != "")
.Select(rp => rp.PermissionNumber)
.ToList() ?? new List();
@@ -299,6 +355,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)
+ .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()
+ }
+ };
+ }
+ }
+
///
/// 读取隶属于指定角色的管理员用户编码集合
///
@@ -317,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();
@@ -365,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)
@@ -387,8 +511,7 @@ namespace EOM.TSHotelManagement.Service
var entity = new UserRole
{
RoleNumber = input.RoleNumber,
- UserNumber = u,
- IsDelete = 0
+ UserNumber = u
};
userRoleRepository.Insert(entity);
}
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);
}
diff --git a/README.en.md b/README.en.md
index 424be9c..88d4a10 100644
--- a/README.en.md
+++ b/README.en.md
@@ -8,6 +8,7 @@
## Project Overview
@@ -193,12 +194,20 @@ 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|
+|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..ba8b8cb 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@
## 项目简介
@@ -193,12 +194,20 @@ 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|
+|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 274418f8989c13894910d86f00817b35afdf178e Mon Sep 17 00:00:00 2001
From: ck_yeun9
Date: Sat, 21 Mar 2026 11:05:15 +0000
Subject: [PATCH 2/7] =?UTF-8?q?!60=20=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
* 修复阻断项
* 修复阻断项
* 修复阻断项
* 添加swagger版本标签进行区分。
* 添加员工履历新增、更新接口。
* 房间管理应增加区域或楼层,不同区域的房间号可能是重复的,房态中应按区域或楼层区分排列,前台客服可高效定位到房间.
* merge from remote.
* 房间唯一标识升级:支持RoomId/分区/楼层定位
* 新增项目 Wiki 链接至中英文 README 顶部
* 重构客户消费DTO与接口,统一版本号获取方式
* 统一人员字段抽象为Personnel基类,重构相关代码
* 新增个人中心功能及相关底层优化
* 新增职位导出权限配置
* 导出权限、分页优化及员工打卡业务重构
* 实现收藏夹功能,包括保存和获取用户收藏夹快照的接口及服务
* 添加定时任务列表接口。
* 增强Redis配置与定时任务,新增会员等级自动升级
* 优化预约房间业务流程。
* 修改表结构
* 将权限分配的数据,从软删除改为硬删除,节省表空间
* 剥离菜单与权限代码授权逻辑。
---
.../Customer/CustomerAccountController.cs | 1 +
.../Business/News/NewsController.cs | 1 +
.../Business/Room/RoomController.cs | 7 +
.../History/EmployeeHistoryController.cs | 13 +-
.../Extensions/ApplicationExtensions.cs | 1 +
.../Extensions/ClientApiGroupConvention.cs | 110 ++
.../Extensions/ServiceExtensions.cs | 71 +
.../Filters/BusinessOperationAuditFilter.cs | 450 +++++
.../Dto/CreateEnergyManagementInputDto.cs | 20 +-
.../Dto/ReadEnergyManagementInputDto.cs | 6 +-
.../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 | 8 +-
.../Business/Room/Dto/CheckoutRoomDto.cs | 6 +-
.../Room/Dto/Room/CreateRoomInputDto.cs | 2 +
.../Room/Dto/Room/ReadRoomInputDto.cs | 6 +-
.../Room/Dto/Room/ReadRoomOutputDto.cs | 15 +
.../Room/Dto/Room/ReadRoomPricingOutputDto.cs | 21 +
.../Room/Dto/Room/UpdateRoomInputDto.cs | 10 +-
.../Dto/RoomType/CreateRoomTypeInputDto.cs | 1 +
.../Room/Dto/RoomType/ReadRoomTypeInputDto.cs | 3 +
.../Dto/RoomType/ReadRoomTypeOutputDto.cs | 1 +
.../Dto/RoomType/RoomTypePricingItemDto.cs | 13 +
.../Dto/RoomType/UpdateRoomTypeInputDto.cs | 1 +
.../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 +-
.../ReadEmployeeCheckOutputDto.cs | 12 +-
.../CreateEmployeeHistoryInputDto.cs | 31 +-
.../UpdateEmployeeHistoryInputDto.cs | 33 +-
.../EnergyManagement/EnergyManagement.cs | 7 +-
.../Business/Reser/Reser.cs | 3 +
.../Business/Room/Room.cs | 180 +-
.../Business/Room/RoomType.cs | 8 +
.../Business/Spend/Spend.cs | 3 +
.../Employee/EmployeeCheck.cs | 6 -
.../Constant/CodeConstantBase.cs | 53 +-
.../EntityBuilder.cs | 1 +
.../EnergyManagementService.cs | 249 +--
.../Business/Reser/ReserService.cs | 526 +++---
.../Business/Room/IRoomService.cs | 9 +-
.../Business/Room/RoomLocatorHelper.cs | 101 ++
.../Business/Room/RoomPricingEvaluation.cs | 14 +
.../Business/Room/RoomPricingHelper.cs | 117 ++
.../Business/Room/RoomReferenceHelper.cs | 64 +
.../Business/Room/RoomService.cs | 1564 +++++++++--------
.../Business/Room/RoomTypeService.cs | 92 +-
.../Business/Spend/SpendService.cs | 567 +++---
.../Dashboard/DashboardService.cs | 2 +-
.../Employee/Check/EmployeeCheckService.cs | 7 +-
.../History/EmployeeHistoryService.cs | 29 +-
.../History/IEmployeeHistoryService.cs | 11 +-
59 files changed, 2943 insertions(+), 1647 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/RoomLocatorHelper.cs
create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomPricingEvaluation.cs
create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomPricingHelper.cs
create mode 100644 EOM.TSHotelManagement.Service/Business/Room/RoomReferenceHelper.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 a74afed..d8e0890 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.update")]
+ [HttpPost]
+ public BaseResponse UpdateHistoryByEmployeeId([FromBody] UpdateEmployeeHistoryInputDto workerHistory)
+ {
+ return workerHistoryService.UpdateHistoryByEmployeeId(workerHistory);
+ }
+
///
/// 根据工号查询履历信息
///
@@ -43,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..d357abf
--- /dev/null
+++ b/EOM.TSHotelManagement.API/Filters/BusinessOperationAuditFilter.cs
@@ -0,0 +1,450 @@
+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.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",
+ "Utility",
+ "CustomerAccount",
+ "News"
+ };
+
+ private static readonly string[] ReadOnlyActionPrefixes =
+ {
+ "Select",
+ "Read",
+ "Get",
+ "Build"
+ };
+
+ private static readonly string[] SensitivePropertyKeywords =
+ {
+ "password",
+ "token",
+ "secret",
+ "recoverycode",
+ "verificationcode",
+ "otp",
+ "creditcard",
+ "ssn",
+ "bankaccount",
+ "phonenumber"
+ };
+
+ 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 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(httpContext);
+ var operationAccount = ClaimsPrincipalExtensions.GetUserNumber(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 = 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)
+ {
+ 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;
+ }
+
+ private static string BuildLogContent(
+ bool isChinese,
+ string statusText,
+ string method,
+ string path,
+ string operationAccount,
+ string argumentSummary,
+ 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", "无")
+ : SanitizeForLog(responseMessage, 300);
+
+ var content = Localize(
+ isChinese,
+ $"{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)
+ {
+ 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 => $"{SanitizeForLog(a.Key, 60)}={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)
+ {
+ var safeFileName = SanitizeForLog(file.FileName, 120);
+ return Localize(
+ isChinese,
+ $"File({safeFileName}, {file.Length} bytes)",
+ $"文件({safeFileName}, {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 ? Localize(isChinese, "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 type = value.GetType();
+ var properties = GetCachedProperties(type)
+ .Take(8)
+ .Select(p =>
+ {
+ object propertyValue;
+ try
+ {
+ propertyValue = p.GetValue(value);
+ }
+ catch
+ {
+ return null;
+ }
+
+ if (propertyValue == null)
+ {
+ return null;
+ }
+
+ var safePropertyName = SanitizeForLog(p.Name, 60);
+
+ if (IsSensitive(p.Name))
+ {
+ return $"{safePropertyName}=***";
+ }
+
+ if (propertyValue is IFormFile file)
+ {
+ var safeFileName = SanitizeForLog(file.FileName, 120);
+ return Localize(
+ isChinese,
+ $"{safePropertyName}=File({safeFileName}, {file.Length} bytes)",
+ $"{safePropertyName}=文件({safeFileName}, {file.Length} 字节)");
+ }
+
+ if (IsSimpleValue(propertyValue.GetType()))
+ {
+ return $"{safePropertyName}={FormatSimpleValue(propertyValue)}";
+ }
+
+ if (propertyValue is IEnumerable enumerable && propertyValue is not string)
+ {
+ return $"{safePropertyName}={SummarizeEnumerable(enumerable, isChinese)}";
+ }
+
+ return null;
+ })
+ .Where(s => !string.IsNullOrWhiteSpace(s))
+ .ToList();
+
+ var safeTypeName = SanitizeForLog(type.Name, 80);
+ return properties.Count == 0
+ ? 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)
+ {
+ 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 SanitizeForLog(formatted, 120);
+ }
+
+ private static string TrimLogContent(string content, bool isChinese)
+ {
+ if (string.IsNullOrWhiteSpace(content))
+ {
+ return Localize(isChinese, "Operation audit log", "业务操作审计日志");
+ }
+
+ return SanitizeForLog(content, 1900);
+ }
+
+ 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/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..a23f97f 100644
--- a/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs
+++ b/EOM.TSHotelManagement.Contract/Business/EnergyManagement/Dto/ReadEnergyManagementInputDto.cs
@@ -5,11 +5,11 @@ 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; }
+ public DateTime? StartDate { get; set; }
- public DateOnly? EndDate { get; set; }
+ public DateTime? EndDate { 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..2c634c6 100644
--- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs
+++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/CheckinRoomByReservationDto.cs
@@ -30,8 +30,14 @@ 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; }
+ 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/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..d7fc935 100644
--- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs
+++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/ReadRoomInputDto.cs
@@ -2,11 +2,15 @@
{
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; }
- 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 281357c..1d7a3da 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; }
@@ -14,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 e5caef7..a9e3142 100644
--- a/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs
+++ b/EOM.TSHotelManagement.Contract/Business/Room/Dto/Room/UpdateRoomInputDto.cs
@@ -2,16 +2,18 @@ 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; }
- 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/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/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.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.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/Business/EnergyManagement/EnergyManagement.cs b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs
index d12bc48..32c2891 100644
--- a/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs
+++ b/EOM.TSHotelManagement.Domain/Business/EnergyManagement/EnergyManagement.cs
@@ -51,17 +51,20 @@ 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)
///
[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/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..00ca7b2 100644
--- a/EOM.TSHotelManagement.Domain/Business/Room/Room.cs
+++ b/EOM.TSHotelManagement.Domain/Business/Room/Room.cs
@@ -1,177 +1,165 @@
-/*
- * 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
+ Length = 128,
+ UniqueGroupNameList = new[] { "UK_room_number_area_floor" }
)]
-
public string RoomNumber { get; set; }
- ///
- /// 房间类型ID (Room Type ID)
- ///
+ [SugarColumn(
+ ColumnName = "room_area",
+ ColumnDescription = "Room area",
+ IsNullable = true,
+ Length = 128,
+ UniqueGroupNameList = new[] { "UK_room_number_area_floor" }
+ )]
+ public string RoomArea { get; set; }
+
+ [SugarColumn(
+ ColumnName = "room_floor",
+ ColumnDescription = "Room floor",
+ IsNullable = true,
+ UniqueGroupNameList = new[] { "UK_room_number_area_floor" }
+ )]
+ 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; }
+ public DateTime? 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; }
+ public DateTime? 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 = "房间位置描述 (如楼层+门牌号)",
+ ColumnName = "applied_room_rent",
+ ColumnDescription = "Applied room rent for current stay",
IsNullable = false,
- Length = 200
+ 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",
+ 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/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.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.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.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 4393fad..01aa42a 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.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 09b7d43..f01101f 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 = input.StartDate;
+ entity.EndDate = 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 = input.StartDate;
+ entity.EndDate = 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,
+ EndDate = source.EndDate,
+ 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/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/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/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/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..7694296 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,351 @@ 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)
- {
- query = query.Where(whereExpression);
- }
-
- 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
+ var roomResult = ResolveRoom(readRoomInputDto);
+ if (roomResult.Room == null)
{
- rooms = query.ToList();
- count = rooms.Count;
+ return CreateRoomLookupFailureOutput(roomResult, readRoomInputDto?.RoomNumber, readRoomInputDto?.RoomArea, readRoomInputDto?.RoomFloor);
}
- 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)
+ var lastCheckInTime = NormalizeStayDateTime(roomResult.Room.LastCheckInTime);
+ if (lastCheckInTime.HasValue)
{
- var days = Math.Abs((room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - DateTime.Now).Days);
+ var days = CalculateStayDays(lastCheckInTime.Value, DateTime.Now);
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.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;
- 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()
+ public SingleOutputDto SelectCanUseRoomAllByRoomState() => CountByState(RoomState.Vacant, count => new ReadRoomOutputDto { Vacant = count });
+
+ public SingleOutputDto SelectNotUseRoomAllByRoomState() => CountByState(RoomState.Occupied, count => new ReadRoomOutputDto { Occupied = count });
+
+ public object SelectRoomByRoomPrice(ReadRoomInputDto readRoomInputDto)
{
- try
+ var roomResult = ResolveRoom(readRoomInputDto);
+ if (roomResult.Room == null)
{
- 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
- };
+ return 0M;
}
- }
- ///
- /// 查询已入住房间数量
- ///
- ///
- public SingleOutputDto SelectNotUseRoomAllByRoomState()
- {
- try
+ if (string.IsNullOrWhiteSpace(readRoomInputDto?.PricingCode))
{
- var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Occupied && a.IsDelete != 1);
- return new SingleOutputDto
- {
- Data = new ReadRoomOutputDto { Occupied = count }
- };
+ return GetEffectiveRoomRent(roomResult.Room);
}
- catch (Exception ex)
+
+ var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == roomResult.Room.RoomTypeId && a.IsDelete != 1);
+ if (roomType == null)
{
- return new SingleOutputDto
- {
- Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
- Code = BusinessStatusCode.InternalServerError
- };
+ return 0M;
}
- }
- ///
- /// 根据房间编号查询房间价格
- ///
- ///
- public object SelectRoomByRoomPrice(ReadRoomInputDto r)
- {
- return roomRepository.GetFirst(a => a.RoomNumber == r.RoomNumber).RoomRent;
+ var pricingItem = RoomPricingHelper.ResolvePricingItem(roomType.RoomRent, roomType.RoomDeposit, roomType.PricingItemsJson, readRoomInputDto.PricingCode);
+ return pricingItem?.RoomRent ?? 0M;
}
- ///
- /// 查询脏房数量
- ///
- ///
- public SingleOutputDto SelectNotClearRoomAllByRoomState()
+ public SingleOutputDto SelectRoomPricingOptions(ReadRoomInputDto readRoomInputDto)
{
- try
+ var roomResult = ResolveRoom(readRoomInputDto);
+ Room room = null;
+ RoomType roomType = null;
+
+ if (roomResult.Room != null)
{
- var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Dirty && a.IsDelete != 1);
- return new SingleOutputDto
- {
- Data = new ReadRoomOutputDto { Dirty = count }
- };
+ room = roomResult.Room;
+ roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId && a.IsDelete != 1);
}
- catch (Exception ex)
+ else if (readRoomInputDto?.RoomTypeId > 0)
{
- return new SingleOutputDto
- {
- Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
- Code = BusinessStatusCode.InternalServerError
- };
+ roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == readRoomInputDto.RoomTypeId && a.IsDelete != 1);
}
- }
- ///
- /// 查询维修房数量
- ///
- ///
- public SingleOutputDto SelectFixingRoomAllByRoomState()
- {
- try
+ if (roomType == null)
{
- var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Maintenance && a.IsDelete != 1);
- return new SingleOutputDto
+ if (roomResult.IsAmbiguous)
{
- Data = new ReadRoomOutputDto { Maintenance = count }
- };
- }
- catch (Exception ex)
- {
- return new SingleOutputDto
+ return new SingleOutputDto
+ {
+ Code = BusinessStatusCode.Conflict,
+ Message = "Multiple rooms match the current room number.",
+ Data = new ReadRoomPricingOutputDto { PricingItems = new List() }
+ };
+ }
+
+ return new SingleOutputDto
{
- Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
- Code = BusinessStatusCode.InternalServerError
+ Code = BusinessStatusCode.NotFound,
+ Message = "Room type pricing not found.",
+ Data = new ReadRoomPricingOutputDto { PricingItems = new List() }
};
}
- }
- ///
- /// 查询预约房数量
- ///
- ///
- public SingleOutputDto SelectReservedRoomAllByRoomState()
- {
- try
+ 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)))
{
- var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Reserved && a.IsDelete != 1);
- return new SingleOutputDto
+ pricingItems.Add(new RoomTypePricingItemDto
{
- Data = new ReadRoomOutputDto { Reserved = count }
- };
+ PricingCode = room.RoomPricingCode,
+ PricingName = string.IsNullOrWhiteSpace(room.RoomPricingName) ? room.RoomPricingCode : room.RoomPricingName,
+ RoomRent = room.AppliedRoomRent,
+ RoomDeposit = room.AppliedRoomDeposit,
+ StayHours = room.PricingStayHours,
+ IsDefault = false
+ });
}
- catch (Exception ex)
+
+ 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
{
- return new SingleOutputDto
+ Data = new ReadRoomPricingOutputDto
{
- Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
- Code = BusinessStatusCode.InternalServerError
- };
- }
+ 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 });
+
+ public SingleOutputDto SelectFixingRoomAllByRoomState() => CountByState(RoomState.Maintenance, count => new ReadRoomOutputDto { Maintenance = count });
+
+ 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.LastCheckOutTime = DateOnly.MinValue;
+ entity.RoomNumber = normalizedRoomNumber;
+ entity.RoomArea = string.IsNullOrWhiteSpace(normalizedRoomArea) ? null : normalizedRoomArea;
+ entity.LastCheckInTime = null;
+ 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();
}
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 entity = EntityMapper.Map(rn);
- var updateResult = roomRepository.Update(entity);
- if (!updateResult)
+ 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);
+
+ 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 = NormalizeStayDateTime(rn.LastCheckInTime);
+ room.LastCheckOutTime = NormalizeStayDateTime(rn.LastCheckOutTime);
+ 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 +402,718 @@ 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 = CreateTransactionScope();
- 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);
+ 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 };
+ }
- 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 stayDays = CalculateStayDays(originalCheckInTime.Value, now);
+ 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 originalPricingEvaluation = EvaluateRoomPricing(originalRoom);
+ var originalEffectiveRent = originalPricingEvaluation.EffectiveRoomRent;
+ var originalRoomBill = originalEffectiveRent * stayDays * discount;
+
+ targetRoom.CustomerNumber = originalRoom.CustomerNumber;
+ targetRoom.RoomStateId = (int)RoomState.Occupied;
+ 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();
+ }
- //更新原房间状态
- 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();
- }
+ originalRoom.CustomerNumber = string.Empty;
+ originalRoom.RoomStateId = (int)RoomState.Dirty;
+ 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();
+ }
- //转移原房间消费记录
- if (originalSpendNumbers.Count > 0)
+ 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 =>
{
- 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();
- }
- }
-
- //添加旧房间消费记录
- var originalSpend = new Spend
+ spend.RoomId = targetRoom.Id;
+ spend.RoomNumber = targetRoom.RoomNumber;
+ });
+ if (!spendRepository.UpdateRange(spends))
{
- 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);
+ 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 = $"居住 {string.Join("/", originalRoom.RoomArea, originalRoom.RoomFloor, originalRoom.RoomNumber)} 共 {stayDays} 天",
+ ProductPrice = originalEffectiveRent,
+ ConsumptionTime = 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)
+ {
+ return new BaseResponse { Message = "RoomId is required", Code = BusinessStatusCode.BadRequest };
+ }
+
+ using var scope = CreateTransactionScope();
+
+ var customer = custoRepository.AsQueryable().Where(a => a.CustomerNumber == checkoutRoomDto.CustomerNumber && a.IsDelete != 1);
+ if (!customer.Any())
{
- 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 = "The customer does not exist", Code = BusinessStatusCode.InternalServerError };
+ }
+
+ var roomResult = ResolveRoom(checkoutRoomDto);
+ if (roomResult.Room == null)
+ {
+ return CreateRoomLookupFailure(roomResult, checkoutRoomDto?.RoomNumber, checkoutRoomDto?.RoomArea, checkoutRoomDto?.RoomFloor);
+ }
+
+ var room = roomResult.Room;
+ var now = DateTime.Now;
+ var checkinDate = NormalizeStayDateTime(room.LastCheckInTime);
+ var occupiedCustomerNumber = room.CustomerNumber;
+ var pricingEvaluation = EvaluateRoomPricing(room);
+ var effectiveRoomRent = pricingEvaluation.EffectiveRoomRent;
+
+ room.CustomerNumber = string.Empty;
+ 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();
+ }
- var room = roomRepository.GetFirst(a => a.RoomNumber == checkoutRoomDto.RoomNumber);
+ energyRepository.Insert(new EnergyManagement
+ {
+ InformationId = uniqueCode.GetNewId("EM-"),
+ StartDate = checkinDate ?? now,
+ EndDate = now,
+ WaterUsage = checkoutRoomDto.WaterUsage,
+ PowerUsage = checkoutRoomDto.ElectricityUsage,
+ Recorder = "System",
+ CustomerNumber = occupiedCustomerNumber,
+ RoomId = room.Id,
+ RoomNumber = room.RoomNumber,
+ IsDelete = 0
+ });
- var checkinDate = room.LastCheckInTime;
- var checkoutDate = room.LastCheckOutTime;
+ 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);
- //更新房间状态
- room.CustomerNumber = string.Empty;
- room.LastCheckInTime = DateOnly.MinValue;
- room.LastCheckOutTime = DateOnly.MinValue;
- room.RoomStateId = (int)RoomState.Dirty;
- var roomUpdateResult = roomRepository.Update(room);
- if (!roomUpdateResult)
+ if (unsettledSpends.Count > 0)
+ {
+ unsettledSpends.ForEach(spend => spend.SettlementStatus = ConsumptionConstant.Settled.Code);
+ if (!spendRepository.UpdateRange(unsettledSpends))
{
return BaseResponseFactory.ConcurrencyConflict();
}
+ }
- //添加能源使用记录
- 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 stayDays = CalculateStayDays(checkinDate ?? now, now);
+ 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 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 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();
- }
- }
+ var discount = customerType.Discount > 0 && customerType.Discount < 100 ? customerType.Discount / 100M : 1M;
+ var roomBill = effectiveRoomRent * stayDays * discount;
- // 插入住房消费记录
- 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);
+ spendRepository.Insert(new Spend
+ {
+ SpendNumber = uniqueCode.GetNewId("SP-"),
+ ProductName = $"居住 {string.Join("/", room.RoomArea, room.RoomFloor, room.RoomNumber)} 共 {stayDays} 天",
+ SettlementStatus = ConsumptionConstant.Settled.Code,
+ ConsumptionType = SpendTypeConstant.Room.Code,
+ ConsumptionQuantity = stayDays,
+ ConsumptionTime = now,
+ ProductNumber = room.RoomNumber,
+ ProductPrice = effectiveRoomRent,
+ ConsumptionAmount = roomBill,
+ CustomerNumber = occupiedCustomerNumber,
+ RoomId = room.Id,
+ RoomNumber = room.RoomNumber,
+ IsDelete = 0
+ });
- scope.Complete();
- }
+ 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 = CreateTransactionScope();
- 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 = 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();
}
+
+ 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(BuildRoomListOrderByClause());
+
+ 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 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()
+ .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)
+ {
+ var pricingEvaluation = EvaluateRoomPricing(source);
+ 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 = NormalizeStayDateTime(source.LastCheckInTime),
+ LastCheckOutTime = NormalizeStayDateTime(source.LastCheckOutTime),
+ RoomStateId = source.RoomStateId,
+ RoomState = roomStateMap.TryGetValue(source.RoomStateId, out var roomStateName) ? roomStateName : "",
+ 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,
+ 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 };
+ }
+
+ 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)
+ {
+ 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);
+ 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)
+ {
+ if (room?.PricingStayHours is not > 0)
+ {
+ return false;
+ }
+
+ var pricingStartTime = NormalizeStayDateTime(room.PricingStartTime)
+ ?? NormalizeStayDateTime(room.LastCheckInTime);
+ if (!pricingStartTime.HasValue)
+ {
+ return false;
+ }
+
+ 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;
+ 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 ebfadc0..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,
@@ -150,13 +152,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 = MapRoomTypeToOutput(roomType);
return new SingleOutputDto { Data = source };
}
#endregion
@@ -173,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)
{
@@ -192,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();
@@ -274,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 65eb0d6..c0d1fa0 100644
--- a/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs
+++ b/EOM.TSHotelManagement.Service/Business/Spend/SpendService.cs
@@ -1,286 +1,74 @@
-/*
- * 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 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,
+ ILogger logger)
{
this.spendRepository = spendRepository;
this.sellThingRepository = sellThingRepository;
this.roomRepository = roomRepository;
this.customerRepository = customerRepository;
this.custoTypeRepository = custoTypeRepository;
- this.operationLogRepository = operationLogRepository;
- _httpContextAccessor = httpContextAccessor;
this.logger = logger;
}
- #region 根据客户编号查询历史消费信息
- ///
- /// 根据客户编号查询历史消费信息
- ///
- ///
- ///
- public ListOutputDto SeletHistorySpendInfoAll(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);
- }
-
- 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();
-
- 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