From 91259046f6b3cebc14b278d0abde5d10c416178a Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 15:49:31 +0330 Subject: [PATCH] Revert "feat: introduce Shared.Contracts for account management and refactor related services" This reverts commit 9469a5f76ef94306f597eadc2ee6f209d2d7840d. --- ...untManagement.Application.Contracts.csproj | 1 - .../AccountManagementBootstrapper.cs | 3 - ...ountMangement.Infrastructure.EFCore.csproj | 2 - .../Services/AccountQueryService.cs | 49 ---- DadmehrGostar.sln | 250 ------------------ ...zareshgirProgramManager.Application.csproj | 1 - .../GetUserToGroupCreatingQueryHandler.cs | 72 ++--- .../TransferSectionCommandHandler.cs | 21 +- .../ProjectBoardListQueryHandler.cs | 12 +- .../ProjectSetTimeDetailsQueryHandler.cs | 22 +- .../CreateRole/CreateRoleCommandHandler.cs | 44 +++ .../EditRole/EditRoleCommandHandler.cs | 54 ++++ .../Queries/GetRoles/GetRolesQueryHandler.cs | 76 ++++++ .../GetSalarySettingToEditQueryHandler.cs | 38 ++- .../GetUserListWhoHaveSettingsQueryHandler.cs | 65 ++--- .../Commands/CreateUser/CreateUserCommand.cs | 5 + .../CreateUser/CreateUserCommandHandler.cs | 43 +++ .../CreateUser/CreateUserCommandValidators.cs | 24 ++ .../EditUser/EditUserCommandHandler.cs | 34 +++ .../Commands/LoginUser/LoginUserCommand.cs | 11 + .../LoginUser/LoginUserCommandHandler.cs | 98 +++++++ .../RefreshUserTokenCommand.cs | 11 + .../RefreshUserTokenCommandHandler.cs | 86 ++++++ .../SignOutUser/SignOutUserCommand.cs | 11 + .../SignOutUser/SignOutUserCommandHandler.cs | 68 +++++ .../Commands/SsoLogin/SsoLoginCommand.cs | 10 + .../SsoLogin/SsoLoginCommandHandler.cs | 115 ++++++++ .../GetSingleUserQueryHandler.cs | 124 +++++++++ .../GetUserSelectListQueryHandler.cs | 48 ++++ .../Users/Queries/GetUsers/GetUsersQuery.cs | 5 + .../Queries/GetUsers/GetUsersQueryHandler.cs | 49 ++++ .../Queries/GetUsers/GetUsersResponse.cs | 46 ++++ .../PermissionAgg/Entities/Permission.cs | 21 ++ .../DependencyInjection.cs | 16 +- .../Context/ProgramManagerDbContext.cs | 3 + .../Mappings/RefreshTokenMapping.cs | 50 ++++ .../Persistence/Mappings/RoleMapping.cs | 23 ++ .../Persistence/Mappings/UserMapping.cs | 34 +++ .../Repositories/RoleRepository.cs | 24 ++ .../SalaryPaymentSettingRepository.cs | 58 ++-- .../UserRefreshTokenRepository.cs | 20 ++ .../Repositories/UserRepository.cs | 87 ++++++ Query.Bootstrapper/QueryBootstrapper.cs | 1 + .../ProgramManager/AuthController.cs | 141 ++++++++++ .../ProgramManager/RoleController.cs | 46 ++++ .../ProgramManager/UserController.cs | 67 +++++ ServiceHost/Program.cs | 4 +- Shared.Contracts/Account/AccountBasicDto.cs | 14 - .../Account/IAccountQueryService.cs | 25 -- Shared.Contracts/Shared.Contracts.csproj | 10 - 50 files changed, 1622 insertions(+), 520 deletions(-) delete mode 100644 AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs delete mode 100644 Shared.Contracts/Account/AccountBasicDto.cs delete mode 100644 Shared.Contracts/Account/IAccountQueryService.cs delete mode 100644 Shared.Contracts/Shared.Contracts.csproj diff --git a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj index 57db0cd1..b73ec3c5 100644 --- a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj +++ b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj @@ -14,7 +14,6 @@ - diff --git a/AccountManagement.Configuration/AccountManagementBootstrapper.cs b/AccountManagement.Configuration/AccountManagementBootstrapper.cs index f51b7baa..132bf2d6 100644 --- a/AccountManagement.Configuration/AccountManagementBootstrapper.cs +++ b/AccountManagement.Configuration/AccountManagementBootstrapper.cs @@ -32,11 +32,9 @@ using AccountManagement.Domain.TicketAccessAccountAgg; using AccountManagement.Domain.TicketAgg; using AccountMangement.Infrastructure.EFCore; using AccountMangement.Infrastructure.EFCore.Repository; -using AccountMangement.Infrastructure.EFCore.Services; using Company.Domain.WorkshopAccountAgg; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Shared.Contracts.Account; using TaskManager.Application; using TaskManager.Infrastructure.EFCore.Repository; @@ -48,7 +46,6 @@ namespace AccountManagement.Configuration { services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj index 997ca351..9d4d7e2c 100644 --- a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj +++ b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj @@ -16,10 +16,8 @@ - - diff --git a/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs b/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs deleted file mode 100644 index 83c4a350..00000000 --- a/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Shared.Contracts.Account; - -namespace AccountMangement.Infrastructure.EFCore.Services; - -public class AccountQueryService : IAccountQueryService -{ - private readonly AccountContext _accountContext; - - public AccountQueryService(AccountContext accountContext) - { - _accountContext = accountContext; - } - - public async Task GetAccountAsync(long accountId) - { - return await _accountContext.Accounts - .Where(x => x.id == accountId) - .Select(x => new AccountBasicDto - { - Id = x.id, - Username = x.Username, - Fullname = x.Fullname, - IsActive = x.IsActiveString == "true" - }) - .FirstOrDefaultAsync(); - } - - public async Task> GetProgramManagerAccountListAsync(List accountIds) - { - var ids = accountIds?.ToHashSet() ?? new HashSet(); - if (ids.Count == 0) - return []; - - return await _accountContext.Accounts - .Where(x => ids.Contains(x.id)) - .Select(x => new AccountBasicDto - { - Id = x.id, - Username = x.Username, - Fullname = x.Fullname, - IsActive = x.IsActiveString == "true" - }) - .ToListAsync(); - } -} diff --git a/DadmehrGostar.sln b/DadmehrGostar.sln index d4d76d3a..358d6d87 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -104,378 +104,128 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Infrastructure", "ProgramManager\src\Infrastructure\GozareshgirProgramManager.Infrastructure\GozareshgirProgramManager.Infrastructure.csproj", "{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared.Contracts", "Shared.Contracts\Shared.Contracts.csproj", "{37F4BC4C-B620-4EFA-B4A7-A9797289E901}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|x64.ActiveCfg = Debug|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|x64.Build.0 = Debug|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|x86.ActiveCfg = Debug|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Debug|x86.Build.0 = Debug|Any CPU {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|Any CPU.Build.0 = Release|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|x64.ActiveCfg = Release|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|x64.Build.0 = Release|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|x86.ActiveCfg = Release|Any CPU - {CB6E0A25-B826-4EB0-80CD-D926B1A3D5D5}.Release|x86.Build.0 = Release|Any CPU {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|x64.Build.0 = Debug|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Debug|x86.Build.0 = Debug|Any CPU {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|Any CPU.Build.0 = Release|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|x64.ActiveCfg = Release|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|x64.Build.0 = Release|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|x86.ActiveCfg = Release|Any CPU - {26316896-07EB-4D55-AA88-17A57EF615DD}.Release|x86.Build.0 = Release|Any CPU {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|Any CPU.Build.0 = Debug|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|x64.ActiveCfg = Debug|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|x64.Build.0 = Debug|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|x86.ActiveCfg = Debug|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Debug|x86.Build.0 = Debug|Any CPU {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|Any CPU.ActiveCfg = Release|Any CPU {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|Any CPU.Build.0 = Release|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|x64.ActiveCfg = Release|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|x64.Build.0 = Release|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|x86.ActiveCfg = Release|Any CPU - {618761ED-3835-4C52-A91F-2240FAE39A71}.Release|x86.Build.0 = Release|Any CPU {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|x64.ActiveCfg = Debug|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|x64.Build.0 = Debug|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|x86.ActiveCfg = Debug|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Debug|x86.Build.0 = Debug|Any CPU {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|Any CPU.ActiveCfg = Release|Any CPU {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|Any CPU.Build.0 = Release|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|x64.ActiveCfg = Release|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|x64.Build.0 = Release|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|x86.ActiveCfg = Release|Any CPU - {0AF931F3-B576-4B42-80EC-CD19BAD3F95F}.Release|x86.Build.0 = Release|Any CPU {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|x64.ActiveCfg = Debug|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|x64.Build.0 = Debug|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|x86.ActiveCfg = Debug|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Debug|x86.Build.0 = Debug|Any CPU {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|Any CPU.ActiveCfg = Release|Any CPU {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|Any CPU.Build.0 = Release|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|x64.ActiveCfg = Release|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|x64.Build.0 = Release|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|x86.ActiveCfg = Release|Any CPU - {0327F97A-D526-4BD7-92A3-E5B36BB30AC5}.Release|x86.Build.0 = Release|Any CPU {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|x64.ActiveCfg = Debug|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|x64.Build.0 = Debug|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Debug|x86.Build.0 = Debug|Any CPU {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|Any CPU.Build.0 = Release|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|x64.ActiveCfg = Release|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|x64.Build.0 = Release|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|x86.ActiveCfg = Release|Any CPU - {AB39F1D0-7164-489F-9524-67AEC1DF78B4}.Release|x86.Build.0 = Release|Any CPU {35B6B963-974A-4414-8609-B0668181FA64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {35B6B963-974A-4414-8609-B0668181FA64}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Debug|x64.ActiveCfg = Debug|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Debug|x64.Build.0 = Debug|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Debug|x86.ActiveCfg = Debug|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Debug|x86.Build.0 = Debug|Any CPU {35B6B963-974A-4414-8609-B0668181FA64}.Release|Any CPU.ActiveCfg = Release|Any CPU {35B6B963-974A-4414-8609-B0668181FA64}.Release|Any CPU.Build.0 = Release|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Release|x64.ActiveCfg = Release|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Release|x64.Build.0 = Release|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Release|x86.ActiveCfg = Release|Any CPU - {35B6B963-974A-4414-8609-B0668181FA64}.Release|x86.Build.0 = Release|Any CPU {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|x64.ActiveCfg = Debug|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|x64.Build.0 = Debug|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|x86.ActiveCfg = Debug|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Debug|x86.Build.0 = Debug|Any CPU {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|Any CPU.ActiveCfg = Release|Any CPU {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|Any CPU.Build.0 = Release|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|x64.ActiveCfg = Release|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|x64.Build.0 = Release|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|x86.ActiveCfg = Release|Any CPU - {68D25B12-9F11-454B-BD3A-C96EBBC888F8}.Release|x86.Build.0 = Release|Any CPU {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|x64.ActiveCfg = Debug|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|x64.Build.0 = Debug|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|x86.ActiveCfg = Debug|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Debug|x86.Build.0 = Debug|Any CPU {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|Any CPU.ActiveCfg = Release|Any CPU {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|Any CPU.Build.0 = Release|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|x64.ActiveCfg = Release|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|x64.Build.0 = Release|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|x86.ActiveCfg = Release|Any CPU - {C2EBA38E-5C71-4457-BA80-283FB6A848AC}.Release|x86.Build.0 = Release|Any CPU {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|x64.ActiveCfg = Debug|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|x64.Build.0 = Debug|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|x86.ActiveCfg = Debug|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Debug|x86.Build.0 = Debug|Any CPU {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|Any CPU.Build.0 = Release|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|x64.ActiveCfg = Release|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|x64.Build.0 = Release|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|x86.ActiveCfg = Release|Any CPU - {E2251AF9-237D-4F63-A3D4-6B9C270D0ED8}.Release|x86.Build.0 = Release|Any CPU {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|x64.ActiveCfg = Debug|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|x64.Build.0 = Debug|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|x86.ActiveCfg = Debug|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Debug|x86.Build.0 = Debug|Any CPU {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|Any CPU.Build.0 = Release|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|x64.ActiveCfg = Release|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|x64.Build.0 = Release|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|x86.ActiveCfg = Release|Any CPU - {1D38F80F-8400-43C2-88B3-D2A369AAF1F0}.Release|x86.Build.0 = Release|Any CPU {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|x64.ActiveCfg = Debug|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|x64.Build.0 = Debug|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|x86.ActiveCfg = Debug|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Debug|x86.Build.0 = Debug|Any CPU {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|Any CPU.ActiveCfg = Release|Any CPU {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|Any CPU.Build.0 = Release|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|x64.ActiveCfg = Release|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|x64.Build.0 = Release|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|x86.ActiveCfg = Release|Any CPU - {55799DFE-885F-4B35-AFEE-0D0CE24E6ED9}.Release|x86.Build.0 = Release|Any CPU {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|x64.ActiveCfg = Debug|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|x64.Build.0 = Debug|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|x86.ActiveCfg = Debug|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Debug|x86.Build.0 = Debug|Any CPU {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|Any CPU.ActiveCfg = Release|Any CPU {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|Any CPU.Build.0 = Release|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|x64.ActiveCfg = Release|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|x64.Build.0 = Release|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|x86.ActiveCfg = Release|Any CPU - {F138CA45-A2CA-4C77-B8AA-5AC6B4ECB834}.Release|x86.Build.0 = Release|Any CPU {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|x64.ActiveCfg = Debug|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|x64.Build.0 = Debug|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|x86.ActiveCfg = Debug|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Debug|x86.Build.0 = Debug|Any CPU {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|Any CPU.Build.0 = Release|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|x64.ActiveCfg = Release|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|x64.Build.0 = Release|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|x86.ActiveCfg = Release|Any CPU - {5EE2EC2E-E1B5-457C-9A1F-642D2BDB4AE7}.Release|x86.Build.0 = Release|Any CPU {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|x64.ActiveCfg = Debug|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|x64.Build.0 = Debug|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|x86.ActiveCfg = Debug|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Debug|x86.Build.0 = Debug|Any CPU {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|Any CPU.ActiveCfg = Release|Any CPU {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|Any CPU.Build.0 = Release|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|x64.ActiveCfg = Release|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|x64.Build.0 = Release|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|x86.ActiveCfg = Release|Any CPU - {BA69B1F4-2D53-4FAC-A658-FD59EB552269}.Release|x86.Build.0 = Release|Any CPU {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|x64.ActiveCfg = Debug|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|x64.Build.0 = Debug|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|x86.ActiveCfg = Debug|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Debug|x86.Build.0 = Debug|Any CPU {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|Any CPU.ActiveCfg = Release|Any CPU {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|Any CPU.Build.0 = Release|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|x64.ActiveCfg = Release|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|x64.Build.0 = Release|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|x86.ActiveCfg = Release|Any CPU - {BA6933AF-C104-4271-ADEA-999E1BFC5A6C}.Release|x86.Build.0 = Release|Any CPU {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|x64.ActiveCfg = Debug|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|x64.Build.0 = Debug|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|x86.ActiveCfg = Debug|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Debug|x86.Build.0 = Debug|Any CPU {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|Any CPU.Build.0 = Release|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|x64.ActiveCfg = Release|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|x64.Build.0 = Release|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|x86.ActiveCfg = Release|Any CPU - {AFE354B3-CCDF-4810-9FFF-6F10B49757B8}.Release|x86.Build.0 = Release|Any CPU {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|x64.ActiveCfg = Debug|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|x64.Build.0 = Debug|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|x86.ActiveCfg = Debug|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Debug|x86.Build.0 = Debug|Any CPU {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|Any CPU.ActiveCfg = Release|Any CPU {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|Any CPU.Build.0 = Release|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|x64.ActiveCfg = Release|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|x64.Build.0 = Release|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|x86.ActiveCfg = Release|Any CPU - {9643E1D4-A2FE-4CA1-A303-1A499CDB6D87}.Release|x86.Build.0 = Release|Any CPU {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|x64.ActiveCfg = Debug|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|x64.Build.0 = Debug|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|x86.ActiveCfg = Debug|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Debug|x86.Build.0 = Debug|Any CPU {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|Any CPU.ActiveCfg = Release|Any CPU {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|Any CPU.Build.0 = Release|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|x64.ActiveCfg = Release|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|x64.Build.0 = Release|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|x86.ActiveCfg = Release|Any CPU - {3CDCCA2F-79F1-43FD-B9C4-211279624148}.Release|x86.Build.0 = Release|Any CPU {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|x64.ActiveCfg = Debug|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|x64.Build.0 = Debug|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|x86.ActiveCfg = Debug|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Debug|x86.Build.0 = Debug|Any CPU {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|Any CPU.ActiveCfg = Release|Any CPU {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|Any CPU.Build.0 = Release|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|x64.ActiveCfg = Release|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|x64.Build.0 = Release|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|x86.ActiveCfg = Release|Any CPU - {0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551}.Release|x86.Build.0 = Release|Any CPU {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|x64.ActiveCfg = Debug|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|x64.Build.0 = Debug|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|x86.ActiveCfg = Debug|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Debug|x86.Build.0 = Debug|Any CPU {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|Any CPU.Build.0 = Release|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|x64.ActiveCfg = Release|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|x64.Build.0 = Release|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|x86.ActiveCfg = Release|Any CPU - {339E05B6-E99F-4403-AFDF-CD0540E96C8D}.Release|x86.Build.0 = Release|Any CPU {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|x64.ActiveCfg = Debug|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|x64.Build.0 = Debug|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|x86.ActiveCfg = Debug|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|x86.Build.0 = Debug|Any CPU {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|Any CPU.ActiveCfg = Release|Any CPU {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|Any CPU.Build.0 = Release|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|x64.ActiveCfg = Release|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|x64.Build.0 = Release|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|x86.ActiveCfg = Release|Any CPU - {02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|x86.Build.0 = Release|Any CPU {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|x64.ActiveCfg = Debug|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|x64.Build.0 = Debug|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|x86.ActiveCfg = Debug|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|x86.Build.0 = Debug|Any CPU {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|Any CPU.ActiveCfg = Release|Any CPU {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|Any CPU.Build.0 = Release|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|x64.ActiveCfg = Release|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|x64.Build.0 = Release|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|x86.ActiveCfg = Release|Any CPU - {BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|x86.Build.0 = Release|Any CPU {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|x64.ActiveCfg = Debug|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|x64.Build.0 = Debug|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|x86.ActiveCfg = Debug|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Debug|x86.Build.0 = Debug|Any CPU {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|Any CPU.ActiveCfg = Release|Any CPU {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|Any CPU.Build.0 = Release|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|x64.ActiveCfg = Release|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|x64.Build.0 = Release|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|x86.ActiveCfg = Release|Any CPU - {97E148FA-3C36-40DD-B121-D90C1C0F3B47}.Release|x86.Build.0 = Release|Any CPU {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|x64.ActiveCfg = Debug|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|x64.Build.0 = Debug|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|x86.ActiveCfg = Debug|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Debug|x86.Build.0 = Debug|Any CPU {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|Any CPU.Build.0 = Release|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|x64.ActiveCfg = Release|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|x64.Build.0 = Release|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|x86.ActiveCfg = Release|Any CPU - {4CDAA60E-C7DD-4883-85CC-E7E26CCC6ED3}.Release|x86.Build.0 = Release|Any CPU {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|x64.ActiveCfg = Debug|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|x64.Build.0 = Debug|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|x86.ActiveCfg = Debug|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|x86.Build.0 = Debug|Any CPU {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|Any CPU.ActiveCfg = Release|Any CPU {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|Any CPU.Build.0 = Release|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|x64.ActiveCfg = Release|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|x64.Build.0 = Release|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|x86.ActiveCfg = Release|Any CPU - {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|x86.Build.0 = Release|Any CPU {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|x64.ActiveCfg = Debug|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|x64.Build.0 = Debug|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|x86.ActiveCfg = Debug|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|x86.Build.0 = Debug|Any CPU {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|Any CPU.ActiveCfg = Release|Any CPU {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|Any CPU.Build.0 = Release|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|x64.ActiveCfg = Release|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|x64.Build.0 = Release|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|x86.ActiveCfg = Release|Any CPU - {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|x86.Build.0 = Release|Any CPU {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|x64.ActiveCfg = Debug|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|x64.Build.0 = Debug|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|x86.ActiveCfg = Debug|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|x86.Build.0 = Debug|Any CPU {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|Any CPU.Build.0 = Release|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|x64.ActiveCfg = Release|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|x64.Build.0 = Release|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|x86.ActiveCfg = Release|Any CPU - {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|x86.Build.0 = Release|Any CPU {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|x64.ActiveCfg = Debug|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|x64.Build.0 = Debug|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|x86.ActiveCfg = Debug|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|x86.Build.0 = Debug|Any CPU {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|Any CPU.Build.0 = Release|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|x64.ActiveCfg = Release|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|x64.Build.0 = Release|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|x86.ActiveCfg = Release|Any CPU - {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|x86.Build.0 = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|Any CPU.Build.0 = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|x64.ActiveCfg = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|x64.Build.0 = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|x86.ActiveCfg = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Debug|x86.Build.0 = Debug|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|Any CPU.ActiveCfg = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|Any CPU.Build.0 = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|x64.ActiveCfg = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|x64.Build.0 = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|x86.ActiveCfg = Release|Any CPU - {37F4BC4C-B620-4EFA-B4A7-A9797289E901}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj index 41ec592d..e20615bf 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj @@ -14,7 +14,6 @@ - diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs index f7b3d82d..c98b88e9 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs @@ -5,7 +5,6 @@ using GozareshgirProgramManager.Domain._Common; using GozareshgirProgramManager.Domain.CheckoutAgg.Enums; using Microsoft.EntityFrameworkCore; using PersianTools.Core; -using Shared.Contracts.Account; namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate; @@ -15,14 +14,12 @@ namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUse public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IAccountQueryService _accountQueryService; + private readonly IGozareshgirDbContext _gozareshgirDbContext; - public GetUserToGroupCreatingQueryHandler( - IProgramManagerDbContext context, - IAccountQueryService accountQueryService) + public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context, IGozareshgirDbContext gozareshgirDbContext) { _context = context; - _accountQueryService = accountQueryService; + _gozareshgirDbContext = gozareshgirDbContext; } public async Task> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken) @@ -53,46 +50,35 @@ public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler x.CheckoutStartDate < lastMonthStart - && x.CheckoutEndDate >= lastMonthStart) - on s.AccountId equals ch.UserId into chJoin - from ch in chJoin.DefaultIfEmpty() + + var query = + await (from u in _context.Users - select new - { - AccountId = s.AccountId, - HasCheckout = ch != null - }) - .GroupBy(x => x.AccountId) - .Select(g => new - { - AccountId = g.Key, - HasCheckout = g.Any(x => x.HasCheckout) - }) - .ToListAsync(cancellationToken); + // LEFT JOIN + // تنظیمات حقوق + join s in _context.SalaryPaymentSettings + on u.Id equals s.AccountId into sJoin + from s in sJoin.DefaultIfEmpty() - // دریافت اطلاعات Account ها از AccountManagement - var accountIds = settingsAndCheckouts.Select(x => x.AccountId).Distinct().ToList(); - var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(accountIds); - var accountsDict = accounts.ToDictionary(a => a.Id); + // LEFT JOIN + //فیش + join ch in _context.Checkouts + .Where(x => x.CheckoutStartDate < lastMonthStart + && x.CheckoutEndDate >= lastMonthStart) + on u.Id equals ch.UserId into chJoin + from ch in chJoin.DefaultIfEmpty() - // ترکیب داده‌ها - var query = settingsAndCheckouts - .Where(x => accountsDict.ContainsKey(x.AccountId)) - .Select(x => new GetUserWhoHaveSettingsAndCheckoutDto - { - UserId = x.AccountId, - FullName = accountsDict[x.AccountId].Fullname, - HasSalarySettings = true, // چون از SalaryPaymentSettings اومده پس حتماً تنظیمات داره - HasCheckout = x.HasCheckout - }) - .ToList(); + group new { s, ch } by new { u.Id, u.FullName } into g + + select new GetUserWhoHaveSettingsAndCheckoutDto + { + UserId = g.Key.Id, + FullName = g.Key.FullName, + + HasSalarySettings = g.Any(x => x.s != null), + HasCheckout = g.Any(x => x.ch != null) + }) + .ToListAsync(cancellationToken); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs index 91bdbc8a..4f27773a 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs @@ -2,7 +2,7 @@ using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Domain._Common; using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; -using Shared.Contracts.Account; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; @@ -10,15 +10,15 @@ public class TransferSectionCommandHandler : IBaseCommandHandler>> Handle(ProjectBoardListQuery request, @@ -33,9 +30,10 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.Activities).Select(a => a.UserId).Distinct().ToList(); - // Fetch account basics in batch and map to FullName - var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(activityUserIds); - var users = accounts.ToDictionary(a => a.Id, a => a.Fullname); + var users = await _programManagerDbContext.Users.AsNoTracking() + .Where(x => activityUserIds.Contains(x.Id)) + .Select(x => new { x.Id, x.FullName }) + .ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken); var result = data.Select(x => { diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs index e2084f20..f99f3370 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs @@ -1,9 +1,11 @@ -using GozareshgirProgramManager.Application._Common.Interfaces; +using DNTPersianUtils.Core; +using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; using GozareshgirProgramManager.Domain._Common; using GozareshgirProgramManager.Domain.ProjectAgg.Enums; using Microsoft.EntityFrameworkCore; -using Shared.Contracts.Account; namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; @@ -12,12 +14,10 @@ public class ProjectSetTimeDetailsQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IAccountQueryService _accountQueryService; - public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) + public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context) { _context = context; - _accountQueryService = accountQueryService; } public async Task> Handle(ProjectSetTimeDetailsQuery request, @@ -36,10 +36,10 @@ public class ProjectSetTimeDetailsQueryHandler var userIds = task.Sections.Select(x => x.OriginalAssignedUserId) .Distinct().ToList(); - // Fetch account basics in batch (instead of _context.Users) - var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(userIds); - var accountDict = accounts.ToDictionary(a => a.Id); - + var users = await _context.Users + .Where(x => userIds.Contains(x.Id)) + .AsNoTracking() + .ToListAsync(cancellationToken); var skillIds = task.Sections.Select(x => x.SkillId) .Distinct().ToList(); @@ -51,8 +51,8 @@ public class ProjectSetTimeDetailsQueryHandler var res = new ProjectSetTimeResponse( task.Sections.Select(ts => { + var user = users.FirstOrDefault(x => x.Id == ts.OriginalAssignedUserId); var skill = skills.FirstOrDefault(x => x.Id == ts.SkillId); - var account = accountDict.GetValueOrDefault(ts.OriginalAssignedUserId); return new ProjectSetTimeResponseSections { AdditionalTimes = ts.AdditionalTimes @@ -65,7 +65,7 @@ public class ProjectSetTimeDetailsQueryHandler SkillName = skill?.Name ?? "", TotalAdditionalTime = (int)ts.GetTotalAdditionalTime().TotalHours, TotalEstimateTime = (int)ts.FinalEstimatedHours.TotalHours, - UserName = account?.Username ?? "", + UserName = user?.UserName ?? "", SectionId = ts.Id, InitialDescription = ts.InitialDescription ?? "", InitialTime = (int)ts.InitialEstimatedHours.TotalHours diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs new file mode 100644 index 00000000..c5ef5b2c --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs @@ -0,0 +1,44 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Roles.Commands.CreateRole; + +public class CreateRoleCommandHandler : IBaseCommandHandler +{ + private readonly IRoleRepository _roleRepository; + private readonly IUnitOfWork _unitOfWork; + + public CreateRoleCommandHandler(IRoleRepository roleRepository, IUnitOfWork unitOfWork) + { + _roleRepository = roleRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(CreateRoleCommand request, CancellationToken cancellationToken) + { + + if(string.IsNullOrWhiteSpace(request.RoleName)) + return OperationResult.Failure("نام نقش خالی است"); + if(!request.Permissions.Any()) + return OperationResult.Failure("هیچ دسترسی داده نشده است"); + var permissions = request.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList(); + + var role = new Role(request.RoleName, request.GozareshgirRoleId, permissions); + await _roleRepository.CreateAsync(role); + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + } +} + + +public record CreateRoleCommand : IBaseCommand +{ + public string RoleName { get; set; } + public List Permissions { get; set; } + + public long? GozareshgirRoleId { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs new file mode 100644 index 00000000..36e50fbb --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs @@ -0,0 +1,54 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Roles.Commands.EditRole; + +public class EditRoleCommandHandler : IBaseCommandHandler +{ + private readonly IRoleRepository _roleRepository; + private readonly IUnitOfWork _unitOfWork; + + public EditRoleCommandHandler(IRoleRepository roleRepository, IUnitOfWork unitOfWork) + { + _roleRepository = roleRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(EditRoleCommand request, CancellationToken cancellationToken) + { + if (_roleRepository.Exists(x => x.RoleName == request.RoleName && x.GozareshgirRoleId != request.GozareshgirRoleId)) + return OperationResult.Failure("نام نقش تکراری است"); + + if (string.IsNullOrWhiteSpace(request.RoleName)) + return OperationResult.Failure("نام نقش خالی است"); + + if(request.GozareshgirRoleId == null || request.GozareshgirRoleId == 0) + return OperationResult.Failure("آی دی نقش از سمت گزارشگیر خالی است"); + + var permissions = request.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList(); + + + var role =await _roleRepository.GetByGozareshgirRoleIdAsync(request.GozareshgirRoleId); + + if (role != null) + { + role?.Edit(request.RoleName, permissions); + + await _unitOfWork.SaveChangesAsync(); + } + + return OperationResult.Success(); + + } +} + +public record EditRoleCommand : IBaseCommand +{ + public string RoleName { get; set; } + public List Permissions { get; set; } + + public long? GozareshgirRoleId { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs new file mode 100644 index 00000000..bcdb5fe1 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs @@ -0,0 +1,76 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Roles.Queries.GetRoles; + +public class GetRolesQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetRolesQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetRolesQuery request, CancellationToken cancellationToken) + { + var query = _context.Roles.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(request.RoleName)) + query = query.Where(x => x.RoleName.Contains(request.RoleName)); + if (request.GozareshgirRoleId > 0) + query = query.Where(x => x.GozareshgirRoleId == request.GozareshgirRoleId); + + var roles = await query + .Select(p => new GetRolesDto() + { + Id = p.Id, + RoleName = p.RoleName, + GozareshgirRoleId = p.GozareshgirRoleId, + Permissions = p.Permissions.Select(x=>x.Code).ToList() + + }) + .ToListAsync(cancellationToken); + if(!roles.Any()) + return OperationResult.NotFound("یافت نشد"); + + var response = new GetRolesResponse( + roles + ); + + return OperationResult.Success(response); + + } +} + + +public record GetRolesQuery(string? RoleName, long? GozareshgirRoleId) : IBaseQuery; + +public record GetRolesResponse(List Role); + +public record GetRolesDto +{ + /// + /// آی دی نقش + /// + public long Id { get; set; } + + /// + /// نام نقش + /// + public string RoleName { get; set; } + + /// + /// آی دی نقش در گزارشگیر + /// + public long? GozareshgirRoleId { get; set; } + + /// + /// لیست کدهای دسترسی + /// + public List Permissions { get; set; } + + +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs index 080fcef6..1fe869c7 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs @@ -3,66 +3,60 @@ using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; using GozareshgirProgramManager.Domain._Common; using Microsoft.EntityFrameworkCore; -using Shared.Contracts.Account; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IAccountQueryService _accountQueryService; - public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) + public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context) { _context = context; - _accountQueryService = accountQueryService; } public async Task> Handle(GetSalarySettingToEditQuery request, CancellationToken cancellationToken) { - // دریافت اطلاعات حساب از AccountManagement - var account = await _accountQueryService.GetAccountAsync(request.UserId); - if (account == null) + var user =await _context.Users.FirstOrDefaultAsync(x => x.Id == request.UserId); + if(user == null) return OperationResult.NotFound("کاربر یافت نشد"); var editSalarySettingsList = await _context.SalaryPaymentSettings - .Where(x => x.AccountId == request.UserId) .Select(x => new GetSalarySettingToEdit() { Id = x.Id, HolidayWorking = x.HolidayWorking, UserId = x.AccountId, MonthlySalary = x.MonthlySalary.ToMoney(), + WorkingHoursList = x.WorkingHoursList.Select(wh => new WorkingHoursListDto { - StartShiftOne = wh.HasShiftOne ? wh.StartShiftOne.ToString(@"hh\:mm") : null, + StartShiftOne =wh.HasShiftOne ? wh.StartShiftOne.ToString(@"hh\:mm") : null, EndShiftOne = wh.HasShiftOne ? wh.EndShiftOne.ToString(@"hh\:mm") : null, StartShiftTwo = wh.HasShiftTow ? wh.StartShiftTwo.ToString(@"hh\:mm") : null, - EndShiftTwo = wh.HasShiftTow ? wh.EndShiftTwo.ToString(@"hh\:mm") : null, + EndShiftTwo = wh.HasShiftTow ? wh.EndShiftTwo.ToString(@"hh\:mm") :null, RestTime = wh.HasRestTime ? wh.RestTime.ToString(@"hh\:mm") : null, HasRestTime = wh.HasRestTime, HasShiftOne = wh.HasShiftOne, HasShiftTow = wh.HasShiftTow, PersianDayOfWeek = wh.PersianDayOfWeek, IsActiveDay = wh.IsActiveDay - }).OrderBy(wh => wh.PersianDayOfWeek).ToList(), + }).OrderBy(wh=>wh.PersianDayOfWeek).ToList(), - }).FirstOrDefaultAsync(cancellationToken); + }).FirstOrDefaultAsync(x => x.UserId == request.UserId); - if (editSalarySettingsList == null) - { - return OperationResult.NotFound("تنظیمات مورد نظر یافت نشد"); - } - - var response = new GetSalarySettingToEditResponse(request.UserId, account.Fullname, editSalarySettingsList); + var response = new GetSalarySettingToEditResponse(request.UserId,user.FullName,editSalarySettingsList); return OperationResult.Success(response); + } } public record GetSalarySettingToEditResponse(long UserId, string FullName, GetSalarySettingToEdit EditSalarySettingsList); -public record GetSalarySettingToEditQuery(long UserId) : IBaseQuery; +public record GetSalarySettingToEditQuery(long UserId) :IBaseQuery; + public record GetSalarySettingToEdit { @@ -83,10 +77,12 @@ public record GetSalarySettingToEdit /// /// حقوق ماهانه /// - public string MonthlySalary { get; set; } = string.Empty; + public string MonthlySalary { get; set; } /// /// لیست روزهای هفته و ساعات کاری /// - public List WorkingHoursList { get; set; } = new(); + public List WorkingHoursList { get; set; } } + + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs index ea2192df..05fd3674 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs @@ -4,71 +4,62 @@ using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Domain._Common; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; using Microsoft.EntityFrameworkCore; -using Shared.Contracts.Account; namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings; public class GetUserListWhoHaveSettingsQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IAccountQueryService _accountQueryService; - public GetUserListWhoHaveSettingsQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) + public GetUserListWhoHaveSettingsQueryHandler(IProgramManagerDbContext context) { _context = context; - _accountQueryService = accountQueryService; } public async Task> Handle(GetUserListWhoHaveSettingsQuery request, CancellationToken cancellationToken) { - // Get all salary settings - var allSettings = await _context.SalaryPaymentSettings.ToListAsync(cancellationToken); - - // Get all unique account IDs - var accountIds = allSettings.Select(s => s.AccountId).Distinct().ToList(); - - // Get all user data in one batch through AccountQueryService - var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(accountIds); - var accountDictionary = accounts.ToDictionary(a => a.Id, a => a); - - // Map settings to DTOs - var userSettingsQuery = allSettings - .Where(setting => accountDictionary.ContainsKey(setting.AccountId)) - .Select(setting => + var query = await ( + from u in _context.Users + join s in _context.SalaryPaymentSettings + on u.Id equals s.AccountId into settingsGroup + select new GetUserWhoHaveSettingsDto { - var userBasic = accountDictionary[setting.AccountId]; - return new GetUserWhoHaveSettingsDto - { - UserId = userBasic.Id, - FullName = userBasic.Fullname, - HasSalarySettings = true, - MontlySalary = setting.MonthlySalary.ToMoney(), - WeeklyWorkingTimeAvrageInt = setting.WorkingHoursList?.Sum(w => (int?)w.ShiftDurationInMinutes) ?? 0 - }; - }) - .ToList(); - - var list = userSettingsQuery; + UserId = u.Id, + FullName = u.FullName, + HasSalarySettings = settingsGroup.Any(), + MontlySalary = settingsGroup.Any() ? settingsGroup.FirstOrDefault().MonthlySalary.ToMoney() : "", + WeeklyWorkingTimeAvrageInt = settingsGroup + .SelectMany(x => x.WorkingHoursList) + .Sum(w => (int?)w.ShiftDurationInMinutes) ?? 0 + } + ).ToListAsync(cancellationToken); if (!string.IsNullOrWhiteSpace(request.FullName)) - list = list.Where(x => x.FullName.Contains(request.FullName)).ToList(); + query = query.Where(x => x.FullName.Contains(request.FullName)).ToList(); if (request.HasSalarySettings != HasSalarySettings.Default) { bool hasSettings = request.HasSalarySettings == HasSalarySettings.HasSettings; - list = list.Where(x => x.HasSalarySettings == hasSettings).ToList(); + query = query.Where(x => x.HasSalarySettings == hasSettings).ToList(); } - - var operationQuery = list.Select(user => + + var operationQuery = query.Select(user => { var weeklyWorkingTimeAvrage = user.WeeklyWorkingTimeAvrageInt.ConvertIntDurationToHoursAndMinutes(); - return user with { WeeklyWorkingTimeAvrage = weeklyWorkingTimeAvrage }; + return new GetUserWhoHaveSettingsDto + { + UserId = user.UserId, + FullName = user.FullName, + HasSalarySettings = user.HasSalarySettings, + MontlySalary = user.MontlySalary, + WeeklyWorkingTimeAvrageInt = user.WeeklyWorkingTimeAvrageInt, + WeeklyWorkingTimeAvrage = weeklyWorkingTimeAvrage + }; }).ToList(); - var response = new GetUserListWhoHaveSettingsResponse(operationQuery); return OperationResult.Success(response); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs new file mode 100644 index 00000000..4eba06a0 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs @@ -0,0 +1,5 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; + +public record CreateUserCommand(string FullName, string UserName, string Password, string Mobile, string? Email, long? AccountId, List Roles) : IBaseCommand; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs new file mode 100644 index 00000000..535697b3 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs @@ -0,0 +1,43 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.RoleUserAgg; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; + +public class CreateUserCommandHandler : IBaseCommandHandler +{ + private readonly IUserRepository _userRepository; + private readonly IUnitOfWork _unitOfWork; + + public CreateUserCommandHandler(IUnitOfWork unitOfWork, IUserRepository userRepository) + { + _unitOfWork = unitOfWork; + _userRepository = userRepository; + } + + public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) + { + + #region CustomValidation + if (_userRepository.Exists(x => x.FullName == request.FullName)) + return OperationResult.Failure("نام و خانوادگی تکراری است"); + if (_userRepository.Exists(x => x.UserName == request.UserName)) + return OperationResult.Failure("نام کاربری تکراری است"); + if (_userRepository.Exists(x=> !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == request.Mobile)) + return OperationResult.ValidationError("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); + if(request.AccountId == 0) + return OperationResult.Failure("آی دی اکانت، از سمت گزارشگیر صفر است"); + #endregion + + var userRoles = request.Roles.Where(x => x > 0).Select(x => new RoleUser(x)).ToList() ; + var create = new User(request.FullName, request.UserName, request.Password, request.Mobile, + request.Email, request?.AccountId, userRoles); + + await _userRepository.CreateAsync(create); + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs new file mode 100644 index 00000000..68f9f1a7 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs @@ -0,0 +1,24 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; + +public class CreateUserCommandValidators : AbstractValidator +{ + public CreateUserCommandValidators() + { + RuleFor(x => x.FullName) + .NotEmpty() + .NotNull() + .WithMessage("نام و نام خانوادگی نمی تواند خالی باشد"); + + RuleFor(x => x.Mobile) + .NotNull().NotEmpty().WithMessage("شماره همراه نمی تواند خالی باشد"); + RuleFor(x=>x.Mobile) + .Length(11).WithMessage("طول شماره همراه می بایست 11 رقم باشد"); + RuleFor(x => x.UserName) + .NotEmpty().NotNull().WithMessage("نام کاربری نمیتوان خالی باشد"); + + + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs new file mode 100644 index 00000000..1920f1fb --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs @@ -0,0 +1,34 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.RoleUserAgg; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.EditUser; + +public class EditUserCommandHandler :IBaseCommandHandler +{ + private readonly IUserRepository _userRepository; + private readonly IUnitOfWork _unitOfWork; + + public EditUserCommandHandler(IUserRepository userRepository, IUnitOfWork unitOfWork) + { + _userRepository = userRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(EditUserCommand request, CancellationToken cancellationToken) + { + var user = await _userRepository.GetByGozareshgirAccountId(request.AccountId); + if (user != null) + { + var userRoles = request.Roles.Where(x => x > 0).Select(x => new RoleUser(x)).ToList(); + user.Edit(request.FullName, request.UserName, request.Mobile, userRoles, request.IsActive); + await _unitOfWork.SaveChangesAsync(); + } + + return OperationResult.Success(); + } +} + +public record EditUserCommand(string FullName, string UserName, string Mobile,long AccountId, List Roles, bool IsActive) : IBaseCommand; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs new file mode 100644 index 00000000..80d51cb2 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs @@ -0,0 +1,11 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.LoginUser; + +/// +/// دستور ورود کاربر به سیستم +/// +public record LoginUserCommand(long UserId) : IBaseCommand; + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs new file mode 100644 index 00000000..cb284fd0 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs @@ -0,0 +1,98 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.LoginUser; + +/// +/// Handler برای ورود کاربر به سیستم +/// +public class LoginUserCommandHandler : IRequestHandler> +{ + private readonly IUserRepository _userRepository; + private readonly IUserRefreshTokenRepository _refreshTokenRepository; + private readonly IAuthHelper _authHelper; + private readonly IUnitOfWork _unitOfWork; + + public LoginUserCommandHandler( + IUserRepository userRepository, + IAuthHelper authHelper, + IUnitOfWork unitOfWork, IUserRefreshTokenRepository refreshTokenRepository) + { + _userRepository = userRepository; + _authHelper = authHelper; + _unitOfWork = unitOfWork; + _refreshTokenRepository = refreshTokenRepository; + } + + public async Task> Handle(LoginUserCommand request, CancellationToken cancellationToken) + { + // اعتبارسنجی + if (request.UserId <= 0) + { + return OperationResult.Failure("شناسه کاربری معتبر نیست", ErrorType.BadRequest); + } + + // یافتن کاربر + var user = await _userRepository.GetUserWithRolesByIdAsync(request.UserId, cancellationToken); + + if (user == null) + { + return OperationResult.Failure("کاربر یافت نشد", ErrorType.NotFound); + } + + // بررسی فعال بودن کاربر + if (!user.IsActive) + { + return OperationResult.Failure("حساب کاربری غیرفعال است", ErrorType.Unauthorized); + } + + // تولید توکن‌ها با استفاده از AuthHelper + var roles = user.RoleUser + .Select(r => r.RoleId.ToString()).ToList(); + + var session = _authHelper.SignIn( + user.Id, + user.UserName, + user.FullName, + user.AccountId??0, + roles); + // دریافت اطلاعات درخواست با استفاده از AuthHelper + var ipAddress = _authHelper.GetClientIpAddress(); + var userAgent = _authHelper.GetUserAgent(); + + // ذخیره Refresh Token در دیتابیس + //user.AddRefreshToken(refreshToken, refreshTokenExpiration, ipAddress, userAgent); + + var refreshTokenEntity = new UserRefreshToken( + user.Id, + session.RefreshToken, + session.RefreshTokenExpiration, + ipAddress, + userAgent); + + await _refreshTokenRepository.CreateAsync(refreshTokenEntity); + + + await _unitOfWork.SaveChangesAsync(cancellationToken); + + + // ساخت پاسخ (RefreshToken به فرانت داده نمی‌شود) + var response = new LoginResponse + { + AccessToken = session.AccessToken, + ExpiresAt = session.AccessTokenExpiration, + UserId = user.Id, + FullName = user.FullName, + UserName = user.UserName, + Roles = user.RoleUser.Select(r => r.RoleId).ToList() + }; + + return OperationResult.Success(response); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs new file mode 100644 index 00000000..31cf5838 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs @@ -0,0 +1,11 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.RefreshUserToken; + +/// +/// دستور تازه‌سازی توکن دسترسی کاربر +/// +public record RefreshUserTokenCommand() : IBaseCommand; + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs new file mode 100644 index 00000000..12bfb62b --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs @@ -0,0 +1,86 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using Microsoft.EntityFrameworkCore; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.RefreshUserToken; + +/// +/// Handler برای تازه‌سازی توکن دسترسی +/// +public class RefreshUserTokenCommandHandler : IBaseCommandHandler +{ + private readonly IAuthHelper _authHelper; + private readonly IProgramManagerDbContext _context; + + public RefreshUserTokenCommandHandler( + IAuthHelper authHelper, + IProgramManagerDbContext context) + { + _authHelper = authHelper; + _context = context; + } + + public async Task Handle(RefreshUserTokenCommand request, CancellationToken cancellationToken) + { + + var refreshToken = _authHelper.GetRefreshTokenFromCookie(); + + // یافتن کاربر و Refresh Token فعال از دیتابیس + var user = await _context.Users + .Include(u => u.RefreshTokens) + .Include(u => u.RoleUser) + .FirstOrDefaultAsync(u => u.RefreshTokens.Any(r=>r.Token ==refreshToken), cancellationToken); + + if (user == null) + { + return OperationResult.Failure("کاربر یافت نشد", ErrorType.NotFound); + } + + // بررسی فعال بودن کاربر + if (!user.IsActive) + { + return OperationResult.Failure("حساب کاربری غیرفعال است", ErrorType.Unauthorized); + } + + // پیدا کردن Refresh Token فعال + var activeRefreshToken = user.RefreshTokens + .FirstOrDefault(rt => rt.Token == refreshToken && rt.IsActive); + + if (activeRefreshToken == null) + { + return OperationResult.Failure( + "نشست شما منقضی شده است. لطفاً دوباره وارد شوید", + ErrorType.Unauthorized); + } + + if (!activeRefreshToken.IsActive|| activeRefreshToken.IsRevoked||activeRefreshToken.IsExpired) + { + return OperationResult.Failure( + "نشست شما منقضی شده است. لطفاً دوباره وارد شوید", + ErrorType.Unauthorized); + } + + // تولید Access Token جدید با استفاده از AuthHelper + var roles = user.RoleUser.Select(r => r.RoleId.ToString()).ToList(); + var newAccessToken = _authHelper.GenerateAccessToken( + user.Id, + user.UserName, + user.FullName, + user.AccountId, + roles); + + var response = new AccessTokenResponse + { + AccessToken = newAccessToken, + ExpiresAt = DateTime.UtcNow.AddMinutes(30), + UserId = user.Id, + FullName = user.FullName, + UserName = user.UserName + }; + + return OperationResult.Success(response); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs new file mode 100644 index 00000000..7c9c6bda --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs @@ -0,0 +1,11 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.SignOutUser; + +/// +/// دستور خروج کاربر از سیستم +/// +public record SignOutUserCommand(string RefreshToken) : IBaseCommand; + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs new file mode 100644 index 00000000..92c69fcf --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs @@ -0,0 +1,68 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.SignOutUser; + +/// +/// Handler برای خروج کاربر از سیستم +/// +public class SignOutUserCommandHandler : IBaseCommandHandler +{ + private readonly IAuthHelper _authHelper; + private readonly IProgramManagerDbContext _context; + private readonly IUnitOfWork _unitOfWork; + + public SignOutUserCommandHandler( + IAuthHelper _authHelper, + IProgramManagerDbContext context, + IUnitOfWork unitOfWork) + { + this._authHelper = _authHelper; + _context = context; + _unitOfWork = unitOfWork; + } + + public async Task Handle(SignOutUserCommand request, CancellationToken cancellationToken) + { + // دریافت UserId از Claims با استفاده از AuthHelper + var userId = _authHelper.GetCurrentUserId(); + + if (!userId.HasValue) + { + return OperationResult.Failure("کاربر احراز هویت نشده است", ErrorType.Unauthorized); + } + + if (string.IsNullOrEmpty(request.RefreshToken)) + { + return OperationResult.Failure("توکن تازه‌سازی یافت نشد", ErrorType.BadRequest); + } + + // یافتن کاربر + var user = await _context.Users + .Include(u => u.RefreshTokens) + .FirstOrDefaultAsync(u => u.Id == userId.Value, cancellationToken); + + if (user == null) + { + return OperationResult.Failure("کاربر یافت نشد", ErrorType.NotFound); + } + + try + { + // لغو Refresh Token + user.RevokeRefreshToken(request.RefreshToken); + await _unitOfWork.SaveChangesAsync(cancellationToken); + _authHelper.SignOut(); + + return OperationResult.Success(); + } + catch (InvalidOperationException ex) + { + return OperationResult.Failure(ex.Message, ErrorType.BadRequest); + } + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs new file mode 100644 index 00000000..0c6d5a33 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs @@ -0,0 +1,10 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.SsoLogin; + +/// +/// دستور ورود از طریق SSO با استفاده از توکن JWT +/// +public record SsoLoginCommand(string Token) : IBaseCommand; + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs new file mode 100644 index 00000000..3e638729 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs @@ -0,0 +1,115 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Users.Commands.SsoLogin; + +/// +/// Handler برای ورود از طریق SSO با استفاده از JWT Token +/// +public class SsoLoginCommandHandler : IRequestHandler> +{ + private readonly IUserRepository _userRepository; + private readonly IUserRefreshTokenRepository _refreshTokenRepository; + private readonly IAuthHelper _authHelper; + private readonly IUnitOfWork _unitOfWork; + + public SsoLoginCommandHandler( + IUserRepository userRepository, + IAuthHelper authHelper, + IUnitOfWork unitOfWork, + IUserRefreshTokenRepository refreshTokenRepository) + { + _userRepository = userRepository; + _authHelper = authHelper; + _unitOfWork = unitOfWork; + _refreshTokenRepository = refreshTokenRepository; + } + + public async Task> Handle(SsoLoginCommand request, CancellationToken cancellationToken) + { + // اعتبارسنجی + if (string.IsNullOrWhiteSpace(request.Token)) + { + return OperationResult.Failure("توکن SSO معتبر نیست", ErrorType.BadRequest); + } + + // اعتبارسنجی توکن و استخراج Claims + var principal = _authHelper.ValidateToken(request.Token); + if (principal == null) + { + return OperationResult.Failure("توکن SSO نامعتبر یا منقضی شده است", ErrorType.Unauthorized); + } + + // استخراج AccountId از Claims + var accountIdClaim = principal.FindFirst("AccountId")?.Value; + if (string.IsNullOrEmpty(accountIdClaim) || !long.TryParse(accountIdClaim, out var accountId)) + { + return OperationResult.Failure("AccountId در توکن یافت نشد", ErrorType.BadRequest); + } + + // یافتن کاربر بر اساس AccountId + var user = await _userRepository.GetByGozareshgirAccountId(accountId); + + if (user == null) + { + return OperationResult.Failure("کاربر با AccountId مشخص شده یافت نشد", ErrorType.NotFound); + } + + // بررسی فعال بودن کاربر + if (!user.IsActive) + { + return OperationResult.Failure("حساب کاربری غیرفعال است", ErrorType.Unauthorized); + } + + // بارگذاری نقش‌های کاربر + user = await _userRepository.GetUserWithRolesByIdAsync(user.Id, cancellationToken); + if (user == null) + { + return OperationResult.Failure("خطا در بارگذاری اطلاعات کاربر", ErrorType.InternalServerError); + } + + // تولید توکن‌های جدید برای کاربر + var roles = user.RoleUser + .Select(r => r.RoleId.ToString()).ToList(); + + var session = _authHelper.SignIn( + user.Id, + user.UserName, + user.FullName, + user.AccountId ?? 0, + roles); + + // دریافت اطلاعات درخواست + var ipAddress = _authHelper.GetClientIpAddress(); + var userAgent = _authHelper.GetUserAgent(); + + // ذخیره Refresh Token در دیتابیس + var refreshTokenEntity = new UserRefreshToken( + user.Id, + session.RefreshToken, + session.RefreshTokenExpiration, + ipAddress, + userAgent); + + await _refreshTokenRepository.CreateAsync(refreshTokenEntity); + await _unitOfWork.SaveChangesAsync(cancellationToken); + + // ساخت پاسخ + var response = new LoginResponse + { + AccessToken = session.AccessToken, + ExpiresAt = session.AccessTokenExpiration, + UserId = user.Id, + FullName = user.FullName, + UserName = user.UserName, + Roles = user.RoleUser.Select(r => r.RoleId).ToList() + }; + + return OperationResult.Success(response); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs new file mode 100644 index 00000000..2d79108e --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs @@ -0,0 +1,124 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser; + +public class GetSingleUserQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetSingleUserQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetSingleUserQuery request, CancellationToken cancellationToken) + { + + if (!string.IsNullOrWhiteSpace(request.accountId)) + { + long accountId = 0; + try + { + accountId = Convert.ToInt64(request.accountId); + } + catch (Exception e) + { + return (OperationResult)OperationResult.Failure("فقط عدد وارد کنید"); + } + + + if (accountId > 0) + { + var user = await _context.Users + .FirstOrDefaultAsync(x => x.AccountId == accountId); + + + if(user != null) + { + List roles = user.RoleUser.Select(x => x.RoleId).ToList(); + var response = new GetSingleUserResponse + { + FullName = user.FullName, + UserName = user.UserName, + ProfilePhotoPath = user.ProfilePhotoPath, + Mobile = user.Mobile, + IsActive = user.IsActive, + AccountId = user.AccountId, + Roles = roles, + RoleListDto = await _context.Roles.Where(x => roles.Contains(x.Id)).Select(x=> new RoleListDto() + { + RoleName = x.RoleName, + RoleId = x.Id, + Permissions = x.Permissions.Select(x=>x.Code).ToList() + }).ToListAsync(), + }; + + return OperationResult.Success(response); + } + else + { + return (OperationResult)OperationResult.NotFound("کاربر یافت نشد"); + } + } + } + + return (OperationResult)OperationResult.Failure("آی دی اکانت گزارشگیر پر نشده است"); + } +} + + +public record GetSingleUserResponse +{ + /// + /// نام و نام خانوادگی + /// + public string FullName { get; set; } + + /// + /// نام کاربری + /// + public string UserName { get; set; } + + + + /// + /// مسیر عکس پروفایل + /// + public string ProfilePhotoPath { get; set; } + + /// + /// شماره موبایل + /// + public string Mobile { get; set; } + + + /// + /// فعال/غیر فعال بودن یوزر + /// + public bool IsActive { get; set; } + + /// + /// آی دی کاربر در گزارشگیر + /// + public long? AccountId { get; set; } + + /// + /// نقش ها + /// + public List Roles { get; set; } + + public List RoleListDto { get; set; } +}; + + +public record RoleListDto +{ + public string RoleName { get; set; } + public long RoleId { get; set; } + public List Permissions { get; set; } + +} + +public record GetSingleUserQuery(string? accountId) : IBaseQuery; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs new file mode 100644 index 00000000..7b45273a --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs @@ -0,0 +1,48 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUserSelectList; + +public class GetUserSelectListQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetUserSelectListQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetUserSelectListQuery request, CancellationToken cancellationToken) + { + + var query = await _context.Users.Select(x => new GetUserSelectListDto() + { + FullName = x.FullName, + Id = x.Id + }).ToListAsync(); + + var response = new GetUserSelectListResponse(query); + + + return OperationResult.Success(response); + } +} + + +public record GetUserSelectListResponse(List? GetUserSelectListDto); + +public record GetUserSelectListDto +{ + /// + /// نام و نام خانوادگی + /// + public string FullName { get; set; } + + /// + /// آی دی کاربر + /// + public long Id { get; set; } +} +public record GetUserSelectListQuery() : IBaseQuery; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs new file mode 100644 index 00000000..9a3e15e8 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs @@ -0,0 +1,5 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + +namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers; + +public record GetUsersQuery(string? FullName, string? UserName, string? Mobile) : IBaseQuery; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs new file mode 100644 index 00000000..cb6467f4 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs @@ -0,0 +1,49 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers; + +public class GetUsersQueryHandler :IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetUsersQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetUsersQuery request, CancellationToken cancellationToken) + { + var query = _context.Users.AsQueryable(); + + //if (request.ParentId != null) + //{ + // query = query.Where(x => x.ParentId == request.ParentId); + //} + + var users = await query + .Select(p => new GetUserDto() + { + + FullName = p.FullName, + Mobile = p.Mobile, + UserName = p.UserName, + AccountId = p.AccountId, + IsActive = p.IsActive, + ProfilePhotoPath = p.ProfilePhotoPath, + + + }) + .ToListAsync(cancellationToken); + + var response = new GetUsersResponse( + users + ); + + return OperationResult.Success(response); + } + + + +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs new file mode 100644 index 00000000..e1cd043c --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs @@ -0,0 +1,46 @@ +namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers; + +public record GetUsersResponse(List User); + +public record GetUserDto +{ + /// + /// نام و نام خانوادگی + /// + public string FullName { get; set; } + + /// + /// نام کاربری + /// + public string UserName { get; set; } + + + + /// + /// مسیر عکس پروفایل + /// + public string ProfilePhotoPath { get; set; } + + /// + /// شماره موبایل + /// + public string Mobile { get; set; } + + + /// + /// فعال/غیر فعال بودن یوزر + /// + public bool IsActive { get; set; } + + /// + /// آی دی کاربر در گزارشگیر + /// + public long? AccountId { get; set; } + + /// + /// نقش ها + /// + public List Roles { get; set; } + +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs new file mode 100644 index 00000000..49e5cdc8 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs @@ -0,0 +1,21 @@ +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.PermissionAgg.Entities; + +public class Permission +{ + public long Id { get; private set; } + public int Code { get; private set; } + public Role Role { get; private set; } + + public Permission(int code) + { + Code = code; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs index 4cfa127e..a17403b0 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -6,14 +6,21 @@ using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Domain._Common; using GozareshgirProgramManager.Domain.CustomerAgg.Repositories; using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; using GozareshgirProgramManager.Domain.SkillAgg.Repositories; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; using GozareshgirProgramManager.Infrastructure.Persistence; using GozareshgirProgramManager.Infrastructure.Persistence.Context; using GozareshgirProgramManager.Infrastructure.Persistence.Repositories; using GozareshgirProgramManager.Infrastructure.Services.Authentication; using MediatR; +using FluentValidation; using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; +using GozareshgirProgramManager.Domain.SkillAgg.Repositories; + using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -48,7 +55,12 @@ public static class DependencyInjection // Unit of Work services.AddScoped(); - + + //Users + services.AddScoped(); + + //Roles + services.AddScoped(); //WorkingHours services.AddScoped(); @@ -71,6 +83,8 @@ public static class DependencyInjection services.AddScoped(); services.AddScoped(); + + services.AddScoped(); // JWT Settings services.Configure(configuration.GetSection("JwtSettings")); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs index 5a8b0fc5..69327586 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs @@ -4,7 +4,10 @@ using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Domain.CustomerAgg; using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.RoleUserAgg; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Entities; using GozareshgirProgramManager.Domain.SkillAgg.Entities; using Microsoft.EntityFrameworkCore; diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs new file mode 100644 index 00000000..42ac6330 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs @@ -0,0 +1,50 @@ +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class RefreshTokenMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("UserRefreshTokens"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.Token) + .HasMaxLength(500) + .IsRequired(); + + builder.Property(x => x.ExpiresAt) + .IsRequired(); + + builder.Property(x => x.RevokedAt) + .IsRequired(false); + + builder.Property(x => x.IpAddress) + .HasMaxLength(50) + .IsRequired(false); + + builder.Property(x => x.UserAgent) + .HasMaxLength(500) + .IsRequired(false); + + builder.Property(x => x.UserId) + .IsRequired(); + + // رابطه با User + builder.HasOne(x => x.User) + .WithMany(u => u.RefreshTokens) + .HasForeignKey(x => x.UserId) + .OnDelete(DeleteBehavior.Cascade); + + // Index برای بهینه‌سازی جستجو + builder.HasIndex(x => x.Token) + .IsUnique(); + + builder.HasIndex(x => x.UserId); + + builder.HasIndex(x => x.ExpiresAt); + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs new file mode 100644 index 00000000..085a3d81 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs @@ -0,0 +1,23 @@ +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class RoleMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("PmRoles"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.RoleName).HasMaxLength(100).IsRequired(); + + builder.OwnsMany(x => x.Permissions, navigationBuilder => + { + navigationBuilder.HasKey(x => x.Id); + navigationBuilder.ToTable("PmRolePermissions"); + navigationBuilder.WithOwner(x => x.Role); + }); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs new file mode 100644 index 00000000..39ca99ac --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs @@ -0,0 +1,34 @@ +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class UserMapping :IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Users"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.FullName).HasMaxLength(100).IsRequired(); + builder.Property(x => x.UserName).HasMaxLength(100).IsRequired(); + builder.Property(x => x.Password).HasMaxLength(1000).IsRequired(); + builder.Property(x => x.ProfilePhotoPath).HasMaxLength(500).IsRequired(false); + builder.Property(x => x.Mobile).HasMaxLength(20).IsRequired(); + builder.Property(x => x.Email).HasMaxLength(150).IsRequired(false); ; + builder.Property(x => x.VerifyCode).HasMaxLength(10).IsRequired(false); + builder.OwnsMany(x => x.RoleUser, navigationBuilder => + { + navigationBuilder.HasKey(x => x.Id); + navigationBuilder.ToTable("RoleUsers"); + navigationBuilder.WithOwner(x => x.User); + }); + + builder.HasMany(x=>x.RefreshTokens) + .WithOne(x=>x.User) + .HasForeignKey(x=>x.UserId) + .OnDelete(DeleteBehavior.Cascade); + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs new file mode 100644 index 00000000..01198c37 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs @@ -0,0 +1,24 @@ +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class RoleRepository : RepositoryBase, IRoleRepository +{ + private readonly ProgramManagerDbContext _context; + public RoleRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public async Task GetByGozareshgirRoleIdAsync(long? gozareshgirRolId) + { + return await _context.Roles.FirstOrDefaultAsync(x => x.GozareshgirRoleId == gozareshgirRolId); + } + + + +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs index d016c134..4af80655 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs @@ -1,22 +1,19 @@ -using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; using GozareshgirProgramManager.Infrastructure.Persistence._Common; using GozareshgirProgramManager.Infrastructure.Persistence.Context; using Microsoft.EntityFrameworkCore; -using Shared.Contracts.Account; namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; public class SalaryPaymentSettingRepository : RepositoryBase, ISalaryPaymentSettingRepository { private readonly ProgramManagerDbContext _context; - private readonly IAccountQueryService _accountQueryService; - - public SalaryPaymentSettingRepository(ProgramManagerDbContext context, IAccountQueryService accountQueryService) : base(context) + public SalaryPaymentSettingRepository(ProgramManagerDbContext context) : base(context) { _context = context; - _accountQueryService = accountQueryService; } @@ -28,36 +25,31 @@ public class SalaryPaymentSettingRepository : RepositoryBase> GetAllSettings(List userIdList) { - // دریافت تنظیمات حقوق - var settings = await _context.SalaryPaymentSettings - .AsNoTracking() - .Where(s => userIdList.Contains(s.AccountId)) + _context.SalaryPaymentSettings.AsNoTracking(); + var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.AccountId)) + .Join(_context.Users.AsNoTracking(), + setting => setting.AccountId, + user => user.Id, + (setting, user) => new { setting, user } + ) + .Select(x => new UserSalarySettingDto + { + UserId = x.user.Id, + HolidayWorking = x.setting!.HolidayWorking, + FullName = x.user.FullName, + MonthlySalary = x.setting.MonthlySalary, + WorkingHoursListDto = x.setting.WorkingHoursList + .Where(wh => wh.IsActiveDay) + .Select(wh => new WorkingHoursListDto() + { + ShiftDuration = wh.ShiftDuration, + PersianDayOfWeek = wh.PersianDayOfWeek + }).ToList() + }) .ToListAsync(); - // دریافت اطلاعات پایه کاربران از ACL - var accountIds = settings.Select(s => s.AccountId).Distinct().ToList(); - var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(accountIds); - var accountDictionary = accounts.ToDictionary(a => a.Id, a => a); + return query; - // ترکیب داده‌ها - var result = settings.Select(setting => new UserSalarySettingDto - { - UserId = setting.AccountId, - HolidayWorking = setting.HolidayWorking, - FullName = accountDictionary.ContainsKey(setting.AccountId) - ? accountDictionary[setting.AccountId].Username - : "Unknown", - MonthlySalary = setting.MonthlySalary, - WorkingHoursListDto = setting.WorkingHoursList - .Where(wh => wh.IsActiveDay) - .Select(wh => new WorkingHoursListDto - { - ShiftDuration = wh.ShiftDuration, - PersianDayOfWeek = wh.PersianDayOfWeek - }).ToList() - }).ToList(); - - return result; } public void RemoveRangeSalarySettings(List removedItems) diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs new file mode 100644 index 00000000..7200e888 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs @@ -0,0 +1,20 @@ +using System.Linq.Expressions; +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class UserRefreshTokenRepository : RepositoryBase, IUserRefreshTokenRepository +{ + private readonly ProgramManagerDbContext _context; + public UserRefreshTokenRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs new file mode 100644 index 00000000..7b83ef6e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs @@ -0,0 +1,87 @@ +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class UserRepository : RepositoryBase, IUserRepository +{ + private readonly ProgramManagerDbContext _context; + public UserRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public Task GetByIdAsync(long id) + { + throw new NotImplementedException(); + } + + public async Task GetByGozareshgirAccountId(long accountId) + { + return await _context.Users.FirstOrDefaultAsync(x => x.AccountId == accountId); + } + + public Task GetByEmailAsync(string email) + { + throw new NotImplementedException(); + } + + public Task GetByMobileAsync(string mobile) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync() + { + throw new NotImplementedException(); + } + + public Task> GetActiveUsersAsync() + { + throw new NotImplementedException(); + } + + public Task AddAsync(User user) + { + throw new NotImplementedException(); + } + + public void Update(User user) + { + throw new NotImplementedException(); + } + + public void Delete(User user) + { + throw new NotImplementedException(); + } + + public Task ExistsAsync(long id) + { + throw new NotImplementedException(); + } + + public Task UsernameExistsAsync(string username) + { + throw new NotImplementedException(); + } + + public Task EmailExistsAsync(string email) + { + throw new NotImplementedException(); + } + + public Task MobileExistsAsync(string mobile) + { + throw new NotImplementedException(); + } + + public async Task GetUserWithRolesByIdAsync(long userId, CancellationToken cancellationToken) + { + return await _context.Users.Include(x => x.RoleUser) + .FirstOrDefaultAsync(x=>x.Id == userId, cancellationToken); + } +} \ No newline at end of file diff --git a/Query.Bootstrapper/QueryBootstrapper.cs b/Query.Bootstrapper/QueryBootstrapper.cs index d6582d18..a4f55718 100644 --- a/Query.Bootstrapper/QueryBootstrapper.cs +++ b/Query.Bootstrapper/QueryBootstrapper.cs @@ -12,5 +12,6 @@ namespace Query.Bootstrapper services.AddTransient(); } + } } diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs new file mode 100644 index 00000000..22e3c173 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs @@ -0,0 +1,141 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Users.Commands.LoginUser; +using GozareshgirProgramManager.Application.Modules.Users.Commands.RefreshUserToken; +using GozareshgirProgramManager.Application.Modules.Users.Commands.SignOutUser; +using GozareshgirProgramManager.Application.Modules.Users.Commands.SsoLogin; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; + +/// +/// کنترلر احراز هویت +/// +public class AuthController : ProgramManagerBaseController +{ + private readonly IAuthHelper _authHelper; + private readonly IMediator _mediator; + + public AuthController(IAuthHelper authHelper, IMediator mediator) + { + _authHelper = authHelper; + _mediator = mediator; + } + + /// + /// ورود به سیستم با شناسه کاربری + /// + /// شناسه کاربر + /// فقط Access Token - Refresh Token در سرور ذخیره می‌شود + [HttpPost("login")] + [AllowAnonymous] + public async Task>> Login([FromBody] LoginByIdRequest request) + { + var command = new LoginUserCommand(request.UserId); + var result = await _mediator.Send(command); + + return result; + } + + /// + /// ورود به سیستم از طریق SSO با استفاده از توکن JWT + /// توکن JWT از query string دریافت می‌شود و Claims آن استخراج می‌شود + /// سپس کاربر بر اساس AccountId موجود در Claims لاگین می‌شود + /// + /// JWT Token از سیستم خارجی + /// Access Token و اطلاعات کاربر + [HttpGet("sso-login")] + [AllowAnonymous] + public async Task>> SsoLogin([FromQuery] string token) + { + if (string.IsNullOrWhiteSpace(token)) + { + return BadRequest(OperationResult.Failure("توکن الزامی است", ErrorType.BadRequest)); + } + + var command = new SsoLoginCommand(token); + var result = await _mediator.Send(command); + + return result; + } + + /// + /// خروج از سیستم + /// + [HttpPost("signout")] + [Authorize] + public new async Task> SignOut() + { + // دریافت Refresh Token از Header با استفاده از AuthHelper + var refreshToken = _authHelper.GetRefreshTokenFromCookie(); + + if (string.IsNullOrEmpty(refreshToken)) + { + return OperationResult.Failure("توکن تازه‌سازی یافت نشد"); + } + + var command = new SignOutUserCommand(refreshToken); + var result = await _mediator.Send(command); + + if (result.IsSuccess) + { + return Ok(result); + } + + return StatusCode(result.ErrorType switch + { + ErrorType.Unauthorized => 401, + ErrorType.BadRequest => 400, + ErrorType.NotFound => 404, + _ => 500 + }, result); + } + + /// + /// تازه‌سازی توکن دسترسی + /// توکن منقضی شده را می‌گیرد و Access Token جدید برمی‌گرداند + /// Refresh Token از دیتابیس خوانده می‌شود و به فرانت داده نمی‌شود + /// + [HttpPost("refresh")] + [AllowAnonymous] + public async Task> RefreshAccessToken() + { + + var refreshTokenCommand = new RefreshUserTokenCommand(); + var result = await _mediator.Send(refreshTokenCommand); + + return result; + } + + /// + /// دریافت اطلاعات کاربر جاری + /// + [HttpGet("current")] + public IActionResult GetCurrentUser() + { + if (!_authHelper.IsAuthenticated()) + { + return Unauthorized(new { message = "کاربر احراز هویت نشده است" }); + } + + return Ok(new + { + userId = _authHelper.GetCurrentUserId(), + fullName= _authHelper.GetCurrentFullName(), + roles = _authHelper.GetCurrentUserRoles() + }); + } +} + +/// +/// درخواست ورود با شناسه کاربری +/// +public class LoginByIdRequest +{ + public long UserId { get; set; } +} + + diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs new file mode 100644 index 00000000..39e7ff7d --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs @@ -0,0 +1,46 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Roles.Commands.CreateRole; +using GozareshgirProgramManager.Application.Modules.Roles.Commands.EditRole; +using GozareshgirProgramManager.Application.Modules.Roles.Queries.GetRoles; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; + +public class RoleController : ProgramManagerBaseController +{ + private readonly IMediator _mediator; + + public RoleController(IMediator mediator) + { + _mediator = mediator; + } + + + [HttpGet] + public async Task>> Get([FromQuery] GetRolesQuery query) + { + var res = await _mediator.Send(query); + return res; + } + + + [HttpPost] + public async Task> Create([FromBody] CreateRoleCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + + + [HttpPost("edit")] + public async Task> Edit([FromBody] EditRoleCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs new file mode 100644 index 00000000..f0f7ada3 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs @@ -0,0 +1,67 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; +using GozareshgirProgramManager.Application.Modules.Users.Commands.EditUser; +using GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser; +using GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers; +using GozareshgirProgramManager.Application.Modules.Users.Queries.GetUserSelectList; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; + +public class UserController : ProgramManagerBaseController +{ + private readonly IMediator _mediator; + + + public UserController(IMediator mediator) + { + _mediator = mediator; + } + + + [HttpGet] + public async Task>> Get([FromQuery] GetUsersQuery query) + { + var res = await _mediator.Send(query); + return res; + } + + + [HttpGet("{accountId}")] + public async Task>> GetUserByAccountId(string accountId) + { + var query = new GetSingleUserQuery(accountId); + var res = await _mediator.Send(query); + + return res; + } + + [HttpGet("GetUserSelectList")] + public async Task>> GetUserSelectList() + { + var query = new GetUserSelectListQuery(); + var res = await _mediator.Send(query); + + return res; + } + + + [HttpPost("create")] + public async Task> Create([FromBody] CreateUserCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + + [HttpPost("edit")] + public async Task> Edit([FromBody] EditUserCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + +} \ No newline at end of file diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 3ac9f4f6..37dc5ecb 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -27,7 +27,7 @@ using Swashbuckle.AspNetCore.SwaggerUI; using AccountManagement.Domain.InternalApiCaller; using FluentValidation; using GozareshgirProgramManager.Application._Bootstrapper; -using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; +using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; using Microsoft.OpenApi; @@ -52,7 +52,7 @@ var connectionStringProgramManager = builder.Configuration.GetConnectionString(" builder.Services.AddProgramManagerApplication(); builder.Services.AddProgramManagerInfrastructure(builder.Configuration); -builder.Services.AddValidatorsFromAssemblyContaining(); +builder.Services.AddValidatorsFromAssemblyContaining(); builder.Services.AddScoped(); #region MongoDb diff --git a/Shared.Contracts/Account/AccountBasicDto.cs b/Shared.Contracts/Account/AccountBasicDto.cs deleted file mode 100644 index 0f97fa61..00000000 --- a/Shared.Contracts/Account/AccountBasicDto.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Shared.Contracts.Account; -/// -/// این DTO هیچ وابستگی به DbContext یا Entity ندارد -/// DTO مینیمال برای انتقال اطلاعات پایه حساب کاربری بین ماژول‌ها -/// -public class AccountBasicDto -{ - public bool IsActive { get; init; } - public string Fullname { get; init; } - public string Username { get; init; } - public long Id { get; init; } -} - - diff --git a/Shared.Contracts/Account/IAccountQueryService.cs b/Shared.Contracts/Account/IAccountQueryService.cs deleted file mode 100644 index 15d52361..00000000 --- a/Shared.Contracts/Account/IAccountQueryService.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Shared.Contracts.Account; - -/// -/// Contract Interface برای دسترسی به اطلاعات پایه کاربران از سایر ماژول‌ها -/// این Interface به عنوان ACL (Anti-Corruption Layer) عمل می‌کند -/// -/// مزایا: -/// - هیچ وابستگی به Implementation ندارد -/// - ماژول‌های دیگر فقط به این Contract دسترسی دارند -/// - امکان تبدیل به Microservice بدون Breaking Change -/// - Testability بالا (Mock کردن آسان) -/// -public interface IAccountQueryService -{ - /// - /// دریافت اطلاعات پایه یک کاربر - /// - Task GetAccountAsync(long accountId); - - /// - /// دریافت اطلاعات پایه لیستی از کاربران (Batch Query برای جلوگیری از N+1) - /// - Task> GetProgramManagerAccountListAsync(List accountIds); -} - diff --git a/Shared.Contracts/Shared.Contracts.csproj b/Shared.Contracts/Shared.Contracts.csproj deleted file mode 100644 index 5fd9bd06..00000000 --- a/Shared.Contracts/Shared.Contracts.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - net10.0 - enable - enable - - - -